diff --git a/changelog/unreleased/SOLR-18188-testsStopUsingApacheHttpClient.yml b/changelog/unreleased/SOLR-18188-testsStopUsingApacheHttpClient.yml new file mode 100644 index 000000000000..8f6c26a349c9 --- /dev/null +++ b/changelog/unreleased/SOLR-18188-testsStopUsingApacheHttpClient.yml @@ -0,0 +1,9 @@ +title: > + Tests updated to NOT use org.apache.solr.client.solrj.apache which is now also removed. + solr-test-framework doesn't use/depend on Apache HttpClient/httpcomponents anymore. +type: other +authors: + - name: David Smiley +links: + - name: SOLR-18188 + url: https://issues.apache.org/jira/browse/SOLR-18188 diff --git a/gradle/testing/randomization.gradle b/gradle/testing/randomization.gradle index 83d71e7e9079..2bf7d2ae9657 100644 --- a/gradle/testing/randomization.gradle +++ b/gradle/testing/randomization.gradle @@ -133,6 +133,7 @@ configure(allprojects.findAll {project -> project.path.startsWith(":solr")}) { testOptions += [ [propName: 'tests.src.home', value: null, description: "See SOLR-14023."], [propName: 'solr.tests.use.numeric.points', value: null, description: "Point implementation to use (true=numerics, false=trie)."], + [propName: 'tests.ssl', value: false, description: "Force SSL on for all tests that support it (respects @SuppressSSL)."], ] } } diff --git a/solr/api/gradle.lockfile b/solr/api/gradle.lockfile index b3671bdd38a7..8642404b5dd4 100644 --- a/solr/api/gradle.lockfile +++ b/solr/api/gradle.lockfile @@ -93,9 +93,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,testRuntimeClasspath org.apache.curator:curator-client:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=jarValidation,testRuntimeClasspath diff --git a/solr/benchmark/gradle.lockfile b/solr/benchmark/gradle.lockfile index 17d788a364b5..d5bd38498272 100644 --- a/solr/benchmark/gradle.lockfile +++ b/solr/benchmark/gradle.lockfile @@ -83,9 +83,6 @@ org.apache.commons:commons-math3:3.6.1=annotationProcessor,compileClasspath,jarV org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,runtimeClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,runtimeClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,runtimeClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,runtimeClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=jarValidation,runtimeClasspath,testRuntimeClasspath diff --git a/solr/core/build.gradle b/solr/core/build.gradle index 5d801a99ece8..e5f0d3034dac 100644 --- a/solr/core/build.gradle +++ b/solr/core/build.gradle @@ -200,7 +200,6 @@ dependencies { testRuntimeOnly(libs.mockito.subclass, { exclude group: "net.bytebuddy", module: "byte-buddy-agent" }) - testImplementation libs.apache.httpcomponents.httpclient testImplementation libs.opentelemetry.sdk.testing } diff --git a/solr/core/gradle.lockfile b/solr/core/gradle.lockfile index 7267ab45b84a..7727bfffc9e8 100644 --- a/solr/core/gradle.lockfile +++ b/solr/core/gradle.lockfile @@ -90,9 +90,6 @@ org.apache.commons:commons-math3:3.6.1=apiHelper,compileClasspath,jarValidation, org.apache.curator:curator-client:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath diff --git a/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java b/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java index ad9660080ca3..7a7f105c0848 100644 --- a/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java +++ b/solr/core/src/test/org/apache/solr/cli/TestSolrCLIRunExample.java @@ -475,7 +475,7 @@ public void testInteractiveSolrCloudExample() throws Exception { // index some docs - to verify all is good for both shards try (CloudSolrClient cloudClient = - new RandomizingCloudHttp2SolrClientBuilder( + new RandomizingCloudSolrClientBuilder( List.of(executor.solrCloudCluster.getZkServer().getZkAddress()), Optional.empty()) .withDefaultCollection(collectionName) .build()) { diff --git a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java index 18e4d92ba4b6..423ffaa03540 100644 --- a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java @@ -938,7 +938,7 @@ private void searchSeveralWays( } else { // new CloudSolrClient (random shardLeadersOnly) - RandomizingCloudSolrClientBuilder builder = new RandomizingCloudSolrClientBuilder(cluster); + var builder = new RandomizingCloudSolrClientBuilder(cluster); boolean useDefaultCollection = random().nextBoolean(); try (CloudSolrClient solrClient = useDefaultCollection diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java index 203d035318eb..295344d57d9c 100644 --- a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java +++ b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java @@ -33,6 +33,7 @@ import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.cloud.Replica; import org.apache.solr.common.cloud.ZkNodeProps; import org.apache.solr.common.cloud.ZkStateReader; import org.apache.solr.common.params.CommonParams; @@ -158,11 +159,25 @@ public void test() throws Exception { .getZkController() .getZkClient() .getCuratorFramework() - .blockUntilConnected(50, TimeUnit.MILLISECONDS); + .blockUntilConnected(30, TimeUnit.SECONDS); indexr("id", docId + 1, t1, "slip this doc in"); - waitForRecoveriesToFinish(false); + // Wait for the session-expired node to fully re-register its replica as ACTIVE. + // waitForRecoveriesToFinish alone is insufficient because it ignores replicas on nodes + // not yet back in live_nodes, which can race with teardown. + String expiredNodeName = cloudJetty.jetty.getNodeName(); + ZkStateReader.from(cloudClient) + .waitForState( + DEFAULT_COLLECTION, + 60, + TimeUnit.SECONDS, + (liveNodes, collectionState) -> + liveNodes.contains(expiredNodeName) + && collectionState.getSlices().stream() + .flatMap(s -> s.getReplicas().stream()) + .filter(r -> liveNodes.contains(r.getNodeName())) + .allMatch(r -> r.getState() == Replica.State.ACTIVE)); checkShardConsistency(SHARD1); checkShardConsistency(SHARD2); @@ -285,7 +300,7 @@ private void bringDownShardIndexSomeDocsAndRecover() throws Exception { // ensure shard is dead expectThrows( - SolrServerException.class, + Exception.class, "This server should be down and this update should have failed", () -> index_specific(deadShard.client.solrClient, id, 999, i1, 107, t1, "specific doc!")); diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java index 758588d74655..16031370fc3b 100644 --- a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java @@ -44,7 +44,7 @@ import org.apache.solr.SolrTestCaseJ4.SuppressSSL; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.CoreAdminRequest.Create; @@ -695,10 +695,9 @@ public void test() throws Exception { // try add commitWithin long before = cloudClient.query(new SolrQuery("*:*")).getResults().getNumFound(); - for (SolrClient client : clients) { + for (var client : clients) { assertEquals( - "unexpected pre-commitWithin document count on node: " - + ((HttpSolrClient) client).getBaseURL(), + "unexpected pre-commitWithin document count on node: " + client.getBaseURL(), before, client.query(new SolrQuery("*:*")).getResults().getNumFound()); } @@ -1040,7 +1039,7 @@ private void testShardParamVariations() throws Exception { private void testStopAndStartCoresInOneInstance() throws Exception { JettySolrRunner jetty = jettys.get(0); - try (final SolrClient httpSolrClient = (HttpSolrClient) jetty.newClient(15000, 60000)) { + try (final var httpSolrClient = jetty.newClient(15000, 60000)) { ThreadPoolExecutor executor = null; try { executor = @@ -1149,9 +1148,9 @@ protected CollectionAdminResponse createCollection( CollectionAdminResponse res = new CollectionAdminResponse(); if (client == null) { - final String baseUrl = ((HttpSolrClient) clients.get(clientIndex)).getBaseURL(); + final String baseUrl = clients.get(clientIndex).getBaseURL(); - try (SolrClient aClient = createNewSolrClient("", baseUrl)) { + try (SolrClient aClient = createNewSolrClient(baseUrl, null)) { res.setResponse(aClient.request(request)); } } else { @@ -1259,7 +1258,7 @@ private void doOptimisticLockingAndUpdating() throws Exception { private void testNumberOfCommitsWithCommitAfterAdd() throws SolrServerException, IOException { log.info("### STARTING testNumberOfCommitsWithCommitAfterAdd"); - long startCommits = getNumCommits((HttpSolrClient) clients.get(0)); + long startCommits = getNumCommits(clients.getFirst()); NamedList result = clients @@ -1270,17 +1269,13 @@ private void testNumberOfCommitsWithCommitAfterAdd() throws SolrServerException, .setCommitWithin(900000) .setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true)); - long endCommits = getNumCommits((HttpSolrClient) clients.get(0)); + long endCommits = getNumCommits(clients.getFirst()); assertEquals(startCommits + 1L, endCommits); } - private Long getNumCommits(HttpSolrClient sourceClient) throws SolrServerException, IOException { - String collection = sourceClient.getDefaultCollection(); - try (SolrClient client = - new HttpSolrClient.Builder(sourceClient.getBaseURL()) - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) - .withSocketTimeout(60000, TimeUnit.MILLISECONDS) - .build()) { + private Long getNumCommits(HttpSolrClient client) throws SolrServerException, IOException { + String collection = client.getDefaultCollection(); + { var req = new MetricsRequest(SolrParams.of("wt", "prometheus")); NamedList resp = client.request(req); @@ -1318,7 +1313,7 @@ private void testANewCollectionInOneInstanceWithManualShardAssignement() throws .setNode(jettys.get(0).getNodeName()) .process(cloudClient); for (String coreName : resp.getCollectionCoresStatus().keySet()) { - collectionClients.add(createNewSolrClient(coreName, jettys.get(0).getBaseUrl().toString())); + collectionClients.add(createNewSolrClient(jettys.get(0).getBaseUrl().toString(), coreName)); } } @@ -1379,11 +1374,7 @@ private void testANewCollectionInOneInstanceWithManualShardAssignement() throws .getLeader("shard1"); // now test that unloading a core gets us a new leader - try (SolrClient unloadClient = - new HttpSolrClient.Builder(jettys.get(0).getBaseUrl().toString()) - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) - .withSocketTimeout(60000, TimeUnit.MILLISECONDS) - .build()) { + try (SolrClient unloadClient = jettys.getFirst().newClient(15000, 60000)) { Unload unloadCmd = new Unload(true); unloadCmd.setCoreName(leader.getCoreName()); @@ -1431,12 +1422,11 @@ public void run() { private void testSearchByCollectionName() throws SolrServerException, IOException { log.info("### STARTING testSearchByCollectionName"); - SolrClient client = clients.get(0); - final String baseUrl = ((HttpSolrClient) client).getBaseURL(); + final String baseUrl = clients.getFirst().getBaseURL(); // the cores each have different names, but if we add the collection name to the url // we should get mapped to the right core - try (SolrClient client1 = createNewSolrClient(oneInstanceCollection, baseUrl)) { + try (SolrClient client1 = createNewSolrClient(baseUrl, oneInstanceCollection)) { SolrQuery query = new SolrQuery("*:*"); long oneDocs = client1.query(query).getResults().getNumFound(); assertEquals(3, oneDocs); @@ -1445,13 +1435,12 @@ private void testSearchByCollectionName() throws SolrServerException, IOExceptio private void testUpdateByCollectionName() throws SolrServerException, IOException { log.info("### STARTING testUpdateByCollectionName"); - SolrClient client = clients.get(0); - final String baseUrl = ((HttpSolrClient) client).getBaseURL(); + final String baseUrl = clients.getFirst().getBaseURL(); // the cores each have different names, but if we add the collection name to the url // we should get mapped to the right core // test hitting an update url - try (SolrClient client1 = createNewSolrClient(oneInstanceCollection, baseUrl)) { + try (SolrClient client1 = createNewSolrClient(baseUrl, oneInstanceCollection)) { client1.commit(); } } @@ -1465,7 +1454,7 @@ private void testANewCollectionInOneInstance() throws Exception { assertEquals(0, response.getStatus()); List collectionClients = new ArrayList<>(); for (String coreName : response.getCollectionCoresStatus().keySet()) { - collectionClients.add(createNewSolrClient(coreName, jettys.get(0).getBaseUrl().toString())); + collectionClients.add(createNewSolrClient(jettys.get(0).getBaseUrl().toString(), coreName)); } SolrClient client1 = collectionClients.get(0); @@ -1539,7 +1528,7 @@ private void createSolrCore( pending.add(completionService.submit(call)); - collectionClients.add(createNewSolrClient(collection + num, baseUrl)); + collectionClients.add(createNewSolrClient(baseUrl, collection + num)); } private void testMultipleCollections() throws Exception { @@ -1661,7 +1650,7 @@ private void createNewCollection(final String collection) throws InterruptedExce return null; }; - collectionClients.add(createNewSolrClient(collection, runner.getBaseUrl().toString())); + collectionClients.add(createNewSolrClient(runner.getBaseUrl().toString(), collection)); pending.add(completionService.submit(call)); while (pending != null && pending.size() > 0) { @@ -1672,35 +1661,6 @@ private void createNewCollection(final String collection) throws InterruptedExce } } - @Override - protected SolrClient createNewSolrClient(String collection, String baseUrl) { - - SolrClient client = getHttpSolrClient(baseUrl, collection); - - return client; - } - - /** - * @param collection the name of a collection or core to set as the "default" on the created - * client. - * @param baseUrl the "base" URL of a Solr node. Should not contain a collection or core - * name. - * @param connectionTimeoutMillis the HTTP connection timeout in milliseconds - * @param socketTimeoutMillis the HTTP socket-read timeout in milliseconds - */ - protected SolrClient createNewSolrClient( - String collection, String baseUrl, int connectionTimeoutMillis, int socketTimeoutMillis) { - - SolrClient client = - new HttpSolrClient.Builder(baseUrl) - .withDefaultCollection(collection) - .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS) - .withSocketTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS) - .build(); - - return client; - } - @Override protected QueryResponse queryRandomShard(ModifiableSolrParams params) throws SolrServerException, IOException { diff --git a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java index b8640c9a3d49..03c2bac7a3d9 100644 --- a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java @@ -23,7 +23,6 @@ import java.util.concurrent.TimeUnit; import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.common.SolrInputDocument; @@ -133,7 +132,7 @@ protected CloudSolrClient createCloudClient(String defaultCollection) { protected CloudSolrClient createCloudClient(String defaultCollection, int socketTimeout) { - return getCloudSolrClient( + return createNewCloudSolrClient( zkServer.getZkAddress(), defaultCollection, random().nextBoolean(), 30000, socketTimeout); } @@ -183,13 +182,7 @@ public void test() throws Exception { if (runFullThrottle) { ftIndexThread = new FullThrottleStoppableIndexingThread( - ((CloudLegacySolrClient) cloudClient).getHttpClient(), - controlClient, - cloudClient, - clients, - "ft1", - true, - this.clientSoTimeout); + controlClient, cloudClient, clients, "ft1", true, this.clientSoTimeout); ftIndexThread.start(); } diff --git a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java index b70939ced427..e80b765af89f 100644 --- a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeWithPullReplicasTest.java @@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit; import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.common.SolrInputDocument; @@ -144,7 +143,7 @@ protected CloudSolrClient createCloudClient(String defaultCollection) { } protected CloudSolrClient createCloudClient(String defaultCollection, int socketTimeout) { - return getCloudSolrClient( + return createNewCloudSolrClient( zkServer.getZkAddress(), defaultCollection, random().nextBoolean(), 30000, socketTimeout); } @@ -217,13 +216,7 @@ public void test() throws Exception { if (runFullThrottle) { ftIndexThread = new FullThrottleStoppableIndexingThread( - ((CloudLegacySolrClient) cloudClient).getHttpClient(), - controlClient, - cloudClient, - clients, - "ft1", - true, - this.clientSoTimeout); + controlClient, cloudClient, clients, "ft1", true, this.clientSoTimeout); ftIndexThread.start(); } diff --git a/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java b/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java index e5c32a3a257b..a14af61f4b5a 100644 --- a/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java @@ -20,10 +20,8 @@ import java.io.IOException; import java.lang.invoke.MethodHandles; import java.util.List; -import java.util.Optional; import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.common.SolrException; @@ -43,6 +41,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +// nocommit fails @Nightly // this test is currently too slow for non-nightly public class ForceLeaderTest extends HttpPartitionTest { public static final String TEST_COLLECTION = "forceleader_lower_terms_collection"; @@ -193,19 +192,11 @@ public void testReplicasInLowerTerms() throws Exception { } } - /** - * For this test, we need a cloudClient that is not randomized since we need to NEVER send the - * updates only to the leader. The way the RandomizingCloudSolrClientBuilder works, you can't - * avoid its internal decision-making process to sometimes send updates only to leaders. We - * override the definition of this class in AbstractFullDistribZkTestBase to make sure we always - * use DEFAULT_COLLECTION defined in ForceLeaderTest. - */ @Override protected CloudSolrClient createCloudClient(String defaultCollection) { - CloudLegacySolrClient.Builder builder = - new CloudLegacySolrClient.Builder(List.of(zkServer.getZkAddress()), Optional.empty()); - builder.withDefaultCollection(TEST_COLLECTION); - return builder.withConnectionTimeout(30000).withSocketTimeout(120000).build(); + boolean shardLeadersOnly = false; // this test requires we use any replica + return createNewCloudSolrClient( + zkServer.getZkHost(), TEST_COLLECTION, shardLeadersOnly, 30_000, 120_000); } private void putNonLeadersIntoLowerTerm( @@ -321,11 +312,8 @@ private void doForceLeader(String collectionName, String shard) CollectionAdminRequest.ForceLeader forceLeader = CollectionAdminRequest.forceLeaderElection(collectionName, shard); - try (CloudSolrClient cloudClient = - new CloudLegacySolrClient.Builder(List.of(zkServer.getZkAddress()), Optional.empty()) - .withConnectionTimeout(3000) - .withSocketTimeout(60000) - .build()) { + try (var cloudClient = + createNewCloudSolrClient(zkServer.getZkHost(), null, true, 3_000, 60_000)) { cloudClient.request(forceLeader); } } diff --git a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java index d0d10fda0297..cb5bee468783 100644 --- a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java @@ -29,8 +29,8 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.ConcurrentUpdateSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.jetty.ConcurrentUpdateJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.UpdateRequest; @@ -816,8 +816,9 @@ public void testConcurrentIndexing() throws Exception { final int numDocs = atLeast(50); final JettySolrRunner nodeToUpdate = cluster.getRandomJetty(random()); - try (ConcurrentUpdateSolrClient indexClient = - new ConcurrentUpdateSolrClient.Builder(nodeToUpdate.getProxyBaseUrl().toString()) + try (var indexClient = + new ConcurrentUpdateJettySolrClient.Builder( + nodeToUpdate.getProxyBaseUrl().toString(), nodeToUpdate.getSolrClient(), false) .withDefaultCollection(collectionName) .withQueueSize(10) .withThreadCount(2) diff --git a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java index 3f1e3c19c1b9..76f41dd0e1cd 100644 --- a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java @@ -36,7 +36,6 @@ import org.apache.solr.SolrTestCaseJ4.SuppressSSL; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.common.SolrException; @@ -521,10 +520,7 @@ protected SolrClient getHttpSolrClient(Replica replica, String collection) { // Send doc directly to a server (without going through proxy) protected int sendDoc(String collectionName, int docId, JettySolrRunner leaderJetty) throws IOException, SolrServerException { - try (SolrClient solrClient = - new HttpSolrClient.Builder(leaderJetty.getBaseUrl().toString()).build()) { - return sendDoc(docId, solrClient, collectionName); - } + return sendDoc(docId, leaderJetty.getSolrClient(), collectionName); } protected int sendDoc(String collectionName, int docId) throws Exception { diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionContextKeyTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionContextKeyTest.java index 7591dde5362c..9b1faef7fe74 100644 --- a/solr/core/src/test/org/apache/solr/cloud/LeaderElectionContextKeyTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/LeaderElectionContextKeyTest.java @@ -23,7 +23,6 @@ import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.CoreAdminRequest; import org.apache.solr.common.cloud.ClusterState; @@ -92,37 +91,32 @@ public void test() Replica replica = clusterState.getCollection(TEST_COLLECTION_1).getLeader(shard); assertNotNull(replica); - try (SolrClient shardLeaderClient = - new HttpSolrClient.Builder(replica.get("base_url").toString()).build()) { - assertEquals( - 1L, getElectionNodes(TEST_COLLECTION_1, shard, stateReader.getZkClient()).size()); - List collection2Shard1Nodes = - getElectionNodes(TEST_COLLECTION_2, "shard1", stateReader.getZkClient()); - List collection2Shard2Nodes = - getElectionNodes(TEST_COLLECTION_2, "shard2", stateReader.getZkClient()); - CoreAdminRequest.unloadCore(replica.getCoreName(), shardLeaderClient); - // Waiting for leader election being kicked off - long timeout = System.nanoTime() + TimeUnit.NANOSECONDS.convert(60, TimeUnit.SECONDS); - boolean found = false; - while (System.nanoTime() < timeout) { - try { - found = getElectionNodes(TEST_COLLECTION_1, shard, stateReader.getZkClient()).size() == 0; - break; - } catch (KeeperException.NoNodeException nne) { - // ignore - } + SolrClient shardLeaderClient = cluster.getReplicaJetty(replica).getSolrClient(); + assertEquals(1L, getElectionNodes(TEST_COLLECTION_1, shard, stateReader.getZkClient()).size()); + List collection2Shard1Nodes = + getElectionNodes(TEST_COLLECTION_2, "shard1", stateReader.getZkClient()); + List collection2Shard2Nodes = + getElectionNodes(TEST_COLLECTION_2, "shard2", stateReader.getZkClient()); + CoreAdminRequest.unloadCore(replica.getCoreName(), shardLeaderClient); + // Waiting for leader election being kicked off + long timeout = System.nanoTime() + TimeUnit.NANOSECONDS.convert(60, TimeUnit.SECONDS); + boolean found = false; + while (System.nanoTime() < timeout) { + try { + found = getElectionNodes(TEST_COLLECTION_1, shard, stateReader.getZkClient()).size() == 0; + break; + } catch (KeeperException.NoNodeException nne) { + // ignore } - assertTrue(found); - // There are no leader election was kicked off on testCollection2 - assertThat( - collection2Shard1Nodes, - CoreMatchers.is( - getElectionNodes(TEST_COLLECTION_2, "shard1", stateReader.getZkClient()))); - assertThat( - collection2Shard2Nodes, - CoreMatchers.is( - getElectionNodes(TEST_COLLECTION_2, "shard2", stateReader.getZkClient()))); } + assertTrue(found); + // There are no leader election was kicked off on testCollection2 + assertThat( + collection2Shard1Nodes, + CoreMatchers.is(getElectionNodes(TEST_COLLECTION_2, "shard1", stateReader.getZkClient()))); + assertThat( + collection2Shard2Nodes, + CoreMatchers.is(getElectionNodes(TEST_COLLECTION_2, "shard2", stateReader.getZkClient()))); } private List getElectionNodes(String collection, String shard, SolrZkClient client) diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderVoteWaitTimeoutTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderVoteWaitTimeoutTest.java index 4deca8cebd5d..d00190cfe531 100644 --- a/solr/core/src/test/org/apache/solr/cloud/LeaderVoteWaitTimeoutTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/LeaderVoteWaitTimeoutTest.java @@ -31,7 +31,6 @@ import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrRequest.SolrRequestType; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.common.SolrInputDocument; @@ -291,48 +290,47 @@ public void testMostInSyncReplicasCanWinElection() throws Exception { private void addDoc(String collection, int docId, JettySolrRunner solrRunner) throws IOException, SolrServerException { - try (SolrClient solrClient = - new HttpSolrClient.Builder(solrRunner.getBaseUrl().toString()).build()) { - solrClient.add(collection, new SolrInputDocument("id", String.valueOf(docId))); - solrClient.commit(collection); - } + var solrClient = solrRunner.getSolrClient(); + solrClient.add(collection, new SolrInputDocument("id", String.valueOf(docId))); + solrClient.commit(collection); } private void assertDocsExistInAllReplicas( List notLeaders, String testCollectionName, int firstDocId, int lastDocId) throws Exception { Replica leader = cluster.getZkStateReader().getLeaderRetry(testCollectionName, "shard1", 10000); - SolrClient leaderSolr = getSolrClient(leader, testCollectionName); + SolrClient leaderSolr = getJettyForReplica(leader).getSolrClient(); List replicas = new ArrayList<>(notLeaders.size()); for (Replica r : notLeaders) { - replicas.add(getSolrClient(r, testCollectionName)); + replicas.add(getJettyForReplica(r).getSolrClient()); } - try { - for (int d = firstDocId; d <= lastDocId; d++) { - String docId = String.valueOf(d); - assertDocExists(leaderSolr, docId); - for (SolrClient replicaSolr : replicas) { - assertDocExists(replicaSolr, docId); - } - } - } finally { - if (leaderSolr != null) { - leaderSolr.close(); - } + for (int d = firstDocId; d <= lastDocId; d++) { + String docId = String.valueOf(d); + assertDocExists(leaderSolr, testCollectionName, docId); for (SolrClient replicaSolr : replicas) { - replicaSolr.close(); + assertDocExists(replicaSolr, testCollectionName, docId); } } } - private void assertDocExists(SolrClient solr, String docId) throws Exception { - NamedList rsp = realTimeGetDocId(solr, docId); + private JettySolrRunner getJettyForReplica(Replica replica) { + return cluster.getJettySolrRunners().stream() + .filter(j -> j.getNodeName().equals(replica.getNodeName())) + .findFirst() + .orElseThrow( + () -> + new IllegalArgumentException( + "Cannot find Jetty for replica node: " + replica.getNodeName())); + } + + private void assertDocExists(SolrClient solr, String collection, String docId) throws Exception { + NamedList rsp = realTimeGetDocId(solr, collection, docId); String match = JSONTestUtil.matchObj("/id", rsp.get("doc"), docId); assertNull("Doc with id=" + docId + " not found due to: " + match + "; rsp=" + rsp, match); } - private NamedList realTimeGetDocId(SolrClient solr, String docId) + private NamedList realTimeGetDocId(SolrClient solr, String collection, String docId) throws SolrServerException, IOException { return solr.request( new GenericSolrRequest( @@ -340,10 +338,7 @@ private NamedList realTimeGetDocId(SolrClient solr, String docId) "/get", SolrRequestType.QUERY, params("id", docId, "distrib", "false")) - .setRequiresCollection(true)); - } - - protected SolrClient getSolrClient(Replica replica, String coll) { - return getHttpSolrClient(replica.getBaseUrl(), coll); + .setRequiresCollection(true), + collection); } } diff --git a/solr/core/src/test/org/apache/solr/cloud/MultiThreadedOCPTest.java b/solr/core/src/test/org/apache/solr/cloud/MultiThreadedOCPTest.java index 6a8e56cbb514..38f629245692 100644 --- a/solr/core/src/test/org/apache/solr/cloud/MultiThreadedOCPTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/MultiThreadedOCPTest.java @@ -51,7 +51,7 @@ public MultiThreadedOCPTest() { @Test public void testFillWorkQueue() throws Exception { - try (SolrClient client = createNewSolrClient("", getBaseUrl(jettys.get(0)))) { + try (SolrClient client = createNewSolrClient(getBaseUrl(jettys.get(0)), null)) { // This test does not make sense when the Collection API execution is distributed. There is no // queue to fill if (!new CollectionAdminRequest.RequestApiDistributedProcessing() @@ -147,7 +147,7 @@ private Long waitForTaskToCompleted(SolrClient client, int requestId) throws Exc @Test public void testParallelCollectionAPICalls() throws IOException, SolrServerException { final int ASYNC_SHIFT = 10000; - try (SolrClient client = createNewSolrClient("", getBaseUrl(jettys.get(0)))) { + try (SolrClient client = createNewSolrClient(getBaseUrl(jettys.get(0)), null)) { for (int i = 1 + ASYNC_SHIFT; i <= NUM_COLLECTIONS + ASYNC_SHIFT; i++) { CollectionAdminRequest.createCollection("ocptest" + i, "conf1", 3, 1) .processAsync(String.valueOf(i), client); @@ -188,7 +188,7 @@ public void testParallelCollectionAPICalls() throws IOException, SolrServerExcep @Test public void testTaskExclusivity() throws Exception, SolrServerException { - try (SolrClient client = createNewSolrClient("", getBaseUrl(jettys.get(0)))) { + try (SolrClient client = createNewSolrClient(getBaseUrl(jettys.get(0)), null)) { Create createCollectionRequest = CollectionAdminRequest.createCollection("ocptest_shardsplit", "conf1", 4, 1); @@ -246,7 +246,7 @@ public void testTaskExclusivity() throws Exception, SolrServerException { @Test public void testDeduplicationOfSubmittedTasks() throws IOException, SolrServerException { - try (SolrClient client = createNewSolrClient("", getBaseUrl(jettys.get(0)))) { + try (SolrClient client = createNewSolrClient(getBaseUrl(jettys.get(0)), null)) { CollectionAdminRequest.createCollection("ocptest_shardsplit2", "conf1", 3, 1).process(client); SplitShard splitShardRequest = @@ -300,7 +300,7 @@ public void run() { } }; indexThread.start(); - try (SolrClient client = createNewSolrClient("", getBaseUrl(jettys.get(0)))) { + try (SolrClient client = createNewSolrClient(getBaseUrl(jettys.get(0)), null)) { SplitShard splitShardRequest = CollectionAdminRequest.splitShard("collection1").setShardName(SHARD1); diff --git a/solr/core/src/test/org/apache/solr/cloud/RecoveryStrategyStressTest.java b/solr/core/src/test/org/apache/solr/cloud/RecoveryStrategyStressTest.java index 2cd0ef45a348..67c143b240fa 100644 --- a/solr/core/src/test/org/apache/solr/cloud/RecoveryStrategyStressTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/RecoveryStrategyStressTest.java @@ -24,10 +24,7 @@ import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; -import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.common.cloud.DocCollection; import org.apache.solr.common.cloud.Replica; @@ -114,15 +111,14 @@ private void assertShardConsistency(Slice shard, boolean expectDocs) throws Exce long[] numCounts = new long[replicas.size()]; int i = 0; for (Replica replica : replicas) { - try (var client = - new HttpSolrClient.Builder(replica.getBaseUrl()) - .withDefaultCollection(replica.getCoreName()) - .withHttpClient(((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient()) - .build()) { - numCounts[i] = - client.query(new SolrQuery("*:*").add("distrib", "false")).getResults().getNumFound(); - i++; - } + numCounts[i] = + cluster + .getReplicaJetty(replica) + .getSolrClient() + .query(replica.getCoreName(), params("q", "*:*", "distrib", "false")) + .getResults() + .getNumFound(); + i++; } for (int j = 1; j < replicas.size(); j++) { if (numCounts[j] != numCounts[j - 1]) diff --git a/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTest.java b/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTest.java index 48d4855c1d20..24383d8d317c 100644 --- a/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTest.java @@ -21,10 +21,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; -import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.common.cloud.DocCollection; import org.apache.solr.common.cloud.Replica; @@ -137,15 +134,13 @@ private void assertShardConsistency(Slice shard, boolean expectDocs) throws Exce long[] numCounts = new long[replicas.size()]; int i = 0; for (Replica replica : replicas) { - try (var client = - new HttpSolrClient.Builder(replica.getBaseUrl()) - .withDefaultCollection(replica.getCoreName()) - .withHttpClient(((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient()) - .build()) { - numCounts[i] = - client.query(new SolrQuery("*:*").add("distrib", "false")).getResults().getNumFound(); - i++; - } + numCounts[i++] = + cluster + .getReplicaJetty(replica) + .getSolrClient() + .query(replica.getCoreName(), params("q", "*:*", "distrib", "false")) + .getResults() + .getNumFound(); } for (int j = 1; j < replicas.size(); j++) { if (numCounts[j] != numCounts[j - 1]) diff --git a/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java b/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java index 479a5c44ba34..111bcaea8b76 100644 --- a/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java +++ b/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java @@ -18,22 +18,17 @@ import static org.apache.solr.client.solrj.response.RequestStatusState.COMPLETED; -import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrResponse; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.jetty.PreemptiveBasicAuthClientCustomizer; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.UpdateRequest; -import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.RequestStatusState; import org.apache.solr.common.cloud.DocCollection; import org.apache.solr.common.cloud.Replica; @@ -66,11 +61,6 @@ private > T withBasicAuth(T req) { return req; } - private QueryResponse queryWithBasicAuth(SolrClient client, SolrQuery q) - throws IOException, SolrServerException { - return withBasicAuth(new QueryRequest(q)).process(client); - } - @Test public void testRecoveryWithAuthEnabled() throws Exception { final String collection = "recoverytestwithauth"; @@ -110,16 +100,13 @@ private void assertShardConsistency(Slice shard, boolean expectDocs) throws Exce long[] numCounts = new long[replicas.size()]; int i = 0; for (Replica replica : replicas) { - try (var client = - new HttpSolrClient.Builder(replica.getBaseUrl()) - .withDefaultCollection(replica.getCoreName()) - .withHttpClient(((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient()) - .build()) { - var q = new SolrQuery("*:*"); - q.add("distrib", "false"); - numCounts[i] = queryWithBasicAuth(client, q).getResults().getNumFound(); - i++; - } + var client = cluster.getReplicaJetty(replica).getSolrClient(); + var q = new SolrQuery("q", "*:*", "distrib", "false"); + numCounts[i++] = + withBasicAuth(new QueryRequest(q)) + .process(client, replica.getCoreName()) + .getResults() + .getNumFound(); } for (int j = 1; j < replicas.size(); j++) { if (numCounts[j] != numCounts[j - 1]) diff --git a/solr/core/src/test/org/apache/solr/cloud/RouteFieldTest.java b/solr/core/src/test/org/apache/solr/cloud/RouteFieldTest.java index 0b6bd761ee5a..fbc789ed2f58 100644 --- a/solr/core/src/test/org/apache/solr/cloud/RouteFieldTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/RouteFieldTest.java @@ -26,7 +26,6 @@ import java.util.Map; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; @@ -174,11 +173,13 @@ private void compareShardDocs(String urlId, String urlRoute) private SolrDocumentList getDocsMatching(String coreUrl, QueryRequest request) throws IOException, SolrServerException { - final var baseUrl = URLUtil.extractBaseUrl(coreUrl); final var coreName = URLUtil.extractCoreFromCoreUrl(coreUrl); - try (SolrClient solrClient = - new HttpSolrClient.Builder(baseUrl).withDefaultCollection(coreName).build()) { - return (SolrDocumentList) solrClient.request(request).get("response"); - } + SolrClient solrClient = + cluster.getJettySolrRunners().stream() + .filter(j -> coreUrl.startsWith(j.getBaseUrl().toString())) + .findFirst() + .orElseThrow() + .getSolrClient(); + return request.process(solrClient, coreName).getResults(); } } diff --git a/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java b/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java index bbdfecf34753..b0e329f0836c 100644 --- a/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java @@ -23,9 +23,8 @@ import java.util.Properties; import org.apache.lucene.tests.util.LuceneTestCase.AwaitsFix; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpClientUtil; -import org.apache.solr.client.solrj.apache.LBHttpSolrClient; +import org.apache.solr.client.solrj.impl.LBSolrClient; +import org.apache.solr.client.solrj.jetty.LBJettySolrClient; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.common.cloud.DocCollection; import org.apache.solr.common.cloud.Replica; @@ -37,7 +36,6 @@ import org.apache.solr.embedded.JettyConfig; import org.apache.solr.embedded.JettySolrRunner; import org.apache.solr.util.SSLTestConfig; -import org.junit.After; import org.junit.Test; /** @@ -48,11 +46,6 @@ @AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/SOLR-12028") // 17-Mar-2018 public class SSLMigrationTest extends AbstractFullDistribZkTestBase { - @After - public void afterTest() { - HttpClientUtil.resetHttpClientBuilder(); // also resets SocketFactoryRegistryProvider - } - @Test public void test() throws Exception { // Migrate from HTTP -> HTTPS -> HTTP @@ -69,8 +62,6 @@ public void testMigrateSSL(SSLTestConfig sslConfig) throws Exception { runner.stop(); } - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); // we reset in After for (int i = 0; i < this.jettys.size(); i++) { JettySolrRunner runner = jettys.get(i); JettyConfig config = @@ -128,12 +119,14 @@ private void setUrlScheme(String value) throws Exception { QueryRequest request = new QueryRequest(params); request.setPath("/admin/collections"); - String[] urls = + LBSolrClient.Endpoint[] urls = getReplicas().stream() .map(r -> r.getStr(ZkStateReader.BASE_URL_PROP)) - .toArray(String[]::new); - // Create new SolrServer to configure new HttpClient w/ SSL config - try (SolrClient client = new LBHttpSolrClient.Builder().withBaseEndpoints(urls).build()) { + .map(LBSolrClient.Endpoint::new) + .toArray(LBSolrClient.Endpoint[]::new); + // Create new HttpClient w/ SSL config + try (var client = + new LBJettySolrClient.Builder(jettys.getFirst().getSolrClient(), urls).build()) { client.request(request); } } diff --git a/solr/core/src/test/org/apache/solr/cloud/ShardRoutingCustomTest.java b/solr/core/src/test/org/apache/solr/cloud/ShardRoutingCustomTest.java index 004d7cc06e80..c101e5331397 100644 --- a/solr/core/src/test/org/apache/solr/cloud/ShardRoutingCustomTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/ShardRoutingCustomTest.java @@ -18,7 +18,6 @@ import java.nio.file.Files; import java.nio.file.Path; -import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.common.cloud.Replica; import org.apache.solr.embedded.JettySolrRunner; @@ -76,8 +75,7 @@ private void doCustomSharding() throws Exception { .process(cloudClient) .isSuccess()); jettys.add(j); - SolrClient client = createNewSolrClient(j.getLocalPort()); - clients.add(client); + clients.add(createNewSolrClient(j.getLocalPort())); waitForActiveReplicaCount(cloudClient, DEFAULT_COLLECTION, 1); diff --git a/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java b/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java index 8f49afba9701..65f2959dd96e 100644 --- a/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java @@ -29,7 +29,7 @@ import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.UpdateRequest; @@ -107,7 +107,7 @@ public void test() throws Exception { // we only set the connect timeout, not so timeout try (SolrClient baseClient = - new HttpSolrClient.Builder(baseUrl) + new HttpJettySolrClient.Builder(baseUrl) .withConnectionTimeout(30000, TimeUnit.MILLISECONDS) .build()) { baseClient.request(request); diff --git a/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java b/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java index 6a90af12d04f..130e288ee960 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java @@ -21,7 +21,7 @@ import jakarta.servlet.http.HttpServletResponse; import java.lang.invoke.MethodHandles; import java.util.Map; -import org.apache.solr.client.solrj.RemoteSolrException; +import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.SolrQuery; @@ -70,9 +70,11 @@ public void testBasics() throws Exception { // Should fail with 401 try { - RemoteSolrException e = - expectThrows(RemoteSolrException.class, this::collectionCreateSearchDeleteTwice); - assertTrue("Should've returned a 401 error", e.getMessage().contains("Error 401")); + SolrServerException e = + expectThrows(SolrServerException.class, this::collectionCreateSearchDeleteTwice); + assertTrue( + "Should've returned a 401 error", + e.getMessage().contains("401") || e.getMessage().contains("Authentication")); } finally { MockAuthenticationPlugin.expectedUsername = null; MockAuthenticationPlugin.expectedPassword = null; diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java index edae061cbb8e..9041d42555d0 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudConsistency.java @@ -32,7 +32,6 @@ import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrRequest.SolrRequestType; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.common.SolrInputDocument; @@ -297,13 +296,13 @@ private void addDocs(String collection, int numDocs, int startId) private void addDoc(String collection, int docId, JettySolrRunner solrRunner) throws IOException, SolrServerException { - try (SolrClient solrClient = - new HttpSolrClient.Builder(solrRunner.getBaseUrl().toString()).build()) { - solrClient.add( - collection, - new SolrInputDocument("id", String.valueOf(docId), "fieldName_s", String.valueOf(docId))); - solrClient.commit(collection); - } + solrRunner + .getSolrClient() + .add( + collection, + new SolrInputDocument( + "id", String.valueOf(docId), "fieldName_s", String.valueOf(docId))); + solrRunner.getSolrClient().commit(collection); } private void assertDocsExistInAllReplicas( diff --git a/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionWithEmptyReplica.java b/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionWithEmptyReplica.java index dccb8aadc578..e9cb371f25a8 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionWithEmptyReplica.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestLeaderElectionWithEmptyReplica.java @@ -22,8 +22,6 @@ import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient.Builder; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.SolrQuery; @@ -116,12 +114,9 @@ private static int assertConsistentReplicas(CloudSolrClient cloudClient, Slice s long numFound = Long.MIN_VALUE; int count = 0; for (Replica replica : shard.getReplicas()) { - SolrClient client = - new Builder(replica.getBaseUrl()) - .withDefaultCollection(replica.getCoreName()) - .withHttpClient(((CloudLegacySolrClient) cloudClient).getHttpClient()) - .build(); - QueryResponse response = client.query(new SolrQuery("q", "*:*", "distrib", "false")); + SolrClient client = cluster.getReplicaJetty(replica).getSolrClient(); + QueryResponse response = + client.query(replica.getCoreName(), params("q", "*:*", "distrib", "false")); // log.info("Found numFound={} on replica: {}", response.getResults().getNumFound(), // replica.getCoreUrl()); if (numFound == Long.MIN_VALUE) { diff --git a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java index 85072d26d329..8fbbe214fe0c 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java @@ -25,9 +25,8 @@ import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpClientUtil; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; @@ -83,14 +82,12 @@ public void before() { // undo the randomization of our super class log.info( "NOTE: This Test ignores the randomized SSL & clientAuth settings selected by base class"); - HttpClientUtil.resetHttpClientBuilder(); // also resets SocketFactoryRegistryProvider HttpJettySolrClient.resetSslContextFactory(); System.clearProperty(SOLR_SSL_ENABLED); } @After public void after() { - HttpClientUtil.resetHttpClientBuilder(); // also resets SocketFactoryRegistryProvider HttpJettySolrClient.resetSslContextFactory(); System.clearProperty(SOLR_SSL_ENABLED); SSLContext.setDefault(DEFAULT_SSL_CONTEXT); @@ -98,8 +95,6 @@ public void after() { public void testNoSsl() throws Exception { final SSLTestConfig sslConfig = new SSLTestConfig(false, false); - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); // must be reset HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); // must be reset System.setProperty(SOLR_SSL_ENABLED, "false"); checkClusterWithNodeReplacement(sslConfig); @@ -110,8 +105,6 @@ public void testNoSslButSillyClientAuth() throws Exception { // ignored, but we test it anyway for completeness of checking the behavior of code that // looks at those options. final SSLTestConfig sslConfig = new SSLTestConfig(false, true); - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); System.setProperty(SOLR_SSL_ENABLED, "false"); checkClusterWithNodeReplacement(sslConfig); @@ -119,8 +112,6 @@ public void testNoSslButSillyClientAuth() throws Exception { public void testSslAndNoClientAuth() throws Exception { final SSLTestConfig sslConfig = new SSLTestConfig(true, false); - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); System.setProperty(SOLR_SSL_ENABLED, "true"); checkClusterWithNodeReplacement(sslConfig); @@ -131,8 +122,6 @@ public void testSslAndClientAuth() throws Exception { final SSLTestConfig sslConfig = new SSLTestConfig(true, true); - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); System.setProperty(SOLR_SSL_ENABLED, "true"); checkClusterWithNodeReplacement(sslConfig); @@ -140,8 +129,6 @@ public void testSslAndClientAuth() throws Exception { public void testSslWithCheckPeerName() throws Exception { final SSLTestConfig sslConfig = new SSLTestConfig(true, false, true); - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); System.setProperty(SOLR_SSL_ENABLED, "true"); checkClusterWithNodeReplacement(sslConfig); @@ -154,7 +141,6 @@ public void testSslWithCheckPeerName() throws Exception { * HttpClientBuilder, new HttpJettySolrClient instances will still be able to talk to our servers. * * @see SSLContext#setDefault - * @see HttpClientUtil#resetHttpClientBuilder * @see #checkClusterWithCollectionCreations */ private void checkClusterWithNodeReplacement(SSLTestConfig sslConfig) throws Exception { @@ -174,8 +160,8 @@ private void checkClusterWithNodeReplacement(SSLTestConfig sslConfig) throws Exc System.setProperty( SolrHttpConstants.SYS_PROP_CHECK_PEER_NAME, Boolean.toString(sslConfig.getCheckPeerName())); - HttpClientUtil.resetHttpClientBuilder(); HttpJettySolrClient.resetSslContextFactory(); + HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); // recheck that we can communicate with all the jetty instances in our cluster checkClusterJettys(cluster, sslConfig); @@ -189,8 +175,6 @@ public void testSslWithInvalidPeerName() throws Exception { // NOTE: first initialize the cluster w/o peer name checks, which means our server will use // certs with a bogus hostname/ip and clients shouldn't care... final SSLTestConfig sslConfig = new SSLTestConfig(true, false, false); - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); System.setProperty(SOLR_SSL_ENABLED, "true"); final JettyConfig config = @@ -203,7 +187,6 @@ public void testSslWithInvalidPeerName() throws Exception { // now initialize a client that still uses the existing SSLContext/Provider, so it will accept // our existing certificate, but *does* care about validating the peer name System.setProperty(SolrHttpConstants.SYS_PROP_CHECK_PEER_NAME, "true"); - HttpClientUtil.resetHttpClientBuilder(); HttpJettySolrClient.resetSslContextFactory(); // and validate we get failures when trying to talk to our cluster... @@ -425,9 +408,8 @@ public static SolrClient getRandomizedHttpSolrClient(String url) { // ... so we are hopefully future proofing against possible changes to // SolrTestCaseJ4.getHttpSolrClient that "optimize" the test client construction in a way that // would prevent us from finding bugs with regular HttpSolrClient instantiation. - // This test fails if you return a HttpJettySolrClient if (random().nextBoolean()) { - return (new HttpSolrClient.Builder(url)).build(); + return HttpSolrClient.builder(url).build(); } // else... return getHttpSolrClient(url); } diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java b/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java index 0423498ba6ab..53c9fe0b3ac2 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestRandomFlRTGCloud.java @@ -30,7 +30,6 @@ import java.util.Random; import java.util.Set; import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; @@ -38,8 +37,8 @@ import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.response.QueryResponse; @@ -52,7 +51,6 @@ import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; -import org.apache.solr.common.util.IOUtils; import org.apache.solr.common.util.NamedList; import org.apache.solr.embedded.JettySolrRunner; import org.apache.solr.response.transform.DocTransformer; @@ -77,9 +75,6 @@ public class TestRandomFlRTGCloud extends SolrCloudTestCase { /** A collection specific client for operations at the cloud level */ private static CloudSolrClient COLLECTION_CLIENT; - /** We have a map of clients, keyed by base URL */ - private static final Map CLIENTS = new ConcurrentHashMap<>(); - /** Always included in fl, so we can check what doc we're looking at */ private static final FlValidator ID_VALIDATOR = new SimpleFieldValueValidator("id"); @@ -167,7 +162,7 @@ public static void createMiniSolrCloudCluster() throws Exception { configureCluster(numNodes).addConfig(configName, configDir).configure(); - COLLECTION_CLIENT = cluster.getSolrClient(COLLECTION_NAME); + COLLECTION_CLIENT = cluster.getSolrClient(COLLECTION_NAME); // FYI is closed automatically CollectionAdminRequest.createCollection(COLLECTION_NAME, configName, numShards, repFactor) .withProperty("config", "solrconfig-tlog.xml") @@ -179,14 +174,7 @@ public static void createMiniSolrCloudCluster() throws Exception { @AfterClass public static void afterClass() throws Exception { - if (null != COLLECTION_CLIENT) { - COLLECTION_CLIENT.close(); - COLLECTION_CLIENT = null; - } - for (SolrClient client : CLIENTS.values()) { - IOUtils.closeQuietly(client); - } - CLIENTS.clear(); + COLLECTION_CLIENT = null; } /** @@ -420,10 +408,6 @@ private String makeXml(String s) { } } - private static SolrClient getSolrClient(final String jettyBaseUrl) { - return new HttpSolrClient.Builder(jettyBaseUrl).withDefaultCollection(COLLECTION_NAME).build(); - } - /** * Does one or more RTG request for the specified docIds with a randomized fl & fq params, * asserting that the returned document (if any) makes sense given the expected SolrInputDocuments @@ -617,9 +601,8 @@ public static SolrClient getRandomClient(Random rand) { // Return the CloudSolrClient, it only uses javabin writerType. return COLLECTION_CLIENT; } else { - JettySolrRunner jetty = jettySolrRunners.get(idx); - String jettyBaseUrl = jetty.getBaseUrl().toString(); - return CLIENTS.computeIfAbsent(jettyBaseUrl, TestRandomFlRTGCloud::getSolrClient); + var solrClient = jettySolrRunners.get(idx).getSolrClient(); + return new CollectionScopedSolrClient(solrClient, COLLECTION_NAME); } } diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java index 218bff726e19..08330e310c2f 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java @@ -29,7 +29,7 @@ import org.apache.solr.BaseDistributedSearchTestCase; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.cloud.overseer.OverseerAction; @@ -107,44 +107,42 @@ private void testRequestTracking() throws Exception { Collection replicas = b1x1.getSlice("shard1").getReplicas(); assertEquals(1, replicas.size()); String baseUrl = replicas.iterator().next().getBaseUrl(); - if (!baseUrl.endsWith("/")) baseUrl += "/"; - try (SolrClient client = - new HttpSolrClient.Builder(baseUrl) - .withDefaultCollection("a1x2") - .withConnectionTimeout(2000, TimeUnit.MILLISECONDS) - .withSocketTimeout(5000, TimeUnit.MILLISECONDS) - .build()) { - - long expectedTotalRequests = 0; - Set uniqueCoreNames = new LinkedHashSet<>(); - - log.info("Making requests to {} a1x2", baseUrl); - while (uniqueCoreNames.size() < cores.size() && expectedTotalRequests < 1000L) { - expectedTotalRequests++; - client.query(new SolrQuery("*:*")); - - double actualTotalRequests = 0; - for (Map.Entry entry : cores.entrySet()) { - final double coreCount = getSelectRequestCount(entry.getValue()); - actualTotalRequests += coreCount; - if (0 < coreCount) { - uniqueCoreNames.add(entry.getKey()); - } + SolrClient client = + jettys.stream() + .filter(j -> baseUrl.equals(j.getBaseUrl().toString())) + .findFirst() + .orElseThrow() + .getSolrClient(); + + long expectedTotalRequests = 0; + Set uniqueCoreNames = new LinkedHashSet<>(); + + log.info("Making requests to {} a1x2", baseUrl); + while (uniqueCoreNames.size() < cores.size() && expectedTotalRequests < 1000L) { + expectedTotalRequests++; + client.query("a1x2", new SolrQuery("*:*")); + + double actualTotalRequests = 0; + for (Map.Entry entry : cores.entrySet()) { + final double coreCount = getSelectRequestCount(entry.getValue()); + actualTotalRequests += coreCount; + if (0 < coreCount) { + uniqueCoreNames.add(entry.getKey()); } - assertEquals( - "Sanity Check: Num Queries So Far Doesn't Match Total????", - expectedTotalRequests, - (long) actualTotalRequests); } - log.info("Total requests: {}", expectedTotalRequests); assertEquals( - "either request randomization code is broken of this test seed is really unlucky, " - + "Gave up waiting for requests to hit every core at least once after " - + expectedTotalRequests - + " requests", - uniqueCoreNames.size(), - cores.size()); + "Sanity Check: Num Queries So Far Doesn't Match Total????", + expectedTotalRequests, + (long) actualTotalRequests); } + log.info("Total requests: {}", expectedTotalRequests); + assertEquals( + "either request randomization code is broken of this test seed is really unlucky, " + + "Gave up waiting for requests to hit every core at least once after " + + expectedTotalRequests + + " requests", + uniqueCoreNames.size(), + cores.size()); } /** Asserts that requests against a collection are only served by a 'active' local replica */ @@ -221,10 +219,10 @@ private void testQueryAgainstDownReplica() throws Exception { String baseUrl = notLeader.getBaseUrl(); log.info("Firing queries against path={} and collection=football", baseUrl); try (SolrClient client = - new HttpSolrClient.Builder(baseUrl) + new HttpJettySolrClient.Builder(baseUrl) .withDefaultCollection("football") .withConnectionTimeout(2000, TimeUnit.MILLISECONDS) - .withSocketTimeout(5000, TimeUnit.MILLISECONDS) + .withIdleTimeout(5000, TimeUnit.MILLISECONDS) .build()) { SolrCore leaderCore = null; diff --git a/solr/core/src/test/org/apache/solr/cloud/TestStressInPlaceUpdates.java b/solr/core/src/test/org/apache/solr/cloud/TestStressInPlaceUpdates.java index 777188e10d8a..9239f4720b54 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestStressInPlaceUpdates.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestStressInPlaceUpdates.java @@ -30,7 +30,6 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.math3.primes.Primes; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.UpdateResponse; @@ -679,9 +678,9 @@ public SolrClient getClientForLeader() throws KeeperException, InterruptedExcept Slice shard1 = clusterState.getCollection(DEFAULT_COLLECTION).getSlice(SHARD1); leader = shard1.getLeader(); - for (SolrClient client : clients) { + for (var client : clients) { String leaderBaseUrl = zkStateReader.getBaseUrlForNodeName(leader.getNodeName()); - if (((HttpSolrClient) client).getBaseURL().startsWith(leaderBaseUrl)) { + if (client.getBaseURL().startsWith(leaderBaseUrl)) { return client; } } diff --git a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java index ce003c19fb72..093470a2bb9d 100644 --- a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java @@ -30,15 +30,13 @@ import org.apache.solr.SolrTestCaseJ4.SuppressSSL; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.CoreAdminRequest.Unload; -import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.cloud.Replica; import org.apache.solr.common.cloud.Slice; import org.apache.solr.common.cloud.ZkStateReader; -import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.ExecutorUtil; import org.apache.solr.common.util.SolrNamedThreadFactory; import org.apache.solr.core.SolrCore; @@ -83,16 +81,6 @@ public void test() throws Exception { testUnloadShardAndCollection(); } - /** - * @param url a Solr node base URL. Should not contain a core or collection name. - */ - private SolrClient newSolrClient(String url) { - return new HttpSolrClient.Builder(url) - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) - .withSocketTimeout(30000, TimeUnit.MILLISECONDS) - .build(); - } - private void checkCoreNamePresenceAndSliceCount( String collectionName, String coreName, boolean shouldBePresent, int expectedSliceCount) throws Exception { @@ -247,21 +235,21 @@ private void testCoreUnloadAndLeaders() throws Exception { Random random = random(); if (random.nextBoolean()) { - try (SolrClient collectionClient = - getHttpSolrClient(leader.getBaseUrl(), leader.getCoreName())) { - // lets try and use the solrj client to index and retrieve a couple - // documents - SolrInputDocument doc1 = - getDoc(id, 6, i1, -600, tlong, 600, t1, "humpty dumpy sat on a wall"); - SolrInputDocument doc2 = - getDoc(id, 7, i1, -600, tlong, 600, t1, "humpty dumpy3 sat on a walls"); - SolrInputDocument doc3 = - getDoc(id, 8, i1, -600, tlong, 600, t1, "humpty dumpy2 sat on a walled"); - collectionClient.add(doc1); - collectionClient.add(doc2); - collectionClient.add(doc3); - collectionClient.commit(); - } + SolrClient collectionClient = + new CollectionScopedSolrClient(getReplicaNodeClient(leader), leader.getCoreName()); + + // lets try and use the solrj client to index and retrieve a couple + // documents + SolrInputDocument doc1 = + getDoc(id, 6, i1, -600, tlong, 600, t1, "humpty dumpy sat on a wall"); + SolrInputDocument doc2 = + getDoc(id, 7, i1, -600, tlong, 600, t1, "humpty dumpy3 sat on a walls"); + SolrInputDocument doc3 = + getDoc(id, 8, i1, -600, tlong, 600, t1, "humpty dumpy2 sat on a walled"); + collectionClient.add(doc1); + collectionClient.add(doc2); + collectionClient.add(doc3); + collectionClient.commit(); } assertTrue( @@ -276,30 +264,22 @@ private void testCoreUnloadAndLeaders() throws Exception { // so that we start with some versions when we reload... TestInjection.skipIndexWriterCommitOnClose = true; - try (SolrClient addClient = - new HttpSolrClient.Builder(jettys.get(2).getBaseUrl().toString()) - .withDefaultCollection("unloadcollection_shard1_replica3") - .withConnectionTimeout(30000, TimeUnit.MILLISECONDS) - .build()) { - + { // add a few docs for (int x = 20; x < 100; x++) { SolrInputDocument doc1 = getDoc(id, x, i1, -600, tlong, 600, t1, "humpty dumpy sat on a wall"); - addClient.add(doc1); + jettys.get(2).getSolrClient().add("unloadcollection_shard1_replica3", doc1); } } // don't commit so they remain in the tran log // collectionClient.commit(); // unload the leader - try (SolrClient collectionClient = newSolrClient(leader.getBaseUrl())) { - + { Unload unloadCmd = new Unload(false); unloadCmd.setCoreName(leader.getCoreName()); - ModifiableSolrParams p = (ModifiableSolrParams) unloadCmd.getParams(); - - collectionClient.request(unloadCmd); + getReplicaNodeClient(leader).request(unloadCmd); } // Thread.currentThread().sleep(500); // printLayout(); @@ -317,19 +297,11 @@ private void testCoreUnloadAndLeaders() throws Exception { // ensure there is a leader zkStateReader.getLeaderRetry("unloadcollection", "shard1", 15000); - try (SolrClient addClient = - new HttpSolrClient.Builder(jettys.get(1).getBaseUrl().toString()) - .withDefaultCollection("unloadcollection_shard1_replica2") - .withConnectionTimeout(30000, TimeUnit.MILLISECONDS) - .withSocketTimeout(90000, TimeUnit.MILLISECONDS) - .build()) { - - // add a few docs while the leader is down - for (int x = 101; x < 200; x++) { - SolrInputDocument doc1 = - getDoc(id, x, i1, -600, tlong, 600, t1, "humpty dumpy sat on a wall"); - addClient.add(doc1); - } + // add a few docs while the leader is down + for (int x = 101; x < 200; x++) { + SolrInputDocument doc1 = + getDoc(id, x, i1, -600, tlong, 600, t1, "humpty dumpy sat on a wall"); + jettys.get(1).getSolrClient().add("unloadcollection_shard1_replica2", doc1); } assertTrue( @@ -343,11 +315,10 @@ private void testCoreUnloadAndLeaders() throws Exception { // unload the leader again leader = getLeaderFromZk("unloadcollection", "shard1"); - try (SolrClient collectionClient = newSolrClient(leader.getBaseUrl())) { - + { Unload unloadCmd = new Unload(false); unloadCmd.setCoreName(leader.getCoreName()); - collectionClient.request(unloadCmd); + getReplicaNodeClient(leader).request(unloadCmd); } tries = 50; while (leader @@ -374,32 +345,27 @@ private void testCoreUnloadAndLeaders() throws Exception { long found1, found3; - try (SolrClient adminClient = - newSolrClient((jettys.get(1).getBaseUrl() + "/unloadcollection_shard1_replica2"))) { - adminClient.commit(); - SolrQuery q = new SolrQuery("*:*"); - q.set("distrib", false); - found1 = adminClient.query(q).getResults().getNumFound(); + var params = params("q", "*:*", "distrib", "false"); + + { + SolrClient adminClient = jettys.get(1).getSolrClient(); + adminClient.commit("unloadcollection_shard1_replica2"); + found1 = + adminClient.query("unloadcollection_shard1_replica2", params).getResults().getNumFound(); } - try (SolrClient adminClient = - new HttpSolrClient.Builder(jettys.get(2).getBaseUrl().toString()) - .withDefaultCollection("unloadcollection_shard1_replica3") - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) - .withSocketTimeout(30000, TimeUnit.MILLISECONDS) - .build()) { - adminClient.commit(); - SolrQuery q = new SolrQuery("*:*"); - q.set("distrib", false); - found3 = adminClient.query(q).getResults().getNumFound(); + { + SolrClient adminClient = jettys.get(2).getSolrClient(); + adminClient.commit("unloadcollection_shard1_replica3"); + found3 = + adminClient.query("unloadcollection_shard1_replica3", params).getResults().getNumFound(); } - try (SolrClient adminClient = - newSolrClient((jettys.get(3).getBaseUrl() + "/unloadcollection_shard1_replica4"))) { - adminClient.commit(); - SolrQuery q = new SolrQuery("*:*"); - q.set("distrib", false); - long found4 = adminClient.query(q).getResults().getNumFound(); + { + SolrClient adminClient = jettys.get(3).getSolrClient(); + adminClient.commit("unloadcollection_shard1_replica4"); + long found4 = + adminClient.query("unloadcollection_shard1_replica4", params).getResults().getNumFound(); // all 3 shards should now have the same number of docs assertEquals(found1, found3); @@ -407,6 +373,14 @@ private void testCoreUnloadAndLeaders() throws Exception { } } + private SolrClient getReplicaNodeClient(Replica replica) { + return jettys.stream() + .filter(j -> j.getBaseUrl().toString().equals(replica.getBaseUrl())) + .findAny() + .orElseThrow() + .getSolrClient(); + } + private void testUnloadLotsOfCores() throws Exception { JettySolrRunner jetty = jettys.get(0); int shards = TEST_NIGHTLY ? 2 : 1; diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/CollectionsAPIAsyncDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/CollectionsAPIAsyncDistributedZkTest.java index 6eae89d164f2..b874181aded5 100644 --- a/solr/core/src/test/org/apache/solr/cloud/api/collections/CollectionsAPIAsyncDistributedZkTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/CollectionsAPIAsyncDistributedZkTest.java @@ -30,7 +30,6 @@ import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.SolrQuery; @@ -234,7 +233,7 @@ public void testAsyncIdRaceCondition() throws Exception { SolrClient[] clients = new SolrClient[cluster.getJettySolrRunners().size()]; int j = 0; for (JettySolrRunner r : cluster.getJettySolrRunners()) { - clients[j++] = new HttpSolrClient.Builder(r.getBaseUrl().toString()).build(); + clients[j++] = r.getSolrClient(); // no need to close } RequestStatusState state = CollectionAdminRequest.createCollection("testAsyncIdRaceCondition", "conf1", 1, 1) @@ -251,51 +250,41 @@ public void testAsyncIdRaceCondition() throws Exception { ExecutorService es = ExecutorUtil.newMDCAwareFixedThreadPool( numThreads, new SolrNamedThreadFactory("testAsyncIdRaceCondition")); - try { - for (int i = 0; i < numThreads; i++) { - es.execute( - new Runnable() { - - @Override - public void run() { - CollectionAdminRequest.Reload reloadCollectionRequest = - CollectionAdminRequest.reloadCollection("testAsyncIdRaceCondition"); - latch.countDown(); - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(); - } - - try { - if (log.isInfoEnabled()) { - log.info("{} - Reloading Collection.", Thread.currentThread().getName()); - } - reloadCollectionRequest.processAsync( - "repeatedId", clients[random().nextInt(clients.length)]); - numSuccess.incrementAndGet(); - } catch (SolrServerException | RemoteSolrException e) { - if (log.isInfoEnabled()) { - log.info("Exception during collection reloading, we were waiting for one: ", e); - } - assertThat( - e.getMessage(), - containsString("Task with the same requestid already exists. (repeatedId)")); - numFailure.incrementAndGet(); - } catch (IOException e) { - throw new RuntimeException(); - } + for (int i = 0; i < numThreads; i++) { + es.execute( + () -> { + CollectionAdminRequest.Reload reloadCollectionRequest = + CollectionAdminRequest.reloadCollection("testAsyncIdRaceCondition"); + latch.countDown(); + try { + latch.await(); + } catch (InterruptedException e) { + throw new RuntimeException(); + } + + try { + if (log.isInfoEnabled()) { + log.info("{} - Reloading Collection.", Thread.currentThread().getName()); } - }); - } - es.shutdown(); - assertTrue(es.awaitTermination(10, TimeUnit.SECONDS)); - assertEquals(1, numSuccess.get()); - assertEquals(numThreads - 1, numFailure.get()); - } finally { - for (SolrClient client : clients) { - client.close(); - } + reloadCollectionRequest.processAsync( + "repeatedId", clients[random().nextInt(clients.length)]); + numSuccess.incrementAndGet(); + } catch (SolrServerException | RemoteSolrException e) { + if (log.isInfoEnabled()) { + log.info("Exception during collection reloading, we were waiting for one: ", e); + } + assertThat( + e.getMessage(), + containsString("Task with the same requestid already exists. (repeatedId)")); + numFailure.incrementAndGet(); + } catch (IOException e) { + throw new RuntimeException(); + } + }); } + es.shutdown(); + assertTrue(es.awaitTermination(10, TimeUnit.SECONDS)); + assertEquals(1, numSuccess.get()); + assertEquals(numThreads - 1, numFailure.get()); } } diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java index 7fdf13328d12..cc26029cb08a 100644 --- a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java @@ -40,9 +40,8 @@ import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.jetty.CloudJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.SolrQuery; @@ -158,7 +157,7 @@ private void doSplitStaticIndexReplication(SolrIndexSplitter.SplitMethod splitMe builder .withDefaultCollection(collectionName) .sendUpdatesOnlyToShardLeaders() - .withHttpClient(((CloudLegacySolrClient) cloudClient).getHttpClient()) + .withHttpClient(((CloudJettySolrClient) cloudClient).getHttpClient()) .build()) { StoppableIndexingThread thread = new StoppableIndexingThread(controlClient, client, "i1", true); @@ -233,19 +232,7 @@ private void doSplitStaticIndexReplication(SolrIndexSplitter.SplitMethod splitMe CollectionAdminRequest.addReplicaToShard(collectionName, SHARD1_0); // use control client because there are fewer chances of it being the node being restarted // this is to avoid flakiness of test because of NoHttpResponseExceptions - String control_collection = - client - .getClusterState() - .getCollection("control_collection") - .getReplicas() - .get(0) - .getBaseUrl(); - try (var control = - new HttpSolrClient.Builder(control_collection) - .withHttpClient(((CloudLegacySolrClient) client).getHttpClient()) - .build()) { - state = addReplica.processAndWait(control, 30); - } + state = addReplica.processAndWait(controlClient, 30); ZkStateReader.from(cloudClient) .waitForState( @@ -306,11 +293,12 @@ private int assertConsistentReplicas(Slice shard) throws SolrServerException, IO int count = 0; for (Replica replica : shard.getReplicas()) { var client = - new HttpSolrClient.Builder(replica.getBaseUrl()) - .withDefaultCollection(replica.getCoreName()) - .withHttpClient(((CloudLegacySolrClient) cloudClient).getHttpClient()) - .build(); - QueryResponse response = client.query(new SolrQuery("q", "*:*", "distrib", "false")); + clients.stream() + .filter(c -> c.getBaseURL().equals(replica.getBaseUrl())) + .findAny() + .orElseThrow(); + QueryResponse response = + client.query(replica.getCoreName(), new SolrQuery("q", "*:*", "distrib", "false")); if (log.isInfoEnabled()) { log.info( "Found numFound={} on replica: {}", @@ -1282,13 +1270,8 @@ protected void splitShard( QueryRequest request = new QueryRequest(params); request.setPath("/admin/collections"); - String baseUrl = shardToJetty.get(SHARD1).get(0).jetty.getBaseUrl().toString(); - - try (SolrClient baseServer = - new HttpSolrClient.Builder(baseUrl) - .withConnectionTimeout(30, TimeUnit.SECONDS) - .withSocketTimeout(5, TimeUnit.MINUTES) - .build()) { + JettySolrRunner jetty = shardToJetty.get(SHARD1).getFirst().jetty; + try (SolrClient baseServer = jetty.newClient(30_000, 300_000)) { NamedList rsp = baseServer.request(request); if (log.isInfoEnabled()) { log.info("Shard split response: {}", Utils.toJSONString(rsp)); diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java index b48ae59b668b..5f93ef717688 100644 --- a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java +++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestRequestStatusCollectionAPI.java @@ -23,11 +23,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.RemoteSolrException; -import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.response.RequestStatusState; import org.apache.solr.cloud.BasicDistributedZkTest; @@ -231,13 +228,6 @@ protected NamedList sendRequest(ModifiableSolrParams params) QueryRequest request = new QueryRequest(params); request.setPath("/admin/collections"); - String baseUrl = shardToJetty.get(SHARD1).get(0).jetty.getBaseUrl().toString(); - - try (SolrClient baseServer = - new HttpSolrClient.Builder(baseUrl) - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) - .build()) { - return baseServer.request(request); - } + return shardToJetty.get(SHARD1).getFirst().jetty.getSolrClient().request(request); } } diff --git a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java index c325a0ffebf8..361d7e07d46d 100644 --- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java +++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java @@ -28,7 +28,6 @@ import java.util.Iterator; import java.util.List; import java.util.Properties; -import java.util.concurrent.TimeUnit; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.IndexSearcher; @@ -40,7 +39,6 @@ import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.embedded.JettyConfig; import org.apache.solr.embedded.JettySolrRunner; import org.junit.After; @@ -74,13 +72,6 @@ private static JettySolrRunner createAndStartJetty(ReplicationTestHelper.SolrIns return jetty; } - private static SolrClient createNewSolrClient(JettySolrRunner jetty) { - return new HttpSolrClient.Builder(jetty.getBaseUrl().toString()) - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) - .withSocketTimeout(60000, TimeUnit.MILLISECONDS) - .build(); - } - @Override @Before public void setUp() throws Exception { @@ -97,7 +88,7 @@ public void setUp() throws Exception { leader.copyConfigFile(CONF_DIR.resolve(configFile).toString(), "solrconfig.xml"); leaderJetty = createAndStartJetty(leader); - leaderClient = createNewSolrClient(leaderJetty); + leaderClient = leaderJetty.getSolrClient(); docsSeed = random().nextLong(); } diff --git a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java index deaaddfac890..a2f79f7f3b1f 100644 --- a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java +++ b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java @@ -23,13 +23,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Properties; -import java.util.concurrent.TimeUnit; import org.apache.lucene.index.IndexFileNames; import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.embedded.JettyConfig; import org.apache.solr.embedded.JettySolrRunner; @@ -59,15 +57,6 @@ private static JettySolrRunner createAndStartJetty(ReplicationTestHelper.SolrIns return jetty; } - private static SolrClient createNewSolrClient(int port) { - - final String baseUrl = buildUrl(port); - return new HttpSolrClient.Builder(baseUrl) - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) - .withSocketTimeout(60000, TimeUnit.MILLISECONDS) - .build(); - } - @Override @Before public void setUp() throws Exception { @@ -79,7 +68,7 @@ public void setUp() throws Exception { leader.copyConfigFile(CONF_DIR.resolve(configFile).toString(), "solrconfig.xml"); leaderJetty = createAndStartJetty(leader); - leaderClient = createNewSolrClient(leaderJetty.getLocalPort()); + leaderClient = leaderJetty.getSolrClient(); docsSeed = random().nextLong(); } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java index db7883a0a1e6..66627c225833 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java @@ -27,7 +27,6 @@ import java.util.Map; import java.util.Properties; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.io.file.PathUtils; import org.apache.lucene.util.Constants; @@ -35,7 +34,6 @@ import org.apache.solr.client.api.model.CoreStatusResponse; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.CoreAdminRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.json.JacksonContentWriter; @@ -315,23 +313,11 @@ public void testDeleteInstanceDir() throws Exception { solrHomeDirectory.toAbsolutePath().toString(), JettyConfig.builder().build()); runner.start(); - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withDefaultCollection("corex") - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { - SolrInputDocument doc = new SolrInputDocument(); - doc.addField("id", "123"); - client.add(doc); - client.commit(); - } + var client = runner.getSolrClient(); + { + client.add("corex", sdoc("id", "123")); + client.commit("corex"); - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false); req.setDeleteInstanceDir(true); req.setCoreName("corex"); @@ -342,11 +328,7 @@ public void testDeleteInstanceDir() throws Exception { // 1> has the property persisted (SOLR-11783) // 2> is deleted after rename properly. - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { + { CoreAdminRequest.renameCore("corerename", "brand_new_core_name", client); Properties props = new Properties(); try (Reader is = Files.newBufferedReader(renamePropFile, StandardCharsets.UTF_8)) { @@ -356,11 +338,7 @@ public void testDeleteInstanceDir() throws Exception { "Name should have been persisted!", "brand_new_core_name", props.getProperty("name")); } - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { + { CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false); req.setDeleteInstanceDir(true); req.setCoreName("brand_new_core_name"); @@ -389,33 +367,18 @@ public void testUnloadForever() throws Exception { solrHomeDirectory.toAbsolutePath().toString(), JettyConfig.builder().build()); runner.start(); - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withDefaultCollection("corex") - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { - SolrInputDocument doc = new SolrInputDocument(); - doc.addField("id", "123"); - client.add(doc); - client.commit(); + var client = runner.getSolrClient(); + { + client.add("corex", sdoc("id", "123")); + client.commit("corex"); } - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withDefaultCollection("corex") - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { - QueryResponse result = client.query(new SolrQuery("id:*")); + { + QueryResponse result = client.query("corex", new SolrQuery("id:*")); assertEquals(1, result.getResults().getNumFound()); } - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { + { CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false); req.setDeleteInstanceDir(false); // random().nextBoolean()); req.setCoreName("corex"); @@ -426,13 +389,8 @@ public void testUnloadForever() throws Exception { expectThrows( RemoteSolrException.class, () -> { - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withDefaultCollection("corex") - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT * 1000, TimeUnit.MILLISECONDS) - .build()) { - client.query(new SolrQuery("id:*")); + try { + runner.getSolrClient().query("corex", new SolrQuery("id:*")); } finally { runner.stop(); } @@ -454,17 +412,10 @@ public void testDeleteInstanceDirAfterCreateFailure() throws Exception { solrHomeDirectory.toAbsolutePath().toString(), JettyConfig.builder().build()); runner.start(); - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withDefaultCollection("corex") - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { - SolrInputDocument doc = new SolrInputDocument(); - doc.addField("id", "123"); - client.add(doc); - client.commit(); - } + SolrInputDocument doc = new SolrInputDocument(); + doc.addField("id", "123"); + runner.getSolrClient().add("corex", doc); + runner.getSolrClient().commit("corex"); Path dataDir = null; try (SolrClient client = getHttpSolrClient(runner.getBaseUrl().toString())) { @@ -481,21 +432,16 @@ public void testDeleteInstanceDirAfterCreateFailure() throws Exception { subHome.resolve("solrconfig.xml"), StandardCopyOption.REPLACE_EXISTING); - try (SolrClient client = - new HttpSolrClient.Builder(runner.getBaseUrl().toString()) - .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .build()) { - // this is expected because we put a bad solrconfig -- ignore - expectThrows(Exception.class, () -> CoreAdminRequest.reloadCore("corex", client)); + // this is expected because we put a bad solrconfig -- ignore + expectThrows( + Exception.class, () -> CoreAdminRequest.reloadCore("corex", runner.getSolrClient())); - CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false); - req.setDeleteDataDir(true); - // important because the data directory is inside the instance directory - req.setDeleteInstanceDir(false); - req.setCoreName("corex"); - req.process(client); - } + CoreAdminRequest.Unload unloadReq = new CoreAdminRequest.Unload(false); + unloadReq.setDeleteDataDir(true); + // important because the data directory is inside the instance directory + unloadReq.setDeleteInstanceDir(false); + unloadReq.setCoreName("corex"); + unloadReq.process(runner.getSolrClient()); runner.stop(); diff --git a/solr/core/src/test/org/apache/solr/handler/admin/ShowFileRequestHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/ShowFileRequestHandlerTest.java index 69f3108ba8a1..31b0f00b79ce 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/ShowFileRequestHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/ShowFileRequestHandlerTest.java @@ -142,6 +142,7 @@ public void testIllegalContentType() throws SolrServerException, IOException { createShowFileRequest(params("file", "managed-schema", "contentType", "not/known")); request.setResponseParser(new InputStreamResponseParser("xml")); NamedList response = client.request(request); + closeResponseStream(response); assertEquals(response.get("responseStatus"), 404); } @@ -152,6 +153,7 @@ public void testAbsoluteFilename() throws SolrServerException, IOException { params("file", "/etc/passwd", "contentType", "text/plain; charset=utf-8")); request.setResponseParser(new InputStreamResponseParser("xml")); NamedList response = client.request(request); + closeResponseStream(response); assertEquals(response.get("responseStatus"), 404); } @@ -162,6 +164,7 @@ public void testEscapeConfDir() throws SolrServerException, IOException { params("file", "../../solr.xml", "contentType", "application/xml; charset=utf-8")); request.setResponseParser(new InputStreamResponseParser("xml")); NamedList response = client.request(request); + closeResponseStream(response); assertEquals(response.get("responseStatus"), 400); } @@ -176,6 +179,7 @@ public void testPathTraversalFilename() throws SolrServerException, IOException "text/plain; charset=utf-8")); request.setResponseParser(new InputStreamResponseParser("xml")); NamedList response = client.request(request); + closeResponseStream(response); assertEquals(response.get("responseStatus"), 400); } @@ -202,4 +206,11 @@ public void testGetSafeContentType() { // Non-known content types are rejected with 400 error expectThrows(SolrException.class, () -> ShowFileRequestHandler.getSafeContentType("foo/bar")); } + + private void closeResponseStream(NamedList response) throws IOException { + InputStream stream = (InputStream) response.get("stream"); + if (stream != null) { + stream.close(); + } + } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperReadAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperReadAPITest.java index ed5bd6353ddb..f4c558de4678 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperReadAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperReadAPITest.java @@ -19,19 +19,16 @@ import static org.hamcrest.Matchers.containsInAnyOrder; -import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.stream.Collectors; import org.apache.commons.io.IOUtils; import org.apache.solr.client.api.model.ZooKeeperStat; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.ZookeeperReadApi; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.SolrException; import org.apache.zookeeper.CreateMode; import org.junit.After; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -42,22 +39,6 @@ public static void setupCluster() throws Exception { configureCluster(1).addConfig("conf", configset("cloud-minimal")).configure(); } - private URL baseUrl; - private String basezk; - private String basezkls; - - @Before - @Override - public void setUp() throws Exception { - super.setUp(); - - baseUrl = cluster.getJettySolrRunner(0).getBaseUrl(); - - String baseUrlV2 = cluster.getJettySolrRunner(0).getBaseURLV2().toString(); - basezk = baseUrlV2 + "/cluster/zookeeper/data"; - basezkls = baseUrlV2 + "/cluster/zookeeper/children"; - } - @After @Override public void tearDown() throws Exception { @@ -66,96 +47,93 @@ public void tearDown() throws Exception { @Test public void testZkread() throws Exception { - try (HttpSolrClient client = new HttpSolrClient.Builder(baseUrl.toString()).build()) { - final var securityJsonRequest = new ZookeeperReadApi.ReadNode("/security.json"); - final var securityJsonResponse = securityJsonRequest.process(client); - assertEquals(200, securityJsonResponse.getHttpStatus()); - try (final var stream = securityJsonResponse.getResponseStream()) { - final var securityJsonContent = IOUtils.toString(stream, StandardCharsets.UTF_8); - assertNotNull(securityJsonContent); - } - - final var configListRequest = new ZookeeperReadApi.ListNodes("/configs"); - final var configListResponse = configListRequest.process(client); - assertEquals( - 6, configListResponse.unknownProperties().get("/configs").get("_default").children); - assertEquals(2, configListResponse.unknownProperties().get("/configs").get("conf").children); - assertEquals(0, configListResponse.stat.version); - - final var configDataRequest = new ZookeeperReadApi.ReadNode("/configs"); - final var configDataResponse = configDataRequest.process(client); - // /configs exists but has no data, so API returns '200 OK' with empty response body - assertEquals(200, configDataResponse.getHttpStatus()); - try (final var stream = configDataResponse.getResponseStream()) { - assertEquals("", IOUtils.toString(stream, StandardCharsets.UTF_8)); - } + var client = cluster.getJettySolrRunner(0).getSolrClient(); + final var securityJsonRequest = new ZookeeperReadApi.ReadNode("/security.json"); + final var securityJsonResponse = securityJsonRequest.process(client); + assertEquals(200, securityJsonResponse.getHttpStatus()); + try (final var stream = securityJsonResponse.getResponseStream()) { + final var securityJsonContent = IOUtils.toString(stream, StandardCharsets.UTF_8); + assertNotNull(securityJsonContent); + } - byte[] bytes = new byte[1024 * 5]; - for (int i = 0; i < bytes.length; i++) { - bytes[i] = (byte) random().nextInt(128); - } - try { - cluster.getZkClient().create("/configs/_default/testdata", bytes, CreateMode.PERSISTENT); + final var configListRequest = new ZookeeperReadApi.ListNodes("/configs"); + final var configListResponse = configListRequest.process(client); + assertEquals( + 6, configListResponse.unknownProperties().get("/configs").get("_default").children); + assertEquals(2, configListResponse.unknownProperties().get("/configs").get("conf").children); + assertEquals(0, configListResponse.stat.version); + + final var configDataRequest = new ZookeeperReadApi.ReadNode("/configs"); + final var configDataResponse = configDataRequest.process(client); + // /configs exists but has no data, so API returns '200 OK' with empty response body + assertEquals(200, configDataResponse.getHttpStatus()); + try (final var stream = configDataResponse.getResponseStream()) { + assertEquals("", IOUtils.toString(stream, StandardCharsets.UTF_8)); + } - final var testDataRequest = new ZookeeperReadApi.ReadNode("/configs/_default/testdata"); - final var testDataResponse = testDataRequest.process(client); - assertEquals(200, testDataResponse.getHttpStatus()); - try (final var stream = testDataResponse.getResponseStream()) { - final var foundContents = stream.readAllBytes(); - for (int i = 0; i < foundContents.length; i++) { - assertEquals(foundContents[i], bytes[i]); - } + byte[] bytes = new byte[1024 * 5]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) random().nextInt(128); + } + try { + cluster.getZkClient().create("/configs/_default/testdata", bytes, CreateMode.PERSISTENT); + + final var testDataRequest = new ZookeeperReadApi.ReadNode("/configs/_default/testdata"); + final var testDataResponse = testDataRequest.process(client); + assertEquals(200, testDataResponse.getHttpStatus()); + try (final var stream = testDataResponse.getResponseStream()) { + final var foundContents = stream.readAllBytes(); + for (int i = 0; i < foundContents.length; i++) { + assertEquals(foundContents[i], bytes[i]); } - } finally { - cluster.getZkClient().delete("/configs/_default/testdata", -1); } + } finally { + cluster.getZkClient().delete("/configs/_default/testdata", -1); } } @Test public void testRequestingDataFromNonexistentNodeReturnsAnError() throws Exception { - try (HttpSolrClient client = new HttpSolrClient.Builder(baseUrl.toString()).build()) { - final var missingNodeReq = new ZookeeperReadApi.ReadNode("/configs/_default/nonexistentnode"); - final var missingNodeResponse = missingNodeReq.process(client); - assertEquals(404, missingNodeResponse.getHttpStatus()); - - final var expected = - expectThrows( - SolrException.class, () -> missingNodeResponse.getResponseStreamIfSuccessful()); - assertEquals(404, expected.code()); - } + var client = cluster.getJettySolrRunner(0).getSolrClient(); + final var missingNodeReq = new ZookeeperReadApi.ReadNode("/configs/_default/nonexistentnode"); + final var missingNodeResponse = missingNodeReq.process(client); + assertEquals(404, missingNodeResponse.getHttpStatus()); + + final var expected = + expectThrows( + SolrException.class, () -> missingNodeResponse.getResponseStreamIfSuccessful()); + assertEquals(404, expected.code()); } @Test public void testCanListChildNodes() throws Exception { - try (HttpSolrClient client = new HttpSolrClient.Builder(baseUrl.toString()).build()) { - final var listDefaultFilesReq = new ZookeeperReadApi.ListNodes("/configs/_default"); - final var listDefaultFilesResponse = listDefaultFilesReq.process(client); - - // At the top level, the response contains a key with the value of the specified zkPath - assertEquals(1, listDefaultFilesResponse.unknownProperties().size()); - assertEquals( - "/configs/_default", - listDefaultFilesResponse.unknownProperties().keySet().stream() - .collect(Collectors.toList()) - .get(0)); - - // Under the specified zkPath is a key for each child, with values being that stat for that - // node. - // The actual stat values vary a good bit so aren't very useful to assert on, so let's just - // make sure all of the expected child nodes were found. - final Map childStatsByPath = - listDefaultFilesResponse.unknownProperties().get("/configs/_default"); - assertEquals(6, childStatsByPath.size()); - assertThat( - childStatsByPath.keySet(), - containsInAnyOrder( - "protwords.txt", - "solrconfig.xml", - "synonyms.txt", - "stopwords.txt", - "managed-schema.xml", - "lang")); - } + var client = cluster.getJettySolrRunner(0).getSolrClient(); + final var listDefaultFilesReq = new ZookeeperReadApi.ListNodes("/configs/_default"); + final var listDefaultFilesResponse = listDefaultFilesReq.process(client); + + // At the top level, the response contains a key with the value of the specified zkPath + assertEquals(1, listDefaultFilesResponse.unknownProperties().size()); + assertEquals( + "/configs/_default", + listDefaultFilesResponse.unknownProperties().keySet().stream() + .collect(Collectors.toList()) + .get(0)); + + // Under the specified zkPath is a key for each child, with values being that stat for that + // node. + // The actual stat values vary a good bit so aren't very useful to assert on, so let's just + // make sure all of the expected child nodes were found. + final Map childStatsByPath = + listDefaultFilesResponse.unknownProperties().get("/configs/_default"); + assertEquals(6, childStatsByPath.size()); + assertThat( + childStatsByPath.keySet(), + containsInAnyOrder( + "protwords.txt", + "solrconfig.xml", + "synonyms.txt", + "stopwords.txt", + "managed-schema.xml", + "lang")); } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerFailureTest.java b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerFailureTest.java index b73f7cfab9d4..6b48759e7340 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerFailureTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerFailureTest.java @@ -18,15 +18,10 @@ package org.apache.solr.handler.admin; import java.io.IOException; -import java.net.URL; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.response.json.JsonMapResponseParser; import org.apache.solr.cloud.SolrCloudTestCase; @@ -42,22 +37,15 @@ public static void setupCluster() throws Exception { cluster.getZkServer().shutdown(); } - /* - Test the monitoring endpoint, when no Zookeeper is answering. There should still be a response - */ + /** + * Test the monitoring endpoint, when no Zookeeper is answering. There should still be a response + */ @Test - public void monitorZookeeperAfterZkShutdown() - throws IOException, - SolrServerException, - InterruptedException, - ExecutionException, - TimeoutException { - URL baseUrl = cluster.getJettySolrRunner(0).getBaseUrl(); - HttpSolrClient solr = new HttpSolrClient.Builder(baseUrl.toString()).build(); + public void monitorZookeeperAfterZkShutdown() throws IOException, SolrServerException { GenericSolrRequest mntrReq = new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/zookeeper/status"); mntrReq.setResponseParser(new JsonMapResponseParser()); - NamedList nl = solr.httpUriRequest(mntrReq).future.get(10000, TimeUnit.MILLISECONDS); + NamedList nl = cluster.getJettySolrRunner(0).getSolrClient().request(mntrReq); assertEquals("zkStatus", nl.getName(1)); @SuppressWarnings({"unchecked"}) @@ -71,6 +59,5 @@ public void monitorZookeeperAfterZkShutdown() @SuppressWarnings({"unchecked"}) Map details = (Map) detailsList.get(0); assertEquals(false, details.get("ok")); - solr.close(); } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerTest.java index a180edacfbe0..8e6735ef9661 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/ZookeeperStatusHandlerTest.java @@ -23,24 +23,17 @@ import static org.mockito.Mockito.when; import java.io.IOException; -import java.net.URL; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.response.json.JsonMapResponseParser; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.SolrException; import org.apache.solr.common.cloud.ZkDynamicConfig; import org.apache.solr.common.util.NamedList; -import org.junit.After; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Answers; @@ -53,35 +46,17 @@ public static void setupCluster() throws Exception { configureCluster(1).addConfig("conf", configset("cloud-minimal")).configure(); } - @Before - @Override - public void setUp() throws Exception { - super.setUp(); - } - - @After - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - /* Test the monitoring endpoint, used in the Cloud => ZkStatus Admin UI screen NOTE: We do not currently test with multiple zookeepers, but the only difference is that there are multiple "details" objects and mode is "ensemble"... */ @Test - public void monitorZookeeper() - throws IOException, - SolrServerException, - InterruptedException, - ExecutionException, - TimeoutException { - URL baseUrl = cluster.getJettySolrRunner(0).getBaseUrl(); - HttpSolrClient solr = new HttpSolrClient.Builder(baseUrl.toString()).build(); + public void monitorZookeeper() throws IOException, SolrServerException { + var solr = cluster.getJettySolrRunner(0).getSolrClient(); GenericSolrRequest mntrReq = new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/zookeeper/status"); mntrReq.setResponseParser(new JsonMapResponseParser()); - NamedList nl = solr.httpUriRequest(mntrReq).future.get(10000, TimeUnit.MILLISECONDS); + NamedList nl = solr.request(mntrReq); assertEquals("zkStatus", nl.getName(1)); @SuppressWarnings({"unchecked"}) @@ -96,7 +71,6 @@ public void monitorZookeeper() Map details = (Map) detailsList.get(0); assertEquals(true, details.get("ok")); assertTrue(Integer.parseInt((String) details.get("zk_znode_count")) > 50); - solr.close(); } @Test diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java index bb9105cad302..44235189cc97 100644 --- a/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java +++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedCombinedQueryComponentTest.java @@ -22,8 +22,6 @@ import java.util.Arrays; import java.util.List; import org.apache.solr.BaseDistributedSearchTestCase; -import org.apache.solr.client.solrj.apache.HttpSolrClient; -import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.CommonParams; @@ -95,14 +93,11 @@ private synchronized void prepareIndexDocs() throws Exception { clients.sort( (client1, client2) -> { try { - if (client2 instanceof HttpJettySolrClient httpClient2 - && client1 instanceof HttpSolrClient httpClient1) - return new URI(httpClient1.getBaseURL()).getPort() - - new URI(httpClient2.getBaseURL()).getPort(); + return new URI(client1.getBaseURL()).getPort() + - new URI(client2.getBaseURL()).getPort(); } catch (URISyntaxException e) { throw new RuntimeException("Unable to get URI from SolrClient", e); } - return 0; }); for (SolrInputDocument doc : docs) { indexDoc(doc); diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java index 2c66147212ea..6a794b8d768b 100644 --- a/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java +++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java @@ -18,8 +18,6 @@ import org.apache.lucene.util.Constants; import org.apache.solr.BaseDistributedSearchTestCase; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.response.JavaBinResponseParser; import org.apache.solr.client.solrj.response.QueryResponse; @@ -165,26 +163,20 @@ public void test() throws Exception { assertEquals("6", document.getFieldValue("id")); assertEquals(true, document.getFieldValue("[elevated]")); - // Force javabin format - final String clientUrl = jettys.get(0).getBaseUrl().toString(); - try (SolrClient client = - new HttpSolrClient.Builder(clientUrl) - .withDefaultCollection("collection1") - .withResponseParser(new JavaBinResponseParser()) - .build(); ) { - SolrQuery solrQuery = - new SolrQuery("XXXX") - .setParam("qt", "/elevate") - .setParam("shards.qt", "/elevate") - .setRows(500) - .setFields("id,[elevated]") - .setParam("enableElevation", "true") - .setParam("forceElevation", "true") - .setParam("elevateIds", "6", "wt", "javabin") - .setSort("id", SolrQuery.ORDER.desc); - setDistributedParams(solrQuery); - response = client.query(solrQuery); - } + var client = jettys.getFirst().getSolrClient(); + assertTrue(client.getParser() instanceof JavaBinResponseParser); + SolrQuery solrQuery = + new SolrQuery("XXXX") + .setParam("qt", "/elevate") + .setParam("shards.qt", "/elevate") + .setRows(500) + .setFields("id,[elevated]") + .setParam("enableElevation", "true") + .setParam("forceElevation", "true") + .setParam("elevateIds", "6") + .setSort("id", SolrQuery.ORDER.desc); + setDistributedParams(solrQuery); + response = client.query(DEFAULT_TEST_CORENAME, solrQuery); assertTrue(response.getResults().getNumFound() > 0); document = response.getResults().get(0); diff --git a/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java index 579c02491a9f..79592e3bc4cd 100644 --- a/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java @@ -22,8 +22,6 @@ import java.util.Iterator; import java.util.List; import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; @@ -158,14 +156,10 @@ public void testZkConnected() throws Exception { Replica replica = getRandomEntry(slice.getReplicas()); JettySolrRunner jetty = miniCluster.getReplicaJetty(replica); // Use the replica's core URL to avoid ZK communication - try (SolrClient client = - new HttpSolrClient.Builder(replica.getBaseUrl()) - .withDefaultCollection(replica.getCoreName()) - .build()) { - jetty.getCoreContainer().getZkController().getZkClient().close(); - rsp = req.process(client); - assertFalse(rsp.getResponseHeader().getBooleanArg("zkConnected")); - } + var client = jetty.getSolrClient(); + jetty.getCoreContainer().getZkController().getZkClient().close(); + rsp = req.process(client, replica.getCoreName()); + assertFalse(rsp.getResponseHeader().getBooleanArg("zkConnected")); } finally { miniCluster.shutdown(); } @@ -209,13 +203,11 @@ public void testRequireZkConnected() throws Exception { JettySolrRunner disconnectedJetty = miniCluster.getReplicaJetty(disconnectedReplica); req = new QueryRequest(params); // TODO Can be removed when SOLR-17314 fixed // Use the replica's core URL to avoid ZK communication - try (SolrClient solrClient = - new HttpSolrClient.Builder(disconnectedReplica.getBaseUrl()) - .withDefaultCollection(disconnectedReplica.getCoreName()) - .build()) { - ignoreException("ZooKeeper is not connected"); - disconnectedJetty.getCoreContainer().getZkController().getZkClient().close(); - req.process(solrClient); + var solrClient = disconnectedJetty.getSolrClient(); + ignoreException("ZooKeeper is not connected"); + disconnectedJetty.getCoreContainer().getZkController().getZkClient().close(); + try { + req.process(solrClient, disconnectedReplica.getCoreName()); fail( "An exception should be thrown when ZooKeeper is not connected and shards.tolerant=requireZkConnected"); } catch (Exception e) { @@ -268,15 +260,13 @@ public void testRequireZkConnectedDistrib() throws Exception { connectedSlice = getRandomEntry(slices); } Replica connectedReplica = connectedSlice.getReplicas().iterator().next(); - try (SolrClient solrClient = - new HttpSolrClient.Builder(connectedReplica.getBaseUrl()) - .withDefaultCollection(connectedReplica.getCoreName()) - .build()) { - ignoreException("ZooKeeper is not connected"); - ignoreException("no active servers hosting shard:"); - JettySolrRunner disconnectedJetty = miniCluster.getReplicaJetty(disconnectedReplica); - disconnectedJetty.getCoreContainer().getZkController().getZkClient().close(); - req.process(solrClient); + var solrClient = miniCluster.getReplicaJetty(connectedReplica).getSolrClient(); + ignoreException("ZooKeeper is not connected"); + ignoreException("no active servers hosting shard:"); + JettySolrRunner disconnectedJetty = miniCluster.getReplicaJetty(disconnectedReplica); + disconnectedJetty.getCoreContainer().getZkController().getZkClient().close(); + try { + req.process(solrClient, connectedReplica.getCoreName()); fail( "An exception should be thrown when ZooKeeper is not connected and shards.tolerant=requireZkConnected"); } catch (Exception e) { diff --git a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java index f229b01ac67a..610b7267cbe3 100644 --- a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java +++ b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java @@ -193,6 +193,8 @@ public void testUnsupportedMetricsFormat() throws Exception { try (SolrClient adminClient = getHttpSolrClient(solrTestRule.getBaseUrl())) { NamedList res = adminClient.request(req); + InputStream stream = (InputStream) res.get("stream"); + if (stream != null) stream.close(); // Unknown wt parameter should return a 400 error assertEquals(400, res.get("responseStatus")); } diff --git a/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchema.java b/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchema.java index 959ea8554cd4..6a584ddb1652 100644 --- a/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchema.java +++ b/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchema.java @@ -22,8 +22,6 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.solr.client.api.model.CoreStatusResponse; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.json.JacksonContentWriter; import org.apache.solr.cloud.AbstractFullDistribZkTestBase; @@ -60,22 +58,20 @@ public void test() throws Exception { request.setPath("/admin/cores"); int which = r.nextInt(clients.size()); - // create a client that does not have the /collection1 as part of the URL. - try (SolrClient rootClient = - new HttpSolrClient.Builder(buildUrl(jettys.get(which).getLocalPort())).build()) { - NamedList namedListResponse = rootClient.request(request); - final var statusByCore = - JacksonContentWriter.DEFAULT_MAPPER.convertValue( - namedListResponse.get("status"), - new TypeReference>() {}); - final String coreName = statusByCore.keySet().stream().findFirst().get(); - final var collectionStatus = statusByCore.get(coreName); - // Make sure the upgrade to managed schema happened - assertEquals( - "Schema resource name differs from expected name", - "managed-schema.xml", - collectionStatus.schema); - } + // use a client that does not have the /collection1 as part of the URL. + var rootClient = jettys.get(which).getSolrClient(); + NamedList namedListResponse = rootClient.request(request); + final var statusByCore = + JacksonContentWriter.DEFAULT_MAPPER.convertValue( + namedListResponse.get("status"), + new TypeReference>() {}); + final String coreName = statusByCore.keySet().stream().findFirst().get(); + final var collectionStatus = statusByCore.get(coreName); + // Make sure the upgrade to managed schema happened + assertEquals( + "Schema resource name differs from expected name", + "managed-schema.xml", + collectionStatus.schema); try (SolrZkClient zkClient = new SolrZkClient.Builder() diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrJ.java b/solr/core/src/test/org/apache/solr/search/TestSolrJ.java deleted file mode 100644 index 4d3c4a3c9d73..000000000000 --- a/solr/core/src/test/org/apache/solr/search/TestSolrJ.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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.search; - -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Random; -import org.apache.solr.SolrTestCaseJ4; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.ConcurrentUpdateSolrClient; -import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.util.RTimer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TestSolrJ extends SolrTestCaseJ4 { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - public void testSolrJ() { - // docs, producers, connections, sleep_time - // main(new String[] {"1000000","4", "1", "0"}); - - // doCommitPerf(); - } - - public static SolrClient client; - public static String idField = "id"; - public static Exception ex; - - public static void main(String[] args) throws Exception { - // String addr = "http://odin.local:80/solr"; - // String addr = "http://odin.local:8983/solr"; - String addr = "http://127.0.0.1:8983/solr"; - - int i = 0; - final int nDocs = Integer.parseInt(args[i++]); - final int nProducers = Integer.parseInt(args[i++]); - final int nConnections = Integer.parseInt(args[i++]); - final int maxSleep = Integer.parseInt(args[i++]); - - ConcurrentUpdateSolrClient concurrentClient = null; - - // server = concurrentClient = new ConcurrentUpdateSolrServer(addr,32,8); - client = - concurrentClient = - new ConcurrentUpdateSolrClient.Builder(addr) - .withQueueSize(64) - .withThreadCount(nConnections) - .build(); - - client.deleteByQuery("*:*"); - client.commit(); - - final RTimer timer = new RTimer(); - - final int docsPerThread = nDocs / nProducers; - - Thread[] threads = new Thread[nProducers]; - - for (int threadNum = 0; threadNum < nProducers; threadNum++) { - final int base = threadNum * docsPerThread; - - threads[threadNum] = - new Thread("add-thread" + i) { - @Override - public void run() { - try { - indexDocs(base, docsPerThread, maxSleep); - } catch (Exception e) { - log.error("###############################CAUGHT EXCEPTION", e); - ex = e; - } - } - }; - threads[threadNum].start(); - } - - // optional: wait for commit? - - for (int threadNum = 0; threadNum < nProducers; threadNum++) { - threads[threadNum].join(); - } - - if (concurrentClient != null) { - concurrentClient.blockUntilFinished(); - } - - double elapsed = timer.getTime(); - System.out.println( - "time=" + elapsed + " throughput=" + (nDocs * 1000 / elapsed) + " Exception=" + ex); - - // should server threads be marked as daemon? - // need a server.close()!!! - } - - @SuppressWarnings({"unchecked"}) - public static SolrInputDocument getDocument(int docnum) { - SolrInputDocument doc = new SolrInputDocument(); - doc.setField(idField, docnum); - doc.setField("cat", Integer.toString(docnum & 0x0f)); - doc.setField("name", "my name is " + Integer.toString(docnum & 0xff)); - doc.setField("foo_t", "now is the time for all good men to come to the aid of their country"); - doc.setField("foo_i", Integer.toString(docnum & 0x0f)); - doc.setField("foo_s", Integer.toString(docnum & 0xff)); - doc.setField("foo_b", Boolean.toString((docnum & 0x01) == 1)); - doc.setField("parent_s", Integer.toString(docnum - 1)); - doc.setField("price", Integer.toString(docnum >> 4)); - - int golden = (int) 2654435761L; - int h = docnum * golden; - int n = (h & 0xff) + 1; - @SuppressWarnings({"rawtypes"}) - List lst = new ArrayList(n); - for (int i = 0; i < n; i++) { - h = (h + i) * golden; - lst.add(h & 0xfff); - } - - doc.setField("num_is", lst); - return doc; - } - - public static void indexDocs(int base, int count, int maxSleep) - throws IOException, SolrServerException { - Random r = new Random(base); - - for (int i = base; i < count + base; i++) { - if ((i & 0xfffff) == 0) { - System.out.print("\n% " + new Date() + "\t" + i + "\t"); - System.out.flush(); - } - - if ((i & 0xffff) == 0) { - System.out.print("."); - System.out.flush(); - } - - SolrInputDocument doc = getDocument(i); - client.add(doc); - - if (maxSleep > 0) { - int sleep = r.nextInt(maxSleep); - try { - Thread.sleep(sleep); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - log.error("interrupted", e); - throw new RuntimeException(e); - } - } - } - } - - public void doCommitPerf() throws Exception { - - try (SolrClient client = getHttpSolrClient("http://127.0.0.1:8983/solr")) { - - final RTimer timer = new RTimer(); - - for (int i = 0; i < 10000; i++) { - SolrInputDocument doc = new SolrInputDocument(); - doc.addField("id", Integer.toString(i % 13)); - client.add(doc); - client.commit(true, true, true); - } - - System.out.println("TIME: " + timer.getTime()); - } - } -} diff --git a/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java b/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java index 8c8193281be4..34e4d6461204 100644 --- a/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java +++ b/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java @@ -87,7 +87,7 @@ public void test() throws Exception { checkSubFacetStats(); } - public static void buildIndexes(final List clients, final String statField) + public static void buildIndexes(final List clients, final String statField) throws Exception { assertEquals("This indexing code assumes exactly 3 shards/clients", 3, clients.size()); diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java index d08280c17bc7..166b9f440c61 100644 --- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java @@ -31,7 +31,6 @@ import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.request.QueryRequest; @@ -136,9 +135,9 @@ public void testBasicAuth() throws Exception { } // avoid bad connection races due to shutdown - final var apacheHttpClient = ((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient(); - apacheHttpClient.getConnectionManager().closeExpiredConnections(); - apacheHttpClient.getConnectionManager().closeIdleConnections(1, TimeUnit.MILLISECONDS); + // var apacheHttpClient = ((CloudLegacySolrClient) cluster.getSolrClient()).getHttpClient(); + // apacheHttpClient.getConnectionManager().closeExpiredConnections(); + // apacheHttpClient.getConnectionManager().closeIdleConnections(1, TimeUnit.MILLISECONDS); RemoteSolrException exp = expectThrows( diff --git a/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java b/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java index 43f627d917a2..87ec473b13a0 100644 --- a/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java +++ b/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java @@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.LongAdder; +import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.SolrClient; @@ -55,6 +56,7 @@ import org.junit.Test; import org.mockito.Mockito; +@LuceneTestCase.AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/SOLR-17810") public class TestRequestRateLimiter extends SolrCloudTestCase { private static final String FIRST_COLLECTION = "c1"; private static final String SECOND_COLLECTION = "c2"; diff --git a/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java b/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java index ff9ff482e53a..4a92852cbdc5 100644 --- a/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java +++ b/solr/core/src/test/org/apache/solr/update/DeleteByIdWithRouterFieldTest.java @@ -24,9 +24,8 @@ import java.util.Set; import java.util.stream.Collectors; import org.apache.lucene.tests.util.TestUtil; -import org.apache.lucene.util.IOUtils; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.impl.CollectionScopedSolrClient; import org.apache.solr.client.solrj.impl.LBSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.UpdateRequest; @@ -77,22 +76,21 @@ public static void setupClusterAndCollection() throws Exception { .process(cluster.getSolrClient()) .isSuccess()); - solrClient = cluster.newSolrClient(COLL); + solrClient = cluster.getSolrClient(COLL); ClusterState clusterState = cluster.getSolrClient().getClusterState(); for (Replica replica : clusterState.getCollection(COLL).getReplicas()) { clients.add( - new HttpSolrClient.Builder(replica.getBaseUrl()) - .withDefaultCollection(replica.getCoreName()) - .build()); + new CollectionScopedSolrClient( + cluster.getReplicaJetty(replica).getSolrClient(), replica.getCoreName())); } } @AfterClass public static void afterClass() throws Exception { - IOUtils.close(clients); + // lifecycle internally managed; we simply GC here clients.clear(); - IOUtils.close(solrClient); + solrClient = null; RVAL_PRE = null; } diff --git a/solr/core/src/test/org/apache/solr/update/SolrCmdDistributorTest.java b/solr/core/src/test/org/apache/solr/update/SolrCmdDistributorTest.java index 59f28f3409ec..aeb413532045 100644 --- a/solr/core/src/test/org/apache/solr/update/SolrCmdDistributorTest.java +++ b/solr/core/src/test/org/apache/solr/update/SolrCmdDistributorTest.java @@ -28,7 +28,7 @@ import org.apache.solr.BaseDistributedSearchTestCase; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.request.LukeRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.UpdateRequest; @@ -159,7 +159,7 @@ public void test() throws Exception { nodeProps = new ZkNodeProps( ZkStateReader.BASE_URL_PROP, - ((HttpSolrClient) controlClient).getBaseURL(), + controlClient.getBaseURL(), ZkStateReader.CORE_NAME_PROP, controlClient.getDefaultCollection()); nodes.add(new StdNode(new ZkCoreNodeProps(nodeProps))); @@ -182,7 +182,7 @@ public void test() throws Exception { numFound = controlClient.query(new SolrQuery("*:*")).getResults().getNumFound(); assertEquals(1, numFound); - client = (HttpSolrClient) clients.get(0); + client = clients.getFirst(); nodeProps = new ZkNodeProps( ZkStateReader.BASE_URL_PROP, @@ -269,17 +269,16 @@ public void test() throws Exception { int cnt = atLeast(303); for (int i = 0; i < cnt; i++) { nodes.clear(); - for (SolrClient c : clients) { + for (HttpSolrClient c : clients) { if (random().nextBoolean()) { continue; } - HttpSolrClient httpClient = (HttpSolrClient) c; nodeProps = new ZkNodeProps( ZkStateReader.BASE_URL_PROP, - httpClient.getBaseURL(), + c.getBaseURL(), ZkStateReader.CORE_NAME_PROP, - httpClient.getDefaultCollection()); + c.getDefaultCollection()); nodes.add(new StdNode(new ZkCoreNodeProps(nodeProps))); } AddUpdateCommand c = new AddUpdateCommand(null); @@ -292,14 +291,13 @@ public void test() throws Exception { nodes.clear(); - for (SolrClient c : clients) { - HttpSolrClient httpClient = (HttpSolrClient) c; + for (HttpSolrClient c : clients) { nodeProps = new ZkNodeProps( ZkStateReader.BASE_URL_PROP, - httpClient.getBaseURL(), + c.getBaseURL(), ZkStateReader.CORE_NAME_PROP, - httpClient.getDefaultCollection()); + c.getDefaultCollection()); nodes.add(new StdNode(new ZkCoreNodeProps(nodeProps))); } @@ -369,7 +367,7 @@ public void newSearcher( } private void testDeletes(boolean dbq, boolean withFailures) throws Exception { - final HttpSolrClient solrclient = (HttpSolrClient) clients.get(0); + final var solrclient = clients.getFirst(); solrclient.commit(true, true); long numFoundBefore = solrclient.query(new SolrQuery("*:*")).getResults().getNumFound(); final MockStreamingSolrClients streamingClients = @@ -437,7 +435,7 @@ public boolean checkRetry(SolrError err) { } private void testMinRfOnRetries(NodeType nodeType) throws Exception { - final HttpSolrClient solrclient = (HttpSolrClient) clients.get(0); + final var solrclient = clients.getFirst(); final MockStreamingSolrClients streamingClients = new MockStreamingSolrClients(updateShardHandler); try (SolrCmdDistributor cmdDistrib = new SolrCmdDistributor(streamingClients, 0)) { @@ -499,7 +497,7 @@ private void testMaxRetries(NodeType nodeType) throws IOException { try (SolrCmdDistributor cmdDistrib = new SolrCmdDistributor(streamingClients, 0)) { streamingClients.setExp(Exp.CONNECT_EXCEPTION); ArrayList nodes = new ArrayList<>(); - final HttpSolrClient solrClient1 = (HttpSolrClient) clients.get(0); + final var solrClient1 = clients.getFirst(); final AtomicInteger retries = new AtomicInteger(); ZkNodeProps nodeProps = @@ -617,7 +615,7 @@ private SolrError getError(Exception e) { } private void testOneRetry(NodeType nodeType) throws Exception { - final HttpSolrClient solrclient = (HttpSolrClient) clients.get(0); + final var solrclient = clients.getFirst(); long numFoundBefore = solrclient.query(new SolrQuery("*:*")).getResults().getNumFound(); final MockStreamingSolrClients streamingClients = new MockStreamingSolrClients(updateShardHandler); @@ -678,7 +676,7 @@ public boolean checkRetry(SolrError err) { private void testNodeWontRetryBadRequest(NodeType nodeType) throws Exception { ignoreException("Bad Request"); - final HttpSolrClient solrclient = (HttpSolrClient) clients.get(0); + final var solrclient = clients.getFirst(); long numFoundBefore = solrclient.query(new SolrQuery("*:*")).getResults().getNumFound(); final MockStreamingSolrClients streamingClients = new MockStreamingSolrClients(updateShardHandler); @@ -739,7 +737,7 @@ public boolean checkRetry(SolrError err) { } private void testForwardNodeWontRetrySocketError() throws Exception { - final HttpSolrClient solrclient = (HttpSolrClient) clients.get(0); + final var solrclient = clients.getFirst(); long numFoundBefore = solrclient.query(new SolrQuery("*:*")).getResults().getNumFound(); final MockStreamingSolrClients streamingClients = new MockStreamingSolrClients(updateShardHandler); @@ -788,7 +786,7 @@ public boolean checkRetry(SolrError err) { } private void testStdNodeRetriesSocketError() throws Exception { - final HttpSolrClient solrclient = (HttpSolrClient) clients.get(0); + final var solrclient = clients.getFirst(); final MockStreamingSolrClients streamingClients = new MockStreamingSolrClients(updateShardHandler); try (SolrCmdDistributor cmdDistrib = new SolrCmdDistributor(streamingClients, 0)) { @@ -828,7 +826,7 @@ public boolean checkRetry(SolrError err) { private void testRetryNodeAgainstBadAddress() throws SolrServerException, IOException { // Test RetryNode try (SolrCmdDistributor cmdDistrib = new SolrCmdDistributor(updateShardHandler)) { - final HttpSolrClient solrclient = (HttpSolrClient) clients.get(0); + final var solrclient = clients.getFirst(); long numFoundBefore = solrclient.query(new SolrQuery("*:*")).getResults().getNumFound(); ArrayList nodes = new ArrayList<>(); @@ -914,17 +912,13 @@ private void testStuckUpdates() { try (SolrCmdDistributor cmdDistrib = new SolrCmdDistributor(updateShardHandler)) { for (int i = 0; i < 3; i++) { nodes.clear(); - for (SolrClient c : clients) { + for (HttpSolrClient c : clients) { if (random().nextBoolean()) { continue; } - HttpSolrClient httpClient = (HttpSolrClient) c; ZkNodeProps nodeProps = new ZkNodeProps( - ZkStateReader.BASE_URL_PROP, - httpClient.getBaseURL(), - ZkStateReader.CORE_NAME_PROP, - ""); + ZkStateReader.BASE_URL_PROP, c.getBaseURL(), ZkStateReader.CORE_NAME_PROP, ""); StdNode node = new StdNode(new ZkCoreNodeProps(nodeProps)); nodes.add(node); } diff --git a/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesDistrib.java b/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesDistrib.java index 084f94aa9644..8a1dd5fd46c4 100644 --- a/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesDistrib.java +++ b/solr/core/src/test/org/apache/solr/update/TestInPlaceUpdatesDistrib.java @@ -40,7 +40,7 @@ import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.client.solrj.request.schema.SchemaRequest.Field; import org.apache.solr.client.solrj.response.UpdateResponse; @@ -120,8 +120,8 @@ public TestInPlaceUpdatesDistrib() { fixShardCount(3); } - private SolrClient LEADER = null; - private List NONLEADERS = null; + private HttpSolrClient LEADER = null; + private List NONLEADERS = null; @Test @ShardsFixed(num = 3) @@ -226,8 +226,8 @@ private void mapReplicasToClients() throws KeeperException, InterruptedException leader = shard1.getLeader(); String leaderBaseUrl = zkStateReader.getBaseUrlForNodeName(leader.getNodeName()); - for (SolrClient solrClient : clients) { - if (((HttpSolrClient) solrClient).getBaseURL().startsWith(leaderBaseUrl)) { + for (HttpSolrClient solrClient : clients) { + if (solrClient.getBaseURL().startsWith(leaderBaseUrl)) { LEADER = solrClient; } } @@ -238,8 +238,8 @@ private void mapReplicasToClients() throws KeeperException, InterruptedException continue; } String baseUrl = zkStateReader.getBaseUrlForNodeName(rep.getNodeName()); - for (SolrClient client : clients) { - if (((HttpSolrClient) client).getBaseURL().startsWith(baseUrl)) { + for (HttpSolrClient client : clients) { + if (client.getBaseURL().startsWith(baseUrl)) { NONLEADERS.add(client); } } @@ -267,7 +267,7 @@ private void setNullForDVEnabledField() throws Exception { assertEquals("title0", sdoc.get("title_s")); long version0 = (long) sdoc.get("_version_"); - for (SolrClient client : NONLEADERS) { + for (HttpSolrClient client : NONLEADERS) { SolrDocument doc = client.getById(String.valueOf(0), params("distrib", "false")); assertEquals(inplace_updatable_float, doc.get("inplace_updatable_float")); assertEquals(version0, doc.get("_version_")); @@ -281,7 +281,7 @@ private void setNullForDVEnabledField() throws Exception { assertEquals("title0", sdoc.get("title_s")); long version1 = (long) sdoc.get("_version_"); - for (SolrClient client : NONLEADERS) { + for (HttpSolrClient client : NONLEADERS) { SolrDocument doc = client.getById(String.valueOf(0), params("distrib", "false")); assertNull(doc.get("inplace_updatable_float")); assertEquals(version1, doc.get("_version_")); @@ -372,7 +372,8 @@ private void reorderedDBQsSimpleTest() throws Exception { } // assert both replicas have same effect - for (SolrClient client : NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica + for (HttpSolrClient client : + NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica SolrDocument doc = client.getById(String.valueOf(0), params("distrib", "false")); assertNull("This doc was supposed to have been deleted, but was: " + doc, doc); } @@ -662,7 +663,7 @@ private void assertDocIdsAndValuesAgainstAllClients( assertEquals(luceneDocids.size(), valuesList.size()); final long numFoundExpected = luceneDocids.size(); - for (SolrClient client : clients) { + for (HttpSolrClient client : clients) { final String clientDebug = client.toString() + (LEADER.equals(client) ? " (leader)" : " (not leader)"); final String msg = "'" + debug + "' results against client: " + clientDebug; @@ -838,7 +839,7 @@ private void ensureRtgWorksWithPartialUpdatesTest() throws Exception { assertThat(e.getMessage(), containsString("For input string: \"NOT_NUMBER\"")); // RTG from tlog(s) - for (SolrClient client : clients) { + for (HttpSolrClient client : clients) { final String clientDebug = client.toString() + (LEADER.equals(client) ? " (leader)" : " (not leader)"); sdoc = client.getById("100", params("distrib", "false")); @@ -868,7 +869,7 @@ private void ensureRtgWorksWithPartialUpdatesTest() throws Exception { */ private List getInternalDocIds(String id) throws SolrServerException, IOException { List ret = new ArrayList<>(clients.size()); - for (SolrClient client : clients) { + for (HttpSolrClient client : clients) { SolrDocument doc = client.getById(id, params("distrib", "false", "fl", "[docid]")); Object docid = doc.get("[docid]"); assertNotNull(docid); @@ -960,23 +961,23 @@ private void outOfOrderUpdatesIndividualReplicaTest() throws Exception { } // assert both replicas have same effect - for (SolrClient client : NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica + for (HttpSolrClient client : + NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica if (log.isInfoEnabled()) { - log.info("Testing client: {}", ((HttpSolrClient) client).getBaseURL()); + log.info("Testing client: {}", client.getBaseURL()); } assertReplicaValue( client, 0, "inplace_updatable_float", (newinplace_updatable_float + (float) (updates.size() - 1)), - "inplace_updatable_float didn't match for replica at client: " - + ((HttpSolrClient) client).getBaseURL()); + "inplace_updatable_float didn't match for replica at client: " + client.getBaseURL()); assertReplicaValue( client, 0, "title_s", "title0_new", - "Title didn't match for replica at client: " + ((HttpSolrClient) client).getBaseURL()); + "Title didn't match for replica at client: " + client.getBaseURL()); assertEquals(version0 + updates.size(), getReplicaValue(client, 0, "_version_")); } @@ -1064,7 +1065,8 @@ private void reorderedDeletesTest() throws Exception { } // assert both replicas have same effect - for (SolrClient client : NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica + for (HttpSolrClient client : + NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica SolrDocument doc = client.getById(String.valueOf(0), params("distrib", "false")); assertNull("This doc was supposed to have been deleted, but was: " + doc, doc); } @@ -1154,9 +1156,7 @@ private void reorderedDBQsResurrectionTest() throws Exception { // the resurrection can happen from there (instead of the leader) update.setParam( DistributedUpdateProcessor.DISTRIB_FROM, - ((HttpSolrClient) NONLEADERS.get(1)).getBaseURL() - + "/" - + NONLEADERS.get(1).getDefaultCollection()); + (NONLEADERS.get(1)).getBaseURL() + "/" + NONLEADERS.get(1).getDefaultCollection()); AsyncUpdateWithRandomCommit task = new AsyncUpdateWithRandomCommit(update, NONLEADERS.get(0), random().nextLong()); updateResponses.add(threadpool.submit(task)); @@ -1196,8 +1196,8 @@ private void reorderedDBQsResurrectionTest() throws Exception { assertEquals(updateResponses.size(), successful); if (log.isInfoEnabled()) { - log.info("Non leader 0: {}", ((HttpSolrClient) NONLEADERS.get(0)).getBaseURL()); - log.info("Non leader 1: {}", ((HttpSolrClient) NONLEADERS.get(1)).getBaseURL()); // nowarn + log.info("Non leader 0: {}", NONLEADERS.get(0).getBaseURL()); + log.info("Non leader 1: {}", NONLEADERS.get(1).getBaseURL()); // nowarn } SolrDocument doc0 = NONLEADERS.get(0).getById(String.valueOf(0), params("distrib", "false")); @@ -1206,11 +1206,11 @@ private void reorderedDBQsResurrectionTest() throws Exception { log.info("Doc in both replica 0: {}", doc0); log.info("Doc in both replica 1: {}", doc1); // assert both replicas have same effect - for (SolrClient client : NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica + for (HttpSolrClient client : + NONLEADERS) { // 0th is re-ordered replica, 1st is well-ordered replica SolrDocument doc = client.getById(String.valueOf(0), params("distrib", "false")); - assertNotNull("Client: " + ((HttpSolrClient) client).getBaseURL(), doc); - assertEquals( - "Client: " + ((HttpSolrClient) client).getBaseURL(), 5, doc.getFieldValue(field)); + assertNotNull("Client: " + client.getBaseURL(), doc); + assertEquals("Client: " + client.getBaseURL(), 5, doc.getFieldValue(field)); } log.info("reorderedDBQsResurrectionTest: This test passed fine..."); @@ -1284,7 +1284,7 @@ private void delayedReorderingFetchesMissingUpdateFromLeaderTest() throws Except "The replica receiving reordered updates must not have gone down", 3, numActiveReplicas); } - for (SolrClient client : clients) { + for (HttpSolrClient client : clients) { TimeOut timeout = new TimeOut(30, TimeUnit.SECONDS, TimeSource.NANO_TIME); try { timeout.waitFor( @@ -1304,27 +1304,25 @@ private void delayedReorderingFetchesMissingUpdateFromLeaderTest() throws Except } } - for (SolrClient client : clients) { + for (HttpSolrClient client : clients) { + String baseURL = client.getBaseURL(); if (log.isInfoEnabled()) { - log.info("Testing client (Fetch missing test): {}", ((HttpSolrClient) client).getBaseURL()); + log.info("Testing client (Fetch missing test): {}", baseURL); log.info( - "Version at {} is: {}", - ((HttpSolrClient) client).getBaseURL(), - getReplicaValue(client, 1, "_version_")); // nowarn + "Version at {} is: {}", baseURL, getReplicaValue(client, 1, "_version_")); // nowarn } assertReplicaValue( client, 1, "inplace_updatable_float", (newinplace_updatable_float + 2.0f), - "inplace_updatable_float didn't match for replica at client: " - + ((HttpSolrClient) client).getBaseURL()); + "inplace_updatable_float didn't match for replica at client: " + baseURL); assertReplicaValue( client, 1, "title_s", "title1_new", - "Title didn't match for replica at client: " + ((HttpSolrClient) client).getBaseURL()); + "Title didn't match for replica at client: " + baseURL); } // Try another round of these updates, this time with a delete request at the end. @@ -1488,7 +1486,7 @@ UpdateRequest simulatedDeleteRequest(int id, long version) throws IOException { } UpdateRequest simulatedDeleteRequest(String query, long version) { - String baseUrl = getBaseUrl((HttpSolrClient) LEADER); + String baseUrl = getBaseUrl(LEADER); UpdateRequest ur = new UpdateRequest(); ur.deleteByQuery(query); @@ -1688,14 +1686,13 @@ private void reorderedDBQsUsingUpdatedValueFromADroppedUpdate() throws Exception "The replica receiving reordered updates must not have gone down", 3, numActiveReplicas); } - for (SolrClient client : clients) { + for (HttpSolrClient client : clients) { if (log.isInfoEnabled()) { log.info( - "Testing client (testDBQUsingUpdatedFieldFromDroppedUpdate): {}", - ((HttpSolrClient) client).getBaseURL()); + "Testing client (testDBQUsingUpdatedFieldFromDroppedUpdate): {}", client.getBaseURL()); log.info( "Version at {} is: {}", - ((HttpSolrClient) client).getBaseURL(), + client.getBaseURL(), getReplicaValue(client, 1, "_version_")); // nowarn } assertNull(client.getById("1", params("distrib", "false"))); diff --git a/solr/core/src/test/org/apache/solr/util/TestCborDataFormat.java b/solr/core/src/test/org/apache/solr/util/TestCborDataFormat.java index 056e95365299..c98ef9f01eb8 100644 --- a/solr/core/src/test/org/apache/solr/util/TestCborDataFormat.java +++ b/solr/core/src/test/org/apache/solr/util/TestCborDataFormat.java @@ -135,8 +135,10 @@ private byte[] runQuery(String testCollection, CloudSolrClient client, String wt request.setResponseParser(new InputStreamResponseParser(wt)); } result = client.request(request, testCollection); - InputStream inputStream = (InputStream) result.get("stream"); - byte[] b = inputStream.readAllBytes(); + byte[] b; + try (InputStream inputStream = (InputStream) result.get("stream")) { + b = inputStream.readAllBytes(); + } System.out.println(wt + "_time : " + timer.getTime()); System.out.println(wt + "_size : " + b.length); return b; diff --git a/solr/core/src/test/org/apache/solr/util/tracing/TestSimplePropagatorDistributedTracing.java b/solr/core/src/test/org/apache/solr/util/tracing/TestSimplePropagatorDistributedTracing.java index d66e8933e6df..31567090e0cf 100644 --- a/solr/core/src/test/org/apache/solr/util/tracing/TestSimplePropagatorDistributedTracing.java +++ b/solr/core/src/test/org/apache/solr/util/tracing/TestSimplePropagatorDistributedTracing.java @@ -25,7 +25,6 @@ import java.util.Optional; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; @@ -72,7 +71,7 @@ public void testQueryRequest() throws IOException, SolrServerException { try (LogListener reqLog = LogListener.info(SolrCore.class.getName() + ".Request")) { - try (SolrClient testClient = newCloudLegacySolrClient()) { + try (SolrClient testClient = newCloudSolrClient()) { // verify all query events have the same auto-generated trace id var r1 = testClient.query(COLLECTION, new SolrQuery("*:*")); assertEquals(0, r1.getStatus()); @@ -108,7 +107,7 @@ public void testQueryRequest() throws IOException, SolrServerException { public void testUpdateRequest() throws IOException, SolrServerException { try (LogListener reqLog = LogListener.info(LogUpdateProcessorFactory.class.getName())) { - try (SolrClient testClient = newCloudLegacySolrClient()) { + try (SolrClient testClient = newCloudSolrClient()) { // verify all indexing events have trace id present testClient.add(COLLECTION, sdoc("id", "1")); testClient.add(COLLECTION, sdoc("id", "3")); @@ -170,12 +169,6 @@ private void assertSameTraceId(LogListener reqLog, String traceId) { } } - private CloudSolrClient newCloudLegacySolrClient() { - return new CloudLegacySolrClient.Builder( - List.of(cluster.getZkServer().getZkAddress()), Optional.empty()) - .build(); - } - private CloudSolrClient newCloudSolrClient() { var builder = new CloudSolrClient.Builder( diff --git a/solr/cross-dc-manager/gradle.lockfile b/solr/cross-dc-manager/gradle.lockfile index 1a4c1b3845e1..6ba8101beb96 100644 --- a/solr/cross-dc-manager/gradle.lockfile +++ b/solr/cross-dc-manager/gradle.lockfile @@ -129,9 +129,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.kafka:kafka-clients:3.9.2=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.kafka:kafka-group-coordinator-api:3.9.2=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath org.apache.kafka:kafka-group-coordinator:3.9.2=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath diff --git a/solr/licenses/httpmime-4.5.14.jar.sha1 b/solr/licenses/httpmime-4.5.14.jar.sha1 deleted file mode 100644 index 3c37fe334ef5..000000000000 --- a/solr/licenses/httpmime-4.5.14.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -6662758a1f1cb1149cf916bdac28332e0902ec44 diff --git a/solr/licenses/httpmime-LICENSE-ASL.txt b/solr/licenses/httpmime-LICENSE-ASL.txt deleted file mode 100644 index 2c41ec88f61c..000000000000 --- a/solr/licenses/httpmime-LICENSE-ASL.txt +++ /dev/null @@ -1,182 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - -This project contains annotations derived from JCIP-ANNOTATIONS -Copyright (c) 2005 Brian Goetz and Tim Peierls. -See http://www.jcip.net and the Creative Commons Attribution License -(http://creativecommons.org/licenses/by/2.5) - diff --git a/solr/licenses/httpmime-NOTICE.txt b/solr/licenses/httpmime-NOTICE.txt deleted file mode 100644 index 3a98f4542f51..000000000000 --- a/solr/licenses/httpmime-NOTICE.txt +++ /dev/null @@ -1,8 +0,0 @@ -Apache HttpComponents Client -Copyright 1999-2011 The Apache Software Foundation - -This product includes software developed by -The Apache Software Foundation (http://www.apache.org/). - -This project contains annotations derived from JCIP-ANNOTATIONS -Copyright (c) 2005 Brian Goetz and Tim Peierls. See http://www.jcip.net \ No newline at end of file diff --git a/solr/modules/analysis-extras/gradle.lockfile b/solr/modules/analysis-extras/gradle.lockfile index 959fe0e15429..73274f402100 100644 --- a/solr/modules/analysis-extras/gradle.lockfile +++ b/solr/modules/analysis-extras/gradle.lockfile @@ -85,9 +85,6 @@ org.apache.commons:commons-math3:3.6.1=apiHelper,jarValidation,runtimeClasspath, org.apache.curator:curator-client:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/clustering/gradle.lockfile b/solr/modules/clustering/gradle.lockfile index 793882edea38..3a8eb41550c9 100644 --- a/solr/modules/clustering/gradle.lockfile +++ b/solr/modules/clustering/gradle.lockfile @@ -82,9 +82,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/cross-dc/gradle.lockfile b/solr/modules/cross-dc/gradle.lockfile index 52fe93a58be2..7711749a871c 100644 --- a/solr/modules/cross-dc/gradle.lockfile +++ b/solr/modules/cross-dc/gradle.lockfile @@ -86,9 +86,6 @@ org.apache.commons:commons-math3:3.6.1=apiHelper,jarValidation,runtimeClasspath, org.apache.curator:curator-client:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.kafka:kafka-clients:3.9.2=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/cuvs/gradle.lockfile b/solr/modules/cuvs/gradle.lockfile index 933980dbc1a6..16dc0299f3fa 100644 --- a/solr/modules/cuvs/gradle.lockfile +++ b/solr/modules/cuvs/gradle.lockfile @@ -84,9 +84,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/extraction/gradle.lockfile b/solr/modules/extraction/gradle.lockfile index d59161cf3509..b9a493023b16 100644 --- a/solr/modules/extraction/gradle.lockfile +++ b/solr/modules/extraction/gradle.lockfile @@ -87,9 +87,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/gcs-repository/gradle.lockfile b/solr/modules/gcs-repository/gradle.lockfile index eb04f041e5d9..d53d9fa148aa 100644 --- a/solr/modules/gcs-repository/gradle.lockfile +++ b/solr/modules/gcs-repository/gradle.lockfile @@ -138,7 +138,6 @@ org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidat org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/jwt-auth/gradle.lockfile b/solr/modules/jwt-auth/gradle.lockfile index 63071e565760..56c096bfda25 100644 --- a/solr/modules/jwt-auth/gradle.lockfile +++ b/solr/modules/jwt-auth/gradle.lockfile @@ -100,9 +100,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/langid/gradle.lockfile b/solr/modules/langid/gradle.lockfile index 3514bb148bf5..ae749db359aa 100644 --- a/solr/modules/langid/gradle.lockfile +++ b/solr/modules/langid/gradle.lockfile @@ -83,9 +83,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/language-models/gradle.lockfile b/solr/modules/language-models/gradle.lockfile index fb79289383dd..bec30747f9f6 100644 --- a/solr/modules/language-models/gradle.lockfile +++ b/solr/modules/language-models/gradle.lockfile @@ -97,9 +97,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/ltr/gradle.lockfile b/solr/modules/ltr/gradle.lockfile index 44d8e58774ae..34fad9e09df8 100644 --- a/solr/modules/ltr/gradle.lockfile +++ b/solr/modules/ltr/gradle.lockfile @@ -83,9 +83,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/opentelemetry/gradle.lockfile b/solr/modules/opentelemetry/gradle.lockfile index 9c11765122b4..416927dff1b4 100644 --- a/solr/modules/opentelemetry/gradle.lockfile +++ b/solr/modules/opentelemetry/gradle.lockfile @@ -113,9 +113,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java index ad5b474b771c..5433c11fd1d8 100644 --- a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java +++ b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrClient; @@ -41,6 +42,7 @@ import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.util.NamedList; +import org.apache.solr.common.util.RetryUtil; import org.apache.solr.util.stats.MetricUtils; import org.apache.solr.util.tracing.TraceUtils; import org.junit.AfterClass; @@ -92,7 +94,7 @@ public void test() throws IOException, SolrServerException { // Indexing cloudClient.add(COLLECTION, sdoc("id", "1")); - var finishedSpans = getAndClearSpans(); + var finishedSpans = getAndClearSpans(1); finishedSpans.removeIf( span -> span.getAttributes().get(TraceUtils.TAG_HTTP_URL) == null @@ -111,7 +113,7 @@ public void test() throws IOException, SolrServerException { // Searching cloudClient.query(COLLECTION, new SolrQuery("*:*")); - finishedSpans = getAndClearSpans(); + finishedSpans = getAndClearSpans(1); finishedSpans.removeIf( span -> span.getAttributes().get(TraceUtils.TAG_HTTP_URL) == null @@ -138,11 +140,11 @@ public void testAdminApi() throws Exception { request.setResponseParser(new InputStreamResponseParser(MetricUtils.PROMETHEUS_METRICS_WT)); NamedList rsp = cloudClient.request(request); ((InputStream) rsp.get("stream")).close(); - var finishedSpans = getAndClearSpans(); + var finishedSpans = getAndClearSpans(1); assertEquals("get:/admin/metrics", finishedSpans.get(0).getName()); CollectionAdminRequest.listCollections(cloudClient); - finishedSpans = getAndClearSpans(); + finishedSpans = getAndClearSpans(1); assertEquals("list:/admin/collections", finishedSpans.get(0).getName()); } @@ -155,7 +157,7 @@ public void testV2Api() throws Exception { .withPayload("{}") .build() .process(cloudClient); - var finishedSpans = getAndClearSpans(); + var finishedSpans = getAndClearSpans(1); assertEquals("post:/collections/{collection}/reload", finishedSpans.get(0).getName()); assertCollectionName(finishedSpans.get(0), COLLECTION); @@ -165,7 +167,7 @@ public void testV2Api() throws Exception { .withParams(params("commit", "true")) .build() .process(cloudClient); - finishedSpans = getAndClearSpans(); + finishedSpans = getAndClearSpans(1); assertEquals("post:/c/{collection}/update/json", finishedSpans.get(0).getName()); assertCollectionName(finishedSpans.get(0), COLLECTION); @@ -175,7 +177,7 @@ public void testV2Api() throws Exception { .withParams(params("q", "id:9")) .build() .process(cloudClient); - finishedSpans = getAndClearSpans(); + finishedSpans = getAndClearSpans(1); assertEquals("get:/c/{collection}/select", finishedSpans.get(0).getName()); assertCollectionName(finishedSpans.get(0), COLLECTION); assertEquals(1, ((SolrDocumentList) v2Response.getResponse().get("response")).getNumFound()); @@ -191,7 +193,7 @@ public void testApacheClient() throws Exception { CollectionAdminRequest.ColStatus a1 = CollectionAdminRequest.collectionStatus(COLLECTION); CollectionAdminResponse r1 = a1.process(cluster.getSolrClient()); assertEquals(0, r1.getStatus()); - var finishedSpans = getAndClearSpans(); + var finishedSpans = getAndClearSpans(1); var parentTraceId = getRootTraceId(finishedSpans); for (var span : finishedSpans) { if (isRootSpan(span)) { @@ -239,7 +241,7 @@ private void verifyCollectionCreation(String collection) throws Exception { // db.instance=testInternalCollectionApiCommands_shard2_replica_n4 // db.instance=testInternalCollectionApiCommands_shard1_replica_n2 - var finishedSpans = getAndClearSpans(); + var finishedSpans = getAndClearSpans(1); var s0 = finishedSpans.remove(0); assertCollectionName(s0, collection); assertEquals("create:/admin/collections", s0.getName()); @@ -280,7 +282,7 @@ private void verifyCollectionDeletion(String collection) throws Exception { // db.instance=testInternalCollectionApiCommands_shard2_replica_n4 // db.instance=testInternalCollectionApiCommands_shard1_replica_n6 - var finishedSpans = getAndClearSpans(); + var finishedSpans = getAndClearSpans(1); var s0 = finishedSpans.remove(0); assertCollectionName(s0, collection); assertEquals("delete:/admin/collections", s0.getName()); @@ -327,7 +329,21 @@ private void assertOneSpanIsChildOfAnother(List finishedSpans) { } static List getAndClearSpans() { + return getAndClearSpans(0); + } + + static List getAndClearSpans(int minExpected) { InMemorySpanExporter exporter = CustomTestOtelTracerConfigurator.getInMemorySpanExporter(); + try { + RetryUtil.retryUntil( + "Timed out waiting for " + minExpected + " span(s)", + 250, + 20, + TimeUnit.MILLISECONDS, + () -> exporter.getFinishedSpanItems().size() >= minExpected); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } List result = new ArrayList<>(exporter.getFinishedSpanItems()); Collections.reverse(result); // nicer to see spans chronologically exporter.reset(); diff --git a/solr/modules/s3-repository/gradle.lockfile b/solr/modules/s3-repository/gradle.lockfile index 3725a0dc9be5..e5f21b223f01 100644 --- a/solr/modules/s3-repository/gradle.lockfile +++ b/solr/modules/s3-repository/gradle.lockfile @@ -109,7 +109,6 @@ org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidat org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/scripting/gradle.lockfile b/solr/modules/scripting/gradle.lockfile index 889234e4e0fd..2f6a5c50c80e 100644 --- a/solr/modules/scripting/gradle.lockfile +++ b/solr/modules/scripting/gradle.lockfile @@ -82,9 +82,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,runtimeClasspath,runtimeLib org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/modules/sql/gradle.lockfile b/solr/modules/sql/gradle.lockfile index 3af24e910d8a..34c7b3e2fa6e 100644 --- a/solr/modules/sql/gradle.lockfile +++ b/solr/modules/sql/gradle.lockfile @@ -93,9 +93,6 @@ org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath org.apache.httpcomponents.client5:httpclient5:5.2.1=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath org.apache.httpcomponents.core5:httpcore5-h2:5.2=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath org.apache.httpcomponents.core5:httpcore5:5.2.3=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-1.2-api:2.25.3=solrPlatformLibs org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath diff --git a/solr/solr-ref-guide/gradle.lockfile b/solr/solr-ref-guide/gradle.lockfile index 35a6de3f6353..5162141605de 100644 --- a/solr/solr-ref-guide/gradle.lockfile +++ b/solr/solr-ref-guide/gradle.lockfile @@ -90,9 +90,6 @@ org.apache.curator:curator-test:5.9.0=testRuntimeClasspath org.apache.httpcomponents.client5:httpclient5:5.2.1=testRuntimeClasspath org.apache.httpcomponents.core5:httpcore5-h2:5.2=testRuntimeClasspath org.apache.httpcomponents.core5:httpcore5:5.2.3=testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=testRuntimeClasspath diff --git a/solr/solrj-jetty/gradle.lockfile b/solr/solrj-jetty/gradle.lockfile index ee611917aaec..954a371c9267 100644 --- a/solr/solrj-jetty/gradle.lockfile +++ b/solr/solrj-jetty/gradle.lockfile @@ -83,9 +83,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,testRuntimeClasspath org.apache.curator:curator-client:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=jarValidation,testRuntimeClasspath diff --git a/solr/solrj-jetty/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientCompatibilityTest.java b/solr/solrj-jetty/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientCompatibilityTest.java index 82b3fd8e83ae..af9248be307b 100644 --- a/solr/solrj-jetty/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientCompatibilityTest.java +++ b/solr/solrj-jetty/src/test/org/apache/solr/client/solrj/jetty/HttpJettySolrClientCompatibilityTest.java @@ -34,13 +34,13 @@ import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP; import org.eclipse.jetty.ee10.servlet.ServletHolder; import org.eclipse.jetty.http2.client.transport.HttpClientTransportOverHTTP2; -import org.junit.ClassRule; +import org.junit.Rule; @LogLevel("org.eclipse.jetty.client=DEBUG;org.eclipse.jetty.util=DEBUG") @SolrTestCaseJ4.SuppressSSL public class HttpJettySolrClientCompatibilityTest extends SolrTestCaseJ4 { - @ClassRule public static SolrJettyTestRule solrTestRule = new SolrJettyTestRule(); + @Rule public SolrJettyTestRule solrTestRule = new SolrJettyTestRule(); public void testSystemPropertyFlag() { System.setProperty("solr.http1", "true"); @@ -62,6 +62,7 @@ public void testConnectToOldNodesUsingHttp1() throws Exception { .build(); EnvUtils.setProperty( ALLOW_PATHS_SYSPROP, ExternalPaths.SERVER_HOME.toAbsolutePath().toString()); + System.setProperty("solr.http1", "true"); solrTestRule.startSolr(createTempDir(), new Properties(), jettyConfig); solrTestRule.newCollection().withConfigSet(ExternalPaths.TECHPRODUCTS_CONFIGSET).create(); @@ -74,8 +75,6 @@ public void testConnectToOldNodesUsingHttp1() throws Exception { client.query(new SolrQuery("*:*"), SolrRequest.METHOD.GET); } catch (RemoteSolrException ignored) { } - } finally { - solrTestRule.reset(); } } @@ -100,8 +99,6 @@ public void testConnectToNewNodesUsingHttp1() throws Exception { client.query(new SolrQuery("*:*"), SolrRequest.METHOD.GET); } catch (RemoteSolrException ignored) { } - } finally { - solrTestRule.reset(); } } @@ -118,6 +115,7 @@ public void testConnectToOldNodesUsingHttp2() throws Exception { EnvUtils.setProperty( ALLOW_PATHS_SYSPROP, ExternalPaths.SERVER_HOME.toAbsolutePath().toString()); + System.setProperty("solr.http1", "true"); solrTestRule.startSolr(createTempDir(), new Properties(), jettyConfig); solrTestRule.newCollection().withConfigSet(ExternalPaths.TECHPRODUCTS_CONFIGSET).create(); @@ -133,8 +131,6 @@ public void testConnectToOldNodesUsingHttp2() throws Exception { } catch (SolrServerException e) { // expected } - } finally { - solrTestRule.reset(); } } } diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientCustomizerTest.java b/solr/solrj-jetty/src/test/org/apache/solr/client/solrj/jetty/PreemptiveBasicAuthClientCustomizerTest.java similarity index 88% rename from solr/solrj/src/test/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientCustomizerTest.java rename to solr/solrj-jetty/src/test/org/apache/solr/client/solrj/jetty/PreemptiveBasicAuthClientCustomizerTest.java index ae76c810232b..cf5af87a16a5 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientCustomizerTest.java +++ b/solr/solrj-jetty/src/test/org/apache/solr/client/solrj/jetty/PreemptiveBasicAuthClientCustomizerTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import java.util.Properties; import org.apache.solr.SolrTestCase; -import org.apache.solr.client.solrj.apache.HttpClientUtil; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; public class PreemptiveBasicAuthClientCustomizerTest extends SolrTestCase { @@ -70,8 +70,10 @@ public void testCredentialsFromSystemProperties() { PreemptiveBasicAuthClientCustomizer.SYS_PROP_BASIC_AUTH_CREDENTIALS, "foo:bar"); PreemptiveBasicAuthClientCustomizer.CredentialsResolver credentialsResolver = new PreemptiveBasicAuthClientCustomizer.CredentialsResolver(); - assertEquals("foo", credentialsResolver.defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_USER)); - assertEquals("bar", credentialsResolver.defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_PASS)); + assertEquals( + "foo", credentialsResolver.defaultParams.get(SolrHttpConstants.PROP_BASIC_AUTH_USER)); + assertEquals( + "bar", credentialsResolver.defaultParams.get(SolrHttpConstants.PROP_BASIC_AUTH_PASS)); } public void testCredentialsFromConfigFile() throws IOException { @@ -86,7 +88,9 @@ public void testCredentialsFromConfigFile() throws IOException { PreemptiveBasicAuthClientCustomizer.SYS_PROP_HTTP_CLIENT_CONFIG, f.toString()); PreemptiveBasicAuthClientCustomizer.CredentialsResolver credentialsResolver = new PreemptiveBasicAuthClientCustomizer.CredentialsResolver(); - assertEquals("foo", credentialsResolver.defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_USER)); - assertEquals("bar", credentialsResolver.defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_PASS)); + assertEquals( + "foo", credentialsResolver.defaultParams.get(SolrHttpConstants.PROP_BASIC_AUTH_USER)); + assertEquals( + "bar", credentialsResolver.defaultParams.get(SolrHttpConstants.PROP_BASIC_AUTH_PASS)); } } diff --git a/solr/solrj-streaming/build.gradle b/solr/solrj-streaming/build.gradle index 93bf46f788cd..2495dae42716 100644 --- a/solr/solrj-streaming/build.gradle +++ b/solr/solrj-streaming/build.gradle @@ -30,6 +30,7 @@ dependencies { testImplementation project(':solr:core') testImplementation project(':solr:solrj-zookeeper') + testRuntimeOnly project(':solr:solrj-jetty') testRuntimeOnly project(':solr:modules:sql') testRuntimeOnly libs.hsqldb.hsqldb // runtime because via JDBC reflection diff --git a/solr/solrj-streaming/gradle.lockfile b/solr/solrj-streaming/gradle.lockfile index e0b32df6d924..0c5f6b2b3bd2 100644 --- a/solr/solrj-streaming/gradle.lockfile +++ b/solr/solrj-streaming/gradle.lockfile @@ -91,9 +91,6 @@ org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath org.apache.httpcomponents.client5:httpclient5:5.2.1=jarValidation,testRuntimeClasspath org.apache.httpcomponents.core5:httpcore5-h2:5.2=jarValidation,testRuntimeClasspath org.apache.httpcomponents.core5:httpcore5:5.2.3=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=jarValidation,testRuntimeClasspath diff --git a/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/graph/GraphExpressionTest.java b/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/graph/GraphExpressionTest.java index 9b190864c868..72e49588c17c 100644 --- a/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/graph/GraphExpressionTest.java +++ b/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/graph/GraphExpressionTest.java @@ -18,9 +18,6 @@ package org.apache.solr.client.solrj.io.graph; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -56,7 +53,6 @@ import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.NamedList; -import org.apache.solr.embedded.JettySolrRunner; import org.apache.solr.util.BaseTestHarness; import org.junit.Before; import org.junit.BeforeClass; @@ -1226,13 +1222,8 @@ public void testGraphHandler() throws Exception { .add(id, "5", "from_s", "jim", "to_s", "ann", "message_t", "Hello steve") .commit(cluster.getSolrClient(), COLLECTION); - commit(); + SolrClient client = cluster.getRandomJetty(random()).getSolrClient(); - List runners = cluster.getJettySolrRunners(); - JettySolrRunner runner = runners.get(0); - String url = runner.getBaseUrl().toString(); - - SolrClient client = getHttpSolrClient(url); ModifiableSolrParams params = new ModifiableSolrParams(); String expr = @@ -1250,9 +1241,7 @@ public void testGraphHandler() throws Exception { NamedList genericResponse = client.request(query); - InputStream stream = (InputStream) genericResponse.get(InputStreamResponseParser.STREAM_KEY); - InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8); - String xml = readString(reader); + String xml = InputStreamResponseParser.consumeResponseToString(genericResponse); // Validate the nodes String error = BaseTestHarness.validateXPath( @@ -1281,16 +1270,6 @@ public void testGraphHandler() throws Exception { client.close(); } - private String readString(InputStreamReader reader) throws Exception { - StringBuilder builder = new StringBuilder(); - int c = 0; - while ((c = reader.read()) != -1) { - builder.append(((char) c)); - } - - return builder.toString(); - } - protected List getTuples(TupleStream tupleStream) throws IOException { tupleStream.open(); List tuples = new ArrayList<>(); diff --git a/solr/solrj-zookeeper/gradle.lockfile b/solr/solrj-zookeeper/gradle.lockfile index f0f9c46d494c..92e459c934fe 100644 --- a/solr/solrj-zookeeper/gradle.lockfile +++ b/solr/solrj-zookeeper/gradle.lockfile @@ -99,9 +99,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,testRuntimeClasspath org.apache.curator:curator-client:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=jarValidation,testRuntimeClasspath diff --git a/solr/solrj/gradle.lockfile b/solr/solrj/gradle.lockfile index 449d53a460d7..b1a1dc64c61b 100644 --- a/solr/solrj/gradle.lockfile +++ b/solr/solrj/gradle.lockfile @@ -84,9 +84,6 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,testRuntimeClasspath org.apache.curator:curator-client:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=jarValidation,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=jarValidation,testRuntimeClasspath diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java index 93ae9e332f15..7c197323a4b1 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java @@ -465,6 +465,9 @@ public abstract static class BuilderBase, C extends */ @SuppressWarnings("unchecked") public B withHttpClient(C httpSolrClient) { + if (this.baseSolrUrl == null) { + this.baseSolrUrl = httpSolrClient.getBaseURL(); + } if (this.basicAuthAuthorizationStr == null) { this.basicAuthAuthorizationStr = httpSolrClient.basicAuthAuthorizationStr; } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java b/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java index 60005d50e5a4..bf06c491d032 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputField; @@ -69,7 +70,7 @@ public static String buildRequestUrl( SolrRequest solrRequest, String serverRootUrl, String collection) throws MalformedURLException { - String basePath = serverRootUrl; + String basePath = Objects.requireNonNull(serverRootUrl); if (solrRequest.getApiVersion() == SolrRequest.ApiVersion.V2) { basePath = addNormalV2ApiRoot(basePath); } diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java index 102a2beda125..ba83a8495440 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java @@ -17,7 +17,7 @@ package org.apache.solr.client.solrj; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.JavaBinRequestWriter; import org.apache.solr.client.solrj.response.JavaBinResponseParser; @@ -30,9 +30,9 @@ public class SolrExampleBinaryTest extends SolrExampleTests { @Override public SolrClient createNewSolrClient() { - return new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + return new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_COLLECTION_NAME) - .allowMultiPartPost(random().nextBoolean()) .withRequestWriter(new JavaBinRequestWriter()) .withResponseParser(new JavaBinResponseParser()) .build(); diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleCborTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleCborTest.java index 59031c28b7ee..deabd8534c7a 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleCborTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleCborTest.java @@ -27,7 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.JavaBinRequestWriter; import org.apache.solr.client.solrj.request.RequestWriter; import org.apache.solr.client.solrj.request.UpdateRequest; @@ -47,9 +47,9 @@ public class SolrExampleCborTest extends SolrExampleTests { @Override public SolrClient createNewSolrClient() { - return new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + return new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_COLLECTION_NAME) - .allowMultiPartPost(random().nextBoolean()) .withRequestWriter(cborRequestWriter()) .withResponseParser(cborResponseParser()) .build(); diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java index 50cf5879a8f0..ca9ef93e5245 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java @@ -44,10 +44,10 @@ import java.util.Random; import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; import org.apache.solr.client.solrj.embedded.SolrExampleStreamingHttp2Test; import org.apache.solr.client.solrj.embedded.SolrExampleStreamingTest.ErrorTrackingConcurrentUpdateSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.AbstractUpdateRequest.ACTION; import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest; @@ -722,7 +722,7 @@ public void testErrorHandling() throws Exception { doc.addField("id", "DOCID2"); doc.addField("name", "hello"); - if (client instanceof HttpSolrClient) { + if (client instanceof HttpJettySolrClient) { ex = expectThrows(SolrException.class, () -> client.add(doc)); assertEquals(400, ex.code()); assertTrue(ex.getMessage().indexOf("contains multiple values for uniqueKey") > 0); @@ -2386,7 +2386,7 @@ public void testUpdateField() throws Exception { doc.addField(field, oper); try { client.add(doc); - if (client instanceof HttpSolrClient) { + if (client instanceof HttpJettySolrClient) { // XXX concurrent client reports exceptions differently fail("Operation should throw an exception!"); } else if (client instanceof ErrorTrackingConcurrentUpdateSolrClient concurrentClient) { diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java index 1b0efddca917..07f8fe6fa1fb 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java @@ -17,7 +17,7 @@ package org.apache.solr.client.solrj; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.XMLRequestWriter; import org.apache.solr.client.solrj.response.XMLResponseParser; @@ -30,9 +30,9 @@ public class SolrExampleXMLTest extends SolrExampleTests { @Override public SolrClient createNewSolrClient() { - return new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + return new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_COLLECTION_NAME) - .allowMultiPartPost(random().nextBoolean()) .withRequestWriter(new XMLRequestWriter()) .withResponseParser(new XMLResponseParser()) .build(); diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/TestBatchUpdate.java b/solr/solrj/src/test/org/apache/solr/client/solrj/TestBatchUpdate.java index d64b999560b9..94e909d1252a 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/TestBatchUpdate.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/TestBatchUpdate.java @@ -22,8 +22,8 @@ import java.util.Iterator; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.beans.Field; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.JavaBinRequestWriter; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.request.XMLRequestWriter; @@ -60,7 +60,8 @@ public static void beforeTest() throws Exception { @Test public void testWithXml() throws Exception { try (SolrClient client = - new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_CORENAME) .withRequestWriter(new XMLRequestWriter()) .build()) { @@ -72,7 +73,8 @@ public void testWithXml() throws Exception { @Test public void testWithBinary() throws Exception { try (SolrClient client = - new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_CORENAME) .withRequestWriter(new JavaBinRequestWriter()) .build()) { @@ -84,7 +86,8 @@ public void testWithBinary() throws Exception { @Test public void testWithBinaryBean() throws Exception { try (SolrClient client = - new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_CORENAME) .withRequestWriter(new JavaBinRequestWriter()) .build()) { diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java b/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java index 023874d77ddc..e0b26f7d86b1 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java @@ -39,7 +39,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.JavaBinRequestWriter; import org.apache.solr.client.solrj.request.XMLRequestWriter; import org.apache.solr.client.solrj.response.QueryResponse; @@ -114,7 +114,8 @@ public void showExceptions() throws Exception { @Test public void testWithXml() throws Exception { try (SolrClient client = - new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_CORENAME) .withRequestWriter(new XMLRequestWriter()) .build()) { @@ -126,7 +127,8 @@ public void testWithXml() throws Exception { @Test public void testWithBinary() throws Exception { try (SolrClient client = - new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_CORENAME) .withRequestWriter(new JavaBinRequestWriter()) .build()) { diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingBinaryTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingBinaryTest.java index 3a66dc2c7bc3..32aa7164cd12 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingBinaryTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingBinaryTest.java @@ -20,6 +20,7 @@ import java.util.List; import org.apache.solr.SolrTestCaseJ4.SuppressSSL; import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.JavaBinRequestWriter; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.client.solrj.response.JavaBinResponseParser; @@ -35,15 +36,18 @@ public class SolrExampleStreamingBinaryTest extends SolrExampleStreamingTest { @Override public SolrClient createNewSolrClient() { + var httpJettyClient = + new HttpJettySolrClient.Builder() + .withResponseParser(new JavaBinResponseParser()) + .withRequestWriter(new JavaBinRequestWriter()) + .build(); SolrClient client = - new ErrorTrackingConcurrentUpdateSolrClient.Builder(solrTestRule.getBaseUrl()) + new ErrorTrackingConcurrentUpdateSolrClient.Builder( + solrTestRule.getBaseUrl(), httpJettyClient, true) .withDefaultCollection(DEFAULT_TEST_CORENAME) .withQueueSize(2) .withThreadCount(5) - .withResponseParser(new JavaBinResponseParser()) - .withRequestWriter(new JavaBinRequestWriter()) .build(); - return client; } diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java index 0625ab905919..be869ada9bf7 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java @@ -22,7 +22,8 @@ import java.util.List; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrExampleTests; -import org.apache.solr.client.solrj.apache.ConcurrentUpdateSolrClient; +import org.apache.solr.client.solrj.jetty.ConcurrentUpdateJettySolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.client.solrj.request.XMLRequestWriter; @@ -38,12 +39,16 @@ public class SolrExampleStreamingTest extends SolrExampleTests { @Override public SolrClient createNewSolrClient() { // smaller queue size hits locks more often - return new ErrorTrackingConcurrentUpdateSolrClient.Builder(solrTestRule.getBaseUrl()) + var httpJettyClient = + new HttpJettySolrClient.Builder() + .withResponseParser(new XMLResponseParser()) + .withRequestWriter(new XMLRequestWriter()) + .build(); + return new ErrorTrackingConcurrentUpdateSolrClient.Builder( + solrTestRule.getBaseUrl(), httpJettyClient, true) .withDefaultCollection(DEFAULT_TEST_COLLECTION_NAME) .withQueueSize(2) .withThreadCount(5) - .withResponseParser(new XMLResponseParser()) - .withRequestWriter(new XMLRequestWriter()) .build(); } @@ -52,8 +57,9 @@ public void testWaitOptions() throws Exception { // TODO these failures are not the same as recorded by the client final List failures = new ArrayList<>(); final String serverUrl = solrTestRule.getBaseUrl() + "/" + DEFAULT_TEST_CORENAME; - try (ConcurrentUpdateSolrClient concurrentClient = - new FailureRecordingConcurrentUpdateSolrClient.Builder(serverUrl) + try (var concurrentClient = + new FailureRecordingConcurrentUpdateSolrClient.Builder( + serverUrl, (HttpJettySolrClient) solrTestRule.getSolrClient(), false) .withQueueSize(2) .withThreadCount(2) .build()) { @@ -79,7 +85,7 @@ public void testWaitOptions() throws Exception { } } - static class FailureRecordingConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient { + static class FailureRecordingConcurrentUpdateSolrClient extends ConcurrentUpdateJettySolrClient { private final List failures = new ArrayList<>(); public FailureRecordingConcurrentUpdateSolrClient(Builder builder) { @@ -91,9 +97,9 @@ public void handleError(Throwable ex) { failures.add(ex); } - static class Builder extends ConcurrentUpdateSolrClient.Builder { - public Builder(String baseSolrUrl) { - super(baseSolrUrl); + static class Builder extends ConcurrentUpdateJettySolrClient.Builder { + public Builder(String baseSolrUrl, HttpJettySolrClient solrClient, boolean closeClient) { + super(baseSolrUrl, solrClient, closeClient); } @Override @@ -103,7 +109,8 @@ public FailureRecordingConcurrentUpdateSolrClient build() { } } - public static class ErrorTrackingConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient { + public static class ErrorTrackingConcurrentUpdateSolrClient + extends ConcurrentUpdateJettySolrClient { public Throwable lastError = null; public ErrorTrackingConcurrentUpdateSolrClient(Builder builder) { @@ -115,10 +122,10 @@ public void handleError(Throwable ex) { lastError = ex; } - public static class Builder extends ConcurrentUpdateSolrClient.Builder { + public static class Builder extends ConcurrentUpdateJettySolrClient.Builder { - public Builder(String baseSolrUrl) { - super(baseSolrUrl); + public Builder(String baseSolrUrl, HttpJettySolrClient solrClient, boolean closeClient) { + super(baseSolrUrl, solrClient, closeClient); } @Override diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java index 5f2fc5ee67af..f08cfcce42f1 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientBadInputTest.java @@ -37,7 +37,7 @@ public static void setupCluster() throws Exception { @Test public void testDeleteByIdReportsInvalidIdLists() throws Exception { - try (SolrClient client = new RandomizingCloudHttp2SolrClientBuilder(cluster).build()) { + try (SolrClient client = new RandomizingCloudSolrClientBuilder(cluster).build()) { assertExceptionThrownWithMessageContaining( IllegalArgumentException.class, List.of("ids", "null"), diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java index 3d2f32fc2a75..88ae42fc32c4 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java @@ -34,6 +34,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.client.solrj.RemoteSolrException; @@ -1062,7 +1063,7 @@ public void testRetryUpdatesWhenClusterStateIsStale() throws Exception { .sendDirectUpdatesToAnyShardReplica() .withDefaultCollection(COL) // don't let collection cache entries get expired, even on a slow machine... - .withCollectionCacheTtl(Integer.MAX_VALUE) + .withCollectionCacheTtl(1, TimeUnit.DAYS) .build()) { // do a query to populate stale_client's cache... diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java index 8d279ea773bd..706e334f1d16 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java @@ -47,7 +47,7 @@ import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.LBHttpSolrClient; +import org.apache.solr.client.solrj.jetty.LBJettySolrClient; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.common.SolrException; import org.apache.solr.common.cloud.ClusterState; @@ -95,13 +95,16 @@ public DocCollection get() { NamedList okResponse = new NamedList<>(); okResponse.add("responseHeader", new NamedList<>(Map.of("status", 0))); - LBHttpSolrClient mockLbclient = getMockLbHttpSolrClient(responses); + LBJettySolrClient mockLbclient = getMockLbHttpSolrClient(responses); AtomicInteger lbhttpRequestCount = new AtomicInteger(); try (ClusterStateProvider clusterStateProvider = getStateProvider(livenodes, refs); CloudSolrClient cloudClient = - new RandomizingCloudSolrClientBuilder(clusterStateProvider) - .withLBHttpSolrClient(mockLbclient) - .build()) { + new RandomizingCloudSolrClientBuilder(clusterStateProvider) { + @Override + protected LBSolrClient createOrGetLbClient(HttpSolrClient myClient) { + return mockLbclient; + } + }.build()) { livenodes.addAll(Set.of("192.168.1.108:7574_solr", "192.168.1.108:8983_solr")); ClusterState cs = ClusterState.createFromJson( @@ -297,9 +300,9 @@ public void testConcurrentRefreshIsDeduplicated() throws Exception { } @SuppressWarnings({"unchecked"}) - private LBHttpSolrClient getMockLbHttpSolrClient(Map> responses) + private LBJettySolrClient getMockLbHttpSolrClient(Map> responses) throws Exception { - LBHttpSolrClient mockLbclient = mock(LBHttpSolrClient.class); + var mockLbclient = mock(LBJettySolrClient.class); when(mockLbclient.request(any(LBSolrClient.Req.class))) .then( diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java index e82dcb1ca9fb..ae429783d4f7 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBadInputTest.java @@ -23,7 +23,7 @@ import java.util.List; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.LBHttpSolrClient; +import org.apache.solr.client.solrj.jetty.LBJettySolrClient; import org.apache.solr.common.util.EnvUtils; import org.apache.solr.util.ExternalPaths; import org.apache.solr.util.SolrJettyTestRule; @@ -51,8 +51,7 @@ public static void beforeTest() throws Exception { @Test public void testDeleteByIdReportsInvalidIdLists() throws Exception { try (SolrClient client = - new LBHttpSolrClient.Builder() - .withBaseEndpoint(solrTestRule.getBaseUrl()) + new LBJettySolrClient.Builder(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(ANY_COLLECTION) .build()) { assertExceptionThrownWithMessageContaining( @@ -82,7 +81,7 @@ public void testDeleteByIdReportsInvalidIdLists() throws Exception { } try (SolrClient client = - new LBHttpSolrClient.Builder().withBaseEndpoint(solrTestRule.getBaseUrl()).build()) { + new LBJettySolrClient.Builder(solrTestRule.getJetty().getSolrClient()).build()) { assertExceptionThrownWithMessageContaining( IllegalArgumentException.class, List.of("ids", "null"), diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java index 5d31f782379a..ab27c827c626 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java @@ -31,7 +31,6 @@ import java.util.Set; import java.util.stream.Collectors; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.UpdateRequest; @@ -207,12 +206,6 @@ private static UpdateRequest prefPull(final UpdateRequest req) { } public void testBuilderImplicitBehavior() throws Exception { - try (CloudSolrClient client = - new CloudLegacySolrClient.Builder( - List.of(cluster.getZkServer().getZkAddress()), Optional.empty()) - .build()) { - assertTrue(client.isUpdatesToLeaders()); - } try (CloudSolrClient client = new CloudSolrClient.Builder(List.of(cluster.getZkServer().getZkAddress()), Optional.empty()) .build()) { @@ -220,28 +213,6 @@ public void testBuilderImplicitBehavior() throws Exception { } } - public void testLegacyClientThatDefaultsToLeaders() throws Exception { - try (CloudSolrClient client = - new CloudLegacySolrClient.Builder( - List.of(cluster.getZkServer().getZkAddress()), Optional.empty()) - .sendUpdatesOnlyToShardLeaders() - .build()) { - checkUpdatesDefaultToLeaders(client); - checkUpdatesWithSendToLeadersFalse(client); - } - } - - public void testLegacyClientThatDoesNotDefaultToLeaders() throws Exception { - try (CloudSolrClient client = - new CloudLegacySolrClient.Builder( - List.of(cluster.getZkServer().getZkAddress()), Optional.empty()) - .sendUpdatesToAnyReplica() - .build()) { - checkUpdatesWithShardsPrefPull(client); - checkUpdatesWithSendToLeadersFalse(client); - } - } - public void testHttp2ClientThatDefaultsToLeaders() throws Exception { try (CloudSolrClient client = new CloudSolrClient.Builder(List.of(cluster.getZkServer().getZkAddress()), Optional.empty()) diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV2Request.java b/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV2Request.java index 09c11077fa8c..aebadc76a426 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV2Request.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV2Request.java @@ -24,7 +24,6 @@ import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.response.V2Response; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.cloud.ClusterState; @@ -84,10 +83,7 @@ public void testIsCollectionRequest() { @Test public void testHttpSolrClient() throws Exception { - SolrClient solrClient = - new HttpSolrClient.Builder(cluster.getJettySolrRunner(0).getBaseUrl().toString()).build(); - doTest(solrClient); - solrClient.close(); + doTest(cluster.getJettySolrRunner(0).getSolrClient()); } @Test @@ -149,22 +145,21 @@ public void testV2Forwarding() throws Exception { cs.getCollection("v2forward").forEachReplica((s, replica) -> node[0] = replica.getNodeName()); // find a node that does not have a replica for this collection - final String[] testNode = new String[1]; - cs.getLiveNodes() - .forEach( - s -> { - if (!s.equals(node[0])) testNode[0] = s; - }); - - String testServer = cluster.getZkStateReader().getBaseUrlForNodeName(testNode[0]); + String testNode = + cs.getLiveNodes().stream().filter(s -> !s.equals(node[0])).findAny().orElseThrow(); + V2Request v2r = new V2Request.Builder("/c/v2forward/_introspect") .withMethod(SolrRequest.METHOD.GET) .build(); - try (SolrClient client1 = new HttpSolrClient.Builder().withBaseSolrUrl(testServer).build()) { - V2Response rsp = v2r.process(client1); - assertEquals("0", rsp._getStr("responseHeader/status")); - } + V2Response rsp = + v2r.process( + cluster.getJettySolrRunners().stream() + .filter(j -> testNode.equals(j.getNodeName())) + .findAny() + .orElseThrow() + .getSolrClient()); + assertEquals("0", rsp._getStr("responseHeader/status")); } } diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java index 984d19864d49..464add48ee53 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/response/InputStreamResponseParserTest.java @@ -26,7 +26,7 @@ import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.common.SolrDocument; @@ -72,7 +72,8 @@ public void doBefore() throws IOException, SolrServerException { public void testQueryParse() throws Exception { try (SolrClient client = - new HttpSolrClient.Builder(solrTestRule.getBaseUrl()) + new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_CORENAME) .withResponseParser(new InputStreamResponseParser("xml")) .build()) { diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestSuggesterResponse.java b/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestSuggesterResponse.java index d159bcc53284..975b5721ecff 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestSuggesterResponse.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/response/TestSuggesterResponse.java @@ -24,7 +24,7 @@ import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.common.SolrInputDocument; @@ -144,8 +144,8 @@ private void addSampleDocs() throws SolrServerException, IOException { private SolrClient createSuggestSolrClient() { final ResponseParser randomParser = random().nextBoolean() ? new JavaBinResponseParser() : new XMLResponseParser(); - return new HttpSolrClient.Builder() - .withBaseSolrUrl(solrTestRule.getBaseUrl()) + return new HttpJettySolrClient.Builder() + .withHttpClient(solrTestRule.getJetty().getSolrClient()) .withDefaultCollection(DEFAULT_TEST_COLLECTION_NAME) .withResponseParser(randomParser) .build(); diff --git a/solr/test-framework/build.gradle b/solr/test-framework/build.gradle index c116e384469c..a871997786ee 100644 --- a/solr/test-framework/build.gradle +++ b/solr/test-framework/build.gradle @@ -64,8 +64,6 @@ dependencies { implementation libs.apache.log4j.api implementation libs.apache.log4j.core implementation libs.commonscli.commonscli - implementation libs.apache.httpcomponents.httpclient - implementation libs.apache.httpcomponents.httpcore implementation libs.opentelemetry.api implementation(libs.opentelemetry.exporter.prometheus) { transitive = false // most things don't want or already have @@ -97,9 +95,4 @@ dependencies { exclude group: "io.prometheus", module: "prometheus-metrics-shaded-protobuf" exclude group: "io.prometheus", module: "prometheus-metrics-config" }) - - implementation(libs.apache.httpcomponents.httpmime, { - exclude group: "commons-codec", module: "commons-codec" - exclude group: "commons-logging", module: "commons-logging" - }) } diff --git a/solr/test-framework/gradle.lockfile b/solr/test-framework/gradle.lockfile index e55bbe89b7fb..e05994327ac4 100644 --- a/solr/test-framework/gradle.lockfile +++ b/solr/test-framework/gradle.lockfile @@ -33,7 +33,7 @@ com.j256.simplemagic:simplemagic:1.17=apiHelper,jarValidation,runtimeClasspath,t com.jayway.jsonpath:json-path:2.9.0=apiHelper,jarValidation,runtimeClasspath,testRuntimeClasspath com.tdunning:t-digest:3.3=apiHelper,jarValidation,runtimeClasspath,testRuntimeClasspath commons-cli:commons-cli:1.11.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -commons-codec:commons-codec:1.21.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-codec:commons-codec:1.21.0=apiHelper,jarValidation,runtimeClasspath,testRuntimeClasspath commons-io:commons-io:2.21.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.dropwizard.metrics:metrics-core:3.2.5=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor @@ -83,9 +83,6 @@ org.apache.commons:commons-math3:3.6.1=apiHelper,jarValidation,runtimeClasspath, org.apache.curator:curator-client:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.curator:curator-test:5.9.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.httpcomponents:httpmime:4.5.14=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-api:2.25.3=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-core:2.25.3=apiHelper,compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.logging.log4j:log4j-slf4j2-impl:2.25.3=apiHelper,jarValidation,runtimeClasspath,testRuntimeClasspath diff --git a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java index e72ffaa213cd..0e58b671d7bf 100644 --- a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java +++ b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java @@ -50,6 +50,7 @@ import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrResponse; import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.UpdateResponse; @@ -166,14 +167,14 @@ public void fixShardCount(int count) { } protected volatile JettySolrRunner controlJetty; - protected final List clients = Collections.synchronizedList(new ArrayList<>()); + protected final List clients = Collections.synchronizedList(new ArrayList<>()); protected final List jettys = Collections.synchronizedList(new ArrayList<>()); protected volatile String[] deadServers; protected volatile String shards; protected volatile String[] shardsArr; protected volatile Path testDir; - protected volatile SolrClient controlClient; + protected volatile HttpSolrClient controlClient; // to stress with higher thread counts and requests, make sure the junit // xml formatter is not being used (all output will be buffered before @@ -444,7 +445,7 @@ public SequencedMap, String> getExtraRequestFilters() { return null; } - protected SolrClient createNewSolrClient(int port) { + protected HttpSolrClient createNewSolrClient(int port) { return getHttpSolrClient(buildUrl(port), DEFAULT_TEST_CORENAME); } diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java index 26668690557e..4f4dedd1eec4 100644 --- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java +++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java @@ -76,9 +76,6 @@ import org.apache.lucene.tests.util.TestUtil; import org.apache.lucene.util.Constants; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; -import org.apache.solr.client.solrj.apache.HttpClientUtil; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.impl.ClusterStateProvider; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; @@ -281,9 +278,6 @@ public static void setupTestCases() { newRandomConfig(); sslConfig = buildSSLConfig(); - // based on randomized SSL config, set SocketFactoryRegistryProvider appropriately - HttpClientUtil.setSocketFactoryRegistryProvider( - sslConfig.buildClientSocketFactoryRegistryProvider()); HttpJettySolrClient.setDefaultSSLConfig(sslConfig.buildClientSSLConfig()); if (isSSLMode()) { // SolrCloud tests should usually clear this @@ -316,7 +310,6 @@ public static void teardownTestCases() throws Exception { } finally { TestInjection.reset(); initCoreDataDir = null; - HttpClientUtil.resetHttpClientBuilder(); HttpJettySolrClient.resetSslContextFactory(); clearNumericTypesProperties(); @@ -2474,55 +2467,8 @@ public static CollectionAdminRequest.RequestStatusResponse waitForAsyncClusterRe rsp -> rsp.getRequestStatus().isFinal()); } - /** - * A variant of {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} that will - * randomize some internal settings. - */ - public static class RandomizingCloudHttp2SolrClientBuilder extends CloudSolrClient.Builder { - - public RandomizingCloudHttp2SolrClientBuilder(List zkHosts, Optional zkChroot) { - super(zkHosts, zkChroot); - randomizeCloudSolrClient(); - } - - public RandomizingCloudHttp2SolrClientBuilder(ClusterStateProvider stateProvider) { - super(new ArrayList<>()); - this.stateProvider = stateProvider; - randomizeCloudSolrClient(); - } - - public RandomizingCloudHttp2SolrClientBuilder(MiniSolrCloudCluster cluster) { - super(new ArrayList<>()); - if (random().nextBoolean()) { - this.zkHosts.add(cluster.getZkServer().getZkAddress()); - } else { - populateSolrUrls(cluster); - } - - randomizeCloudSolrClient(); - } - - private void populateSolrUrls(MiniSolrCloudCluster cluster) { - if (random().nextBoolean()) { - final List solrNodes = cluster.getJettySolrRunners(); - for (JettySolrRunner node : solrNodes) { - this.solrUrls.add(node.getBaseUrl().toString()); - } - } else { - this.solrUrls.add(cluster.getRandomJetty(random()).getBaseUrl().toString()); - } - } - - private void randomizeCloudSolrClient() { - this.directUpdatesToLeadersOnly = random().nextBoolean(); - this.shardLeadersOnly = random().nextBoolean(); - this.parallelUpdates = random().nextBoolean(); - } - } - - /** A variant of {@code CloudSolrClient.Builder} that will randomize some internal settings. */ - @Deprecated - public static class RandomizingCloudSolrClientBuilder extends CloudLegacySolrClient.Builder { + /** A builder that will randomize some internal settings. */ + public static class RandomizingCloudSolrClientBuilder extends CloudSolrClient.Builder { public RandomizingCloudSolrClientBuilder(List zkHosts, Optional zkChroot) { super(zkHosts, zkChroot); @@ -2530,11 +2476,13 @@ public RandomizingCloudSolrClientBuilder(List zkHosts, Optional } public RandomizingCloudSolrClientBuilder(ClusterStateProvider stateProvider) { + super(new ArrayList<>()); this.stateProvider = stateProvider; randomizeCloudSolrClient(); } public RandomizingCloudSolrClientBuilder(MiniSolrCloudCluster cluster) { + super(new ArrayList<>()); if (random().nextBoolean()) { this.zkHosts.add(cluster.getZkServer().getZkAddress()); } else { @@ -2569,12 +2517,14 @@ private void randomizeCloudSolrClient() { * * @param url the base URL for a Solr node. Should not contain a core or collection name. */ - public static HttpSolrClient getHttpSolrClient(String url) { - return new HttpSolrClient.Builder(url).build(); + @Deprecated // probably use an existing client like on a testRule/jettyRunner + public static HttpJettySolrClient getHttpSolrClient(String url) { + return new HttpJettySolrClient.Builder(url).build(); } /** Create a basic HttpSolrClient pointed at the specified replica */ - public static HttpSolrClient getHttpSolrClient(Replica replica) { + @Deprecated // probably use an existing client like on a testRule/jettyRunner + public static HttpJettySolrClient getHttpSolrClient(Replica replica) { return getHttpSolrClient(replica.getBaseUrl(), replica.getCoreName()); } @@ -2587,8 +2537,9 @@ public static HttpSolrClient getHttpSolrClient(Replica replica) { * @param defaultCoreName the name of a core that the created client should default to when making * core-aware requests */ - public static HttpSolrClient getHttpSolrClient(String url, String defaultCoreName) { - return new HttpSolrClient.Builder(url).withDefaultCollection(defaultCoreName).build(); + @Deprecated // probably use an existing client like on a testRule/jettyRunner + public static HttpJettySolrClient getHttpSolrClient(String url, String defaultCoreName) { + return new HttpJettySolrClient.Builder(url).withDefaultCollection(defaultCoreName).build(); } /** diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/CloudLegacySolrClient.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/CloudLegacySolrClient.java deleted file mode 100644 index d6bd73024092..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/CloudLegacySolrClient.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import org.apache.http.NoHttpResponseException; -import org.apache.http.client.HttpClient; -import org.apache.http.conn.ConnectTimeoutException; -import org.apache.solr.client.solrj.impl.CloudSolrClient; -import org.apache.solr.client.solrj.impl.ClusterStateProvider; -import org.apache.solr.client.solrj.impl.LBSolrClient; -import org.apache.solr.client.solrj.impl.SolrZkClientTimeout; -import org.apache.solr.client.solrj.impl.SolrZkClientTimeout.SolrZkClientTimeoutAware; -import org.apache.solr.client.solrj.request.JavaBinRequestWriter; -import org.apache.solr.client.solrj.request.UpdateRequest; -import org.apache.solr.client.solrj.response.JavaBinResponseParser; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.cloud.DocCollection; -import org.apache.solr.common.cloud.DocRouter; -import org.apache.solr.common.params.ModifiableSolrParams; -import org.apache.solr.common.util.IOUtils; -import org.apache.solr.common.util.NamedList; - -/** - * SolrJ client class to communicate with SolrCloud. Instances of this class communicate with - * Zookeeper to discover Solr endpoints for SolrCloud collections, and then use the {@link - * LBHttpSolrClient} to issue requests. - * - * @deprecated Please use {@link CloudSolrClient} - */ -@Deprecated(since = "9.0") -public class CloudLegacySolrClient extends CloudSolrClient { - - private final ClusterStateProvider stateProvider; - private final LBHttpSolrClient lbClient; - private final boolean shutdownLBHttpSolrServer; - private HttpClient myClient; - private final boolean clientIsInternal; - - public static final String STATE_VERSION = CloudSolrClient.STATE_VERSION; - - /** - * Create a new client object that connects to Zookeeper and is always aware of the SolrCloud - * state. If there is a fully redundant Zookeeper quorum and SolrCloud has enough replicas for - * every shard in a collection, there is no single point of failure. Updates will be sent to shard - * leaders by default. - * - * @param builder a {@link Builder} with the options used to create the client. - */ - protected CloudLegacySolrClient(Builder builder) { - super(builder.shardLeadersOnly, builder.parallelUpdates, builder.directUpdatesToLeadersOnly); - this.stateProvider = builder.stateProvider; - this.retryExpiryTimeNano = builder.retryExpiryTimeNano; - this.defaultCollection = builder.defaultCollection; - this.collectionStateCache.timeToLiveMs = - TimeUnit.MILLISECONDS.convert(builder.timeToLiveSeconds, TimeUnit.SECONDS); - this.clientIsInternal = builder.httpClient == null; - this.shutdownLBHttpSolrServer = builder.loadBalancedSolrClient == null; - if (builder.lbClientBuilder != null) { - propagateLBClientConfigOptions(builder); - builder.loadBalancedSolrClient = builder.lbClientBuilder.build(); - } - if (builder.loadBalancedSolrClient != null) - builder.httpClient = builder.loadBalancedSolrClient.getHttpClient(); - this.myClient = - (builder.httpClient == null) ? HttpClientUtil.createClient(null) : builder.httpClient; - if (builder.loadBalancedSolrClient == null) - builder.loadBalancedSolrClient = createLBHttpSolrClient(builder, myClient); - this.lbClient = builder.loadBalancedSolrClient; - } - - private void propagateLBClientConfigOptions(Builder builder) { - final LBHttpSolrClient.Builder lbBuilder = builder.lbClientBuilder; - lbBuilder.withConnectionTimeout(builder.connectionTimeoutMillis, TimeUnit.MILLISECONDS); - lbBuilder.withSocketTimeout(builder.socketTimeoutMillis, TimeUnit.MILLISECONDS); - } - - @Override - protected Map createRoutes( - UpdateRequest updateRequest, - ModifiableSolrParams routableParams, - DocCollection col, - DocRouter router, - Map> urlMap, - String idField) { - return urlMap == null - ? null - : updateRequest.getRoutesToCollection(router, col, urlMap, routableParams, idField); - } - - @Override - protected RouteException getRouteException( - SolrException.ErrorCode serverError, - NamedList exceptions, - Map routes) { - return new RouteException(serverError, exceptions, routes); - } - - @Override - public void close() { - IOUtils.closeQuietly(stateProvider); - - if (shutdownLBHttpSolrServer) { - lbClient.close(); - } - - if (clientIsInternal && myClient != null) { - HttpClientUtil.close(myClient); - } - - super.close(); - } - - @Override - public LBHttpSolrClient getLbClient() { - return lbClient; - } - - public HttpClient getHttpClient() { - return myClient; - } - - @Override - public ClusterStateProvider getClusterStateProvider() { - return stateProvider; - } - - @Override - protected boolean wasCommError(Throwable rootCause) { - return super.wasCommError(rootCause) - || rootCause instanceof ConnectTimeoutException - || rootCause instanceof NoHttpResponseException; - } - - private static LBHttpSolrClient createLBHttpSolrClient( - Builder cloudSolrClientBuilder, HttpClient httpClient) { - final LBHttpSolrClient.Builder lbBuilder = new LBHttpSolrClient.Builder(); - lbBuilder.withHttpClient(httpClient); - lbBuilder.withConnectionTimeout( - cloudSolrClientBuilder.connectionTimeoutMillis, TimeUnit.MILLISECONDS); - lbBuilder.withSocketTimeout(cloudSolrClientBuilder.socketTimeoutMillis, TimeUnit.MILLISECONDS); - lbBuilder.withRequestWriter(new JavaBinRequestWriter()); - lbBuilder.withResponseParser(new JavaBinResponseParser()); - - return lbBuilder.build(); - } - - /** Constructs {@link CloudLegacySolrClient} instances from provided configuration. */ - public static class Builder extends SolrClientBuilder { - protected Collection zkHosts = new ArrayList<>(); - protected List solrUrls = new ArrayList<>(); - protected String zkChroot; - protected LBHttpSolrClient loadBalancedSolrClient; - protected LBHttpSolrClient.Builder lbClientBuilder; - protected boolean shardLeadersOnly = true; - protected boolean directUpdatesToLeadersOnly = false; - protected boolean parallelUpdates = true; - protected long retryExpiryTimeNano = - TimeUnit.NANOSECONDS.convert(3, TimeUnit.SECONDS); // 3 seconds or 3 million nanos - protected ClusterStateProvider stateProvider; - private int zkConnectTimeout = SolrZkClientTimeout.DEFAULT_ZK_CONNECT_TIMEOUT; - private int zkClientTimeout = SolrZkClientTimeout.DEFAULT_ZK_CLIENT_TIMEOUT; - private boolean canUseZkACLs = true; - - /** Constructor for use by subclasses. This constructor was public prior to version 9.0 */ - protected Builder() {} - - /** - * Provide a series of Solr URLs to be used when configuring {@link CloudLegacySolrClient} - * instances. The solr client will use these urls to understand the cluster topology, which solr - * nodes are active etc. - * - *

Provided Solr URLs are expected to point to the root Solr path - * ("http://hostname:8983/solr"); they should not include any collections, cores, or other path - * components. - * - *

Usage example: - * - *

-     *   final List<String> solrBaseUrls = new ArrayList<String>();
-     *   solrBaseUrls.add("http://solr1:8983/solr"); solrBaseUrls.add("http://solr2:8983/solr"); solrBaseUrls.add("http://solr3:8983/solr");
-     *   final SolrClient client = new CloudSolrClient.Builder(solrBaseUrls).build();
-     * 
- */ - public Builder(List solrUrls) { - this.solrUrls = solrUrls; - } - - /** Provide an already created {@link ClusterStateProvider} instance */ - public Builder(ClusterStateProvider stateProvider) { - this.stateProvider = stateProvider; - } - - /** - * Provide a series of ZK hosts which will be used when configuring {@link - * CloudLegacySolrClient} instances. - * - *

Usage example when Solr stores data at the ZooKeeper root ('/'): - * - *

-     *   final List<String> zkServers = new ArrayList<String>();
-     *   zkServers.add("zookeeper1:2181"); zkServers.add("zookeeper2:2181"); zkServers.add("zookeeper3:2181");
-     *   final SolrClient client = new CloudSolrClient.Builder(zkServers, Optional.empty()).build();
-     * 
- * - * Usage example when Solr data is stored in a ZooKeeper chroot: - * - *
-     *    final List<String> zkServers = new ArrayList<String>();
-     *    zkServers.add("zookeeper1:2181"); zkServers.add("zookeeper2:2181"); zkServers.add("zookeeper3:2181");
-     *    final SolrClient client = new CloudSolrClient.Builder(zkServers, Optional.of("/solr")).build();
-     *  
- * - * @param zkHosts a List of at least one ZooKeeper host and port (e.g. "zookeeper1:2181") - * @param zkChroot the path to the root ZooKeeper node containing Solr data. Provide {@code - * java.util.Optional.empty()} if no ZK chroot is used. - */ - public Builder(List zkHosts, Optional zkChroot) { - this.zkHosts = zkHosts; - if (zkChroot.isPresent()) this.zkChroot = zkChroot.get(); - } - - /** Whether to use the default ZK ACLs when building a ZK Client. */ - public Builder canUseZkACLs(boolean canUseZkACLs) { - this.canUseZkACLs = canUseZkACLs; - return this; - } - - /** Provides a {@link HttpClient} for the builder to use when creating clients. */ - public Builder withLBHttpSolrClientBuilder(LBHttpSolrClient.Builder lbHttpSolrClientBuilder) { - this.lbClientBuilder = lbHttpSolrClientBuilder; - return this; - } - - /** Provides a {@link LBHttpSolrClient} for the builder to use when creating clients. */ - public Builder withLBHttpSolrClient(LBHttpSolrClient loadBalancedSolrClient) { - this.loadBalancedSolrClient = loadBalancedSolrClient; - return this; - } - - /** - * Sets the cache ttl for DocCollection Objects cached. - * - * @param seconds ttl value in seconds - */ - public Builder withCollectionCacheTtl(int seconds) { - assert seconds > 0; - this.timeToLiveSeconds = seconds; - return this; - } - - /** - * Tells {@link Builder} that created clients should be configured such that {@link - * CloudSolrClient#isUpdatesToLeaders} returns true. - * - * @see #sendUpdatesToAnyReplica - * @see CloudSolrClient#isUpdatesToLeaders - */ - public Builder sendUpdatesOnlyToShardLeaders() { - shardLeadersOnly = true; - return this; - } - - /** - * Tells {@link Builder} that created clients should be configured such that {@link - * CloudSolrClient#isUpdatesToLeaders} returns false. - * - * @see #sendUpdatesOnlyToShardLeaders - * @see CloudSolrClient#isUpdatesToLeaders - */ - public Builder sendUpdatesToAnyReplica() { - shardLeadersOnly = false; - return this; - } - - /** - * This method has no effect. - * - *

In older versions of Solr, this method was an incorrectly named equivalent to {@link - * #sendUpdatesToAnyReplica}, which had no effect because that setting was ignored in the - * created clients. When the underlying {@link CloudSolrClient} behavior was fixed, this method - * was modified to be an explicit No-Op, since the implied behavior of sending updates to - * all replicas has never been supported, and was never intended to be supported. - * - * @see #sendUpdatesOnlyToShardLeaders - * @see #sendUpdatesToAnyReplica - * @see CloudSolrClient#isUpdatesToLeaders - * @see SOLR-6312 - * @deprecated Never supported - */ - @Deprecated - public Builder sendUpdatesToAllReplicasInShard() { - return this; - } - - /** - * Tells {@link Builder} that created clients should send direct updates to shard leaders only. - * - *

UpdateRequests whose leaders cannot be found will "fail fast" on the client side with a - * {@link SolrException} - * - * @see #sendDirectUpdatesToAnyShardReplica - * @see CloudSolrClient#isDirectUpdatesToLeadersOnly - */ - public Builder sendDirectUpdatesToShardLeadersOnly() { - directUpdatesToLeadersOnly = true; - return this; - } - - /** - * Tells {@link Builder} that created clients can send updates to any shard replica (shard - * leaders and non-leaders). - * - *

Shard leaders are still preferred, but the created clients will fall back to using other - * replicas if a leader cannot be found. - * - * @see #sendDirectUpdatesToShardLeadersOnly - * @see CloudSolrClient#isDirectUpdatesToLeadersOnly - */ - public Builder sendDirectUpdatesToAnyShardReplica() { - directUpdatesToLeadersOnly = false; - return this; - } - - /** - * Tells {@link Builder} whether created clients should send shard updates serially or in - * parallel - * - *

When an {@link UpdateRequest} affects multiple shards, {@link CloudLegacySolrClient} - * splits it up and sends a request to each affected shard. This setting chooses whether those - * sub-requests are sent serially or in parallel. - * - *

If not set, this defaults to 'true' and sends sub-requests in parallel. - */ - public Builder withParallelUpdates(boolean parallelUpdates) { - this.parallelUpdates = parallelUpdates; - return this; - } - - /** - * Sets the Zk connection timeout - * - * @param zkConnectTimeout timeout value - * @param unit time unit - */ - public Builder withZkConnectTimeout(int zkConnectTimeout, TimeUnit unit) { - this.zkConnectTimeout = Math.toIntExact(unit.toMillis(zkConnectTimeout)); - return this; - } - - /** - * Sets the Zk client session timeout - * - * @param zkClientTimeout timeout value - * @param unit time unit - */ - public Builder withZkClientTimeout(int zkClientTimeout, TimeUnit unit) { - this.zkClientTimeout = Math.toIntExact(unit.toMillis(zkClientTimeout)); - return this; - } - - /** Create a {@link CloudLegacySolrClient} based on the provided configuration. */ - public CloudLegacySolrClient build() { - if (stateProvider == null) { - if (!zkHosts.isEmpty() && !solrUrls.isEmpty()) { - throw new IllegalArgumentException( - "Both zkHost(s) & solrUrl(s) have been specified. Only specify one."); - } else if (!zkHosts.isEmpty()) { - this.stateProvider = - ClusterStateProvider.newZkClusterStateProvider(zkHosts, zkChroot, canUseZkACLs); - if (stateProvider instanceof SolrZkClientTimeoutAware timeoutAware) { - timeoutAware.setZkClientTimeout(zkClientTimeout); - timeoutAware.setZkConnectTimeout(zkConnectTimeout); - } - } else if (!this.solrUrls.isEmpty()) { - try { - stateProvider = new HttpClusterStateProvider(solrUrls, httpClient); - } catch (Exception e) { - throw new RuntimeException( - "Couldn't initialize a HttpClusterStateProvider (is/are the " - + "Solr server(s), " - + solrUrls - + ", down?)", - e); - } - } else { - throw new IllegalArgumentException("Both zkHosts and solrUrl cannot be null."); - } - } - return new CloudLegacySolrClient(this); - } - - @Override - public Builder getThis() { - return this; - } - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/ConcurrentUpdateSolrClient.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/ConcurrentUpdateSolrClient.java deleted file mode 100644 index a042bdae5363..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/ConcurrentUpdateSolrClient.java +++ /dev/null @@ -1,887 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.invoke.MethodHandles; -import java.nio.charset.StandardCharsets; -import java.util.ArrayDeque; -import java.util.Locale; -import java.util.Objects; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentProducer; -import org.apache.http.entity.EntityTemplate; -import org.apache.solr.client.solrj.RemoteSolrException; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.SolrRequest; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.ConcurrentUpdateBaseSolrClient; -import org.apache.solr.client.solrj.impl.StallDetection; -import org.apache.solr.client.solrj.request.UpdateRequest; -import org.apache.solr.client.solrj.util.ClientUtils; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.CommonParams; -import org.apache.solr.common.params.ModifiableSolrParams; -import org.apache.solr.common.params.SolrParams; -import org.apache.solr.common.params.UpdateParams; -import org.apache.solr.common.util.ExecutorUtil; -import org.apache.solr.common.util.IOUtils; -import org.apache.solr.common.util.NamedList; -import org.apache.solr.common.util.SolrNamedThreadFactory; -import org.apache.solr.common.util.URLUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -/** - * ConcurrentUpdateSolrClient buffers all added documents and writes them into open HTTP - * connections. This class is thread safe. - * - *

Params from {@link UpdateRequest} are converted to http request parameters. When params change - * between UpdateRequests a new HTTP request is started. - * - *

Although any SolrClient request can be made with this implementation, it is only recommended - * to use ConcurrentUpdateSolrClient with /update requests. The class {@link HttpSolrClient} is - * better suited for the query interface. - * - * @deprecated Please use {@link ConcurrentUpdateBaseSolrClient} - */ -@Deprecated(since = "9.0") -public class ConcurrentUpdateSolrClient extends SolrClient { - private static final long serialVersionUID = 1L; - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private HttpSolrClient client; - final BlockingQueue queue; - final ExecutorService scheduler; - final Queue runners; - volatile CountDownLatch lock = null; // used to block everything - final int threadCount; - boolean shutdownExecutor = false; - int pollQueueTimeMillis = 250; - private final boolean streamDeletes; - private boolean internalHttpClient; - private final int connectionTimeout; - private final int soTimeout; - private volatile boolean closed; - - AtomicInteger pollInterrupts; - AtomicInteger pollExits; - AtomicInteger blockLoops; - AtomicInteger emptyQueueLoops; - - protected StallDetection stallDetection; - - /** - * Use builder to construct this class. Uses the supplied HttpClient to send documents to the Solr - * server. - */ - protected ConcurrentUpdateSolrClient(Builder builder) { - this.internalHttpClient = (builder.httpClient == null); - final var httpSolrClientBuilder = - (URLUtil.isBaseUrl(builder.baseSolrUrl)) - ? new HttpSolrClient.Builder(builder.baseSolrUrl) - : new HttpSolrClient.Builder(URLUtil.extractBaseUrl(builder.baseSolrUrl)) - .withDefaultCollection(URLUtil.extractCoreFromCoreUrl(builder.baseSolrUrl)); - this.client = - httpSolrClientBuilder - .withHttpClient(builder.httpClient) - .withConnectionTimeout(builder.connectionTimeoutMillis, TimeUnit.MILLISECONDS) - .withSocketTimeout(builder.socketTimeoutMillis, TimeUnit.MILLISECONDS) - .withFollowRedirects(false) - .withTheseParamNamesInTheUrl(builder.urlParamNames) - .build(); - this.queue = new LinkedBlockingQueue<>(builder.queueSize); - this.threadCount = builder.threadCount; - this.runners = new ArrayDeque<>(); - this.streamDeletes = builder.streamDeletes; - this.connectionTimeout = builder.connectionTimeoutMillis; - this.soTimeout = builder.socketTimeoutMillis; - this.pollQueueTimeMillis = builder.pollQueueTime; - this.defaultCollection = builder.defaultCollection; - - // Initialize stall detection - int stallTimeMillis = Integer.getInteger("solr.cloud.client.stallTime", 15000); - - // make sure the stall time is larger than the polling time - // to give a chance for the queue to change - int minimalStallTime = pollQueueTimeMillis * 2; - if (minimalStallTime > stallTimeMillis) { - stallTimeMillis = minimalStallTime; - } - - this.stallDetection = new StallDetection(stallTimeMillis, () -> queue.size()); - - if (builder.executorService != null) { - this.scheduler = builder.executorService; - this.shutdownExecutor = false; - } else { - this.scheduler = - ExecutorUtil.newMDCAwareCachedThreadPool( - new SolrNamedThreadFactory("concurrentUpdateScheduler")); - this.shutdownExecutor = true; - } - - if (log.isDebugEnabled()) { - this.pollInterrupts = new AtomicInteger(); - this.pollExits = new AtomicInteger(); - this.blockLoops = new AtomicInteger(); - this.emptyQueueLoops = new AtomicInteger(); - } - - // processedCount is now managed by StallDetection - } - - public Set getUrlParamNames() { - return this.client.getUrlParamNames(); - } - - /** Opens a connection and sends everything... */ - @SuppressWarnings({"unchecked"}) - class Runner implements Runnable { - volatile Thread thread = null; - volatile boolean inPoll = false; - - public Thread getThread() { - return thread; - } - - @Override - public void run() { - this.thread = Thread.currentThread(); - log.debug("starting runner: {}", this); - // This loop is so we can continue if an element was added to the queue after the last runner - // exited. - for (; ; ) { - try { - - sendUpdateStream(); - - } catch (Throwable e) { - if (e instanceof OutOfMemoryError) { - throw (OutOfMemoryError) e; - } - handleError(e); - } finally { - synchronized (runners) { - // check to see if anything else was added to the queue - if (runners.size() == 1 && !queue.isEmpty() && !ExecutorUtil.isShutdown(scheduler)) { - // If there is something else to process, keep last runner alive by staying in the - // loop. - } else { - runners.remove(this); - if (runners.isEmpty()) { - // notify anyone waiting in blockUntilFinished - runners.notifyAll(); - } - break; - } - } - } - } - - log.debug("finished: {}", this); - } - - public void interruptPoll() { - Thread lthread = thread; - if (inPoll && lthread != null) { - lthread.interrupt(); - } - } - - // - // Pull from the queue multiple times and streams over a single connection. - // Exits on exception, interruption, or an empty queue to pull from. - // - void sendUpdateStream() throws Exception { - - while (!queue.isEmpty()) { - HttpPost method = null; - HttpResponse response = null; - - InputStream rspBody = null; - try { - Update update; - notifyQueueAndRunnersIfEmptyQueue(); - try { - inPoll = true; - update = queue.poll(pollQueueTimeMillis, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - if (log.isDebugEnabled()) pollInterrupts.incrementAndGet(); - continue; - } finally { - inPoll = false; - } - if (update == null) break; - - String contentType = client.requestWriter.getUpdateContentType(); - final boolean isXml = ClientUtils.TEXT_XML.equals(contentType); - - final ModifiableSolrParams origParams = - new ModifiableSolrParams(update.getRequest().getParams()); - final String origTargetCollection = update.getCollection(); - - EntityTemplate template = - new EntityTemplate( - new ContentProducer() { - - @Override - public void writeTo(OutputStream out) throws IOException { - - if (isXml) { - out.write("".getBytes(StandardCharsets.UTF_8)); // can be anything - } - Update upd = update; - while (upd != null) { - UpdateRequest req = upd.getRequest(); - if (!origParams.equals(req.getParams()) - || !Objects.equals(origTargetCollection, upd.getCollection())) { - // Request has different params or destination core/collection, return to - // queue - queue.add(upd); - break; - } - - client.requestWriter.write(req, out); - if (isXml) { - // check for commit or optimize - SolrParams params = req.getParams(); - if (params != null) { - String fmt = null; - if (params.getBool(UpdateParams.OPTIMIZE, false)) { - fmt = ""; - } else if (params.getBool(UpdateParams.COMMIT, false)) { - fmt = ""; - } - if (fmt != null) { - byte[] content = - String.format( - Locale.ROOT, - fmt, - params.getBool(UpdateParams.WAIT_SEARCHER, false) + "") - .getBytes(StandardCharsets.UTF_8); - out.write(content); - } - } - } - out.flush(); - - notifyQueueAndRunnersIfEmptyQueue(); - inPoll = true; - try { - while (true) { - try { - upd = queue.poll(pollQueueTimeMillis, TimeUnit.MILLISECONDS); - break; - } catch (InterruptedException e) { - if (log.isDebugEnabled()) pollInterrupts.incrementAndGet(); - if (!queue.isEmpty()) { - continue; - } - if (log.isDebugEnabled()) pollExits.incrementAndGet(); - upd = null; - break; - } finally { - inPoll = false; - } - } - } finally { - inPoll = false; - } - } - - if (isXml) { - out.write("".getBytes(StandardCharsets.UTF_8)); - } - } - }); - - // The parser 'wt=' param is used instead of the original params - var addParams = SolrParams.of(CommonParams.WT, client.parser.getWriterType()); - var requestParams = SolrParams.wrapDefaults(addParams, origParams); - - String basePath = client.getBaseURL(); - if (update.getCollection() != null) { - basePath += "/" + update.getCollection(); - } else if (client.getDefaultCollection() != null) { - basePath += "/" + client.getDefaultCollection(); - } - - method = new HttpPost(basePath + "/update" + requestParams.toQueryString()); - - RequestConfig.Builder requestConfigBuilder = - HttpClientUtil.createDefaultRequestConfigBuilder(); - requestConfigBuilder.setSocketTimeout(soTimeout); - requestConfigBuilder.setConnectTimeout(connectionTimeout); - - method.setConfig(requestConfigBuilder.build()); - - method.setEntity(template); - method.addHeader("User-Agent", HttpSolrClient.USER_AGENT); - method.addHeader("Content-Type", contentType); - - response = - client - .getHttpClient() - .execute(method, HttpClientUtil.createNewHttpClientRequestContext()); - - rspBody = response.getEntity().getContent(); - - int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - StringBuilder msg = new StringBuilder(); - msg.append(response.getStatusLine().getReasonPhrase()); - msg.append("\n\n\n\n"); - msg.append("request: ").append(method.getURI()); - - SolrException solrExc; - Object remoteError = null; - // parse out the metadata from the SolrException - try { - String encoding = "UTF-8"; // default - if (response.getEntity().getContentType().getElements().length > 0) { - NameValuePair param = - response - .getEntity() - .getContentType() - .getElements()[0] - .getParameterByName("charset"); - if (param != null) { - encoding = param.getValue(); - } - } - NamedList resp = client.parser.processResponse(rspBody, encoding); - remoteError = resp.get("error"); - } catch (Exception exc) { - // don't want to fail to report error if parsing the response fails - log.warn("Failed to parse error response from {} due to: ", client.getBaseURL(), exc); - } finally { - solrExc = new RemoteSolrException(client.getBaseURL(), statusCode, remoteError); - } - - handleError(solrExc); - } else { - onSuccess(response); - } - stallDetection.incrementProcessedCount(); - - } finally { - try { - if (response != null) { - HttpClientUtil.consumeFully(response.getEntity()); - } - } catch (Exception e) { - log.error("Error consuming and closing http response stream.", e); - } - notifyQueueAndRunnersIfEmptyQueue(); - } - } - } - } - - private void notifyQueueAndRunnersIfEmptyQueue() { - if (queue.size() == 0) { - synchronized (queue) { - // queue may be empty - queue.notifyAll(); - } - synchronized (runners) { - // we notify runners too - if there is a high queue poll time and this is the update - // that emptied the queue, we make an attempt to avoid the 250ms timeout in - // blockUntilFinished - runners.notifyAll(); - } - } - } - - // *must* be called with runners monitor held, e.g. synchronized(runners){ addRunner() } - private void addRunner() { - MDC.put("ConcurrentUpdateSolrClient.url", client.getBaseURL()); - try { - Runner r = new Runner(); - runners.add(r); - try { - // this can throw an exception if the scheduler has been shutdown, but that should be fine. - scheduler.execute(r); - } catch (RuntimeException e) { - runners.remove(r); - throw e; - } - } finally { - MDC.remove("ConcurrentUpdateSolrClient.url"); - } - } - - /** Class representing an UpdateRequest and an optional collection. */ - static class Update { - UpdateRequest request; - String collection; - - /** - * @param request the update request. - * @param collection The collection, can be null. - */ - public Update(UpdateRequest request, String collection) { - this.request = request; - this.collection = collection; - } - - /** - * @return the update request. - */ - public UpdateRequest getRequest() { - return request; - } - - public void setRequest(UpdateRequest request) { - this.request = request; - } - - /** - * @return the collection, can be null. - */ - public String getCollection() { - return collection; - } - - public void setCollection(String collection) { - this.collection = collection; - } - } - - @Override - public NamedList request(final SolrRequest request, String collection) - throws SolrServerException, IOException { - if (ClientUtils.shouldApplyDefaultCollection(collection, request)) - collection = defaultCollection; - if (!(request instanceof UpdateRequest req)) { - return client.request(request, collection); - } - - // this happens for commit... - if (streamDeletes) { - if ((req.getDocuments() == null || req.getDocuments().isEmpty()) - && (req.getDeleteById() == null || req.getDeleteById().isEmpty()) - && (req.getDeleteByIdMap() == null || req.getDeleteByIdMap().isEmpty())) { - if (req.getDeleteQuery() == null) { - blockUntilFinished(); - return client.request(request, collection); - } - } - } else { - if ((req.getDocuments() == null || req.getDocuments().isEmpty())) { - blockUntilFinished(); - return client.request(request, collection); - } - } - - SolrParams params = req.getParams(); - if (params != null) { - // check if it is waiting for the searcher - if (params.getBool(UpdateParams.WAIT_SEARCHER, false)) { - log.info("blocking for commit/optimize"); - blockUntilFinished(); // empty the queue - return client.request(request, collection); - } - } - - try { - CountDownLatch tmpLock = lock; - if (tmpLock != null) { - tmpLock.await(); - } - - Update update = new Update(req, collection); - boolean success = queue.offer(update); - - for (; ; ) { - synchronized (runners) { - // see if queue is half full, and we can add more runners - // special case: if only using a threadCount of 1 and the queue - // is filling up, allow 1 additional runner to help process the queue - if (runners.isEmpty() - || (queue.remainingCapacity() < queue.size() && runners.size() < threadCount)) { - // We need more runners, so start a new one. - addRunner(); - } else { - // break out of the retry loop if we added the element to the queue - // successfully, *and* - // while we are still holding the runners lock to prevent race - // conditions. - if (success) break; - } - } - - // Retry to add to the queue w/o the runners lock held (else we risk - // temporary deadlock) - // This retry could also fail because - // 1) existing runners were not able to take off any new elements in the - // queue - // 2) the queue was filled back up since our last try - // If we succeed, the queue may have been completely emptied, and all - // runners stopped. - // In all cases, we should loop back to the top to see if we need to - // start more runners. - // - if (!success) { - success = queue.offer(update, 100, TimeUnit.MILLISECONDS); - } - if (!success) { - stallCheck(); - } - } - } catch (InterruptedException e) { - log.error("interrupted", e); - throw new IOException(e.getLocalizedMessage()); - } - - // RETURN A DUMMY result - NamedList dummy = new NamedList<>(); - dummy.add("NOTE", "the request is processed in a background stream"); - return dummy; - } - - void stallCheck() throws IOException { - stallDetection.stallCheck(); - } - - public synchronized void blockUntilFinished() throws IOException { - lock = new CountDownLatch(1); - try { - - waitForEmptyQueue(); - interruptRunnerThreadsPolling(); - - synchronized (runners) { - - // NOTE: if the executor is shut down, runners may never become empty. A scheduled task may - // never be run, which means it would never remove itself from the runners list. This is why - // we don't wait forever and periodically check if the scheduler is shutting down. - int loopCount = 0; - while (!runners.isEmpty()) { - - if (log.isDebugEnabled()) blockLoops.incrementAndGet(); - - if (ExecutorUtil.isShutdown(scheduler)) break; - - loopCount++; - - // Need to check if the queue is empty before really considering this is finished - // (SOLR-4260) - int queueSize = queue.size(); - // stall prevention - only if queue is not empty - if (queueSize > 0) { - stallCheck(); - } - - if (queueSize > 0 && runners.isEmpty()) { - // TODO: can this still happen? - log.warn( - "No more runners, but queue still has {} adding more runners to process remaining requests on queue", - queueSize); - addRunner(); - } - - interruptRunnerThreadsPolling(); - - // try to avoid the worst case wait timeout - // without bad spin - int timeout; - if (loopCount < 3) { - timeout = 10; - } else if (loopCount < 10) { - timeout = 25; - } else { - timeout = 250; - } - - try { - runners.wait(timeout); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } finally { - lock.countDown(); - lock = null; - } - } - - private void waitForEmptyQueue() throws IOException { - boolean threadInterrupted = Thread.currentThread().isInterrupted(); - - while (!queue.isEmpty()) { - if (log.isDebugEnabled()) emptyQueueLoops.incrementAndGet(); - if (ExecutorUtil.isTerminated(scheduler)) { - log.warn( - "The task queue still has elements but the update scheduler {} is terminated. Can't process any more tasks. Queue size: {}, Runners: {}. Current thread Interrupted? {}", - scheduler, - queue.size(), - runners.size(), - threadInterrupted); - break; - } - - synchronized (runners) { - int queueSize = queue.size(); - if (queueSize > 0 && runners.isEmpty()) { - log.warn( - "No more runners, but queue still has {} adding more runners to process remaining requests on queue", - queueSize); - addRunner(); - } - } - synchronized (queue) { - try { - queue.wait(250); - } catch (InterruptedException e) { - // If we set the thread as interrupted again, the next time the wait it's called it's - // going to return immediately - threadInterrupted = true; - log.warn( - "Thread interrupted while waiting for update queue to be empty. There are still {} elements in the queue.", - queue.size()); - } - } - - // Only check for stalls if the queue is not empty - if (!queue.isEmpty()) { - stallCheck(); - } - } - if (threadInterrupted) { - Thread.currentThread().interrupt(); - } - } - - public void handleError(Throwable ex) { - log.error("error", ex); - } - - /** - * Intended to be used as an extension point for doing post-processing after a request completes. - */ - public void onSuccess(HttpResponse resp) { - // no-op by design, override to add functionality - } - - @Override - public synchronized void close() { - if (closed) { - interruptRunnerThreadsPolling(); - return; - } - closed = true; - - try { - if (shutdownExecutor) { - scheduler.shutdown(); - interruptRunnerThreadsPolling(); - try { - if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) { - scheduler.shutdownNow(); - if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) - log.error("ExecutorService did not terminate"); - } - } catch (InterruptedException ie) { - scheduler.shutdownNow(); - Thread.currentThread().interrupt(); - } - } else { - interruptRunnerThreadsPolling(); - } - } finally { - if (internalHttpClient) IOUtils.closeQuietly(client); - if (log.isDebugEnabled()) { - log.debug( - "STATS pollInterrupts={} pollExists={} blockLoops={} emptyQueueLoops={}", - pollInterrupts.get(), - pollExits.get(), - blockLoops.get(), - emptyQueueLoops.get()); - } - } - } - - private void interruptRunnerThreadsPolling() { - synchronized (runners) { - for (Runner runner : runners) { - runner.interruptPoll(); - } - } - } - - public void shutdownNow() { - if (closed) { - return; - } - closed = true; - try { - - if (shutdownExecutor) { - scheduler.shutdown(); - interruptRunnerThreadsPolling(); - scheduler.shutdownNow(); // Cancel currently executing tasks - try { - if (!scheduler.awaitTermination(30, TimeUnit.SECONDS)) - log.error("ExecutorService did not terminate"); - } catch (InterruptedException ie) { - scheduler.shutdownNow(); - Thread.currentThread().interrupt(); - } - } else { - interruptRunnerThreadsPolling(); - } - } finally { - if (internalHttpClient) IOUtils.closeQuietly(client); - } - } - - /** Constructs {@link ConcurrentUpdateSolrClient} instances from provided configuration. */ - public static class Builder extends SolrClientBuilder { - protected String baseSolrUrl; - protected int queueSize = 10; - protected int threadCount; - protected int pollQueueTime = 250; - protected ExecutorService executorService; - protected boolean streamDeletes; - - /** - * Initialize a Builder object, based on the provided Solr URL. - * - *

The provided URL must point to the root Solr path ("/solr"), for example: - * - *

-     *   SolrClient client = new ConcurrentUpdateSolrClient.Builder("http://my-solr-server:8983/solr")
-     *       .withDefaultCollection("core1")
-     *       .build();
-     *   QueryResponse resp = client.query(new SolrQuery("*:*"));
-     * 
- */ - public Builder(String baseSolrUrl) { - this.baseSolrUrl = baseSolrUrl; - } - - /** - * The maximum number of requests buffered by the SolrClient's internal queue before being - * processed by background threads. - * - *

This value should be carefully paired with the number of queue-consumer threads. A queue - * with a maximum size set too high may require more memory. A queue with a maximum size set too - * low may suffer decreased throughput as {@link - * ConcurrentUpdateSolrClient#request(SolrRequest)} calls block waiting to add requests to the - * queue. - * - *

If not set, this defaults to 10. - * - * @see #withThreadCount(int) - */ - public Builder withQueueSize(int queueSize) { - if (queueSize <= 0) { - throw new IllegalArgumentException("queueSize must be a positive integer."); - } - this.queueSize = queueSize; - return this; - } - - /** - * The maximum number of threads used to empty {@link ConcurrentUpdateSolrClient}s queue. - * - *

Threads are created when documents are added to the client's internal queue and exit when - * no updates remain in the queue. - * - *

This value should be carefully paired with the maximum queue capacity. A client with too - * few threads may suffer decreased throughput as the queue fills up and {@link - * ConcurrentUpdateSolrClient#request(SolrRequest)} calls block waiting to add requests to the - * queue. - */ - public Builder withThreadCount(int threadCount) { - if (threadCount <= 0) { - throw new IllegalArgumentException("threadCount must be a positive integer."); - } - - this.threadCount = threadCount; - return this; - } - - public Builder withPollQueueTime(int pollQueueTime) { - this.pollQueueTime = pollQueueTime; - return this; - } - - /** - * Provides the {@link ExecutorService} for the created client to use when servicing the - * update-request queue. - */ - public Builder withExecutorService(ExecutorService executorService) { - this.executorService = executorService; - return this; - } - - /** - * Configures created clients to always stream delete requests. - * - *

Streamed deletes are put into the update-queue and executed like any other update request. - */ - public Builder alwaysStreamDeletes() { - this.streamDeletes = true; - return this; - } - - /** - * Configures created clients to not stream delete requests. - * - *

With this option set when the created ConcurrentUpdateSolrClient sends a delete request it - * will first will lock the queue and block until all queued updates have been sent, and then - * send the delete request. - */ - public Builder neverStreamDeletes() { - this.streamDeletes = false; - return this; - } - - /** Create a {@link ConcurrentUpdateSolrClient} based on the provided configuration options. */ - public ConcurrentUpdateSolrClient build() { - if (baseSolrUrl == null) { - throw new IllegalArgumentException( - "Cannot create HttpSolrClient without a valid baseSolrUrl!"); - } - - return new ConcurrentUpdateSolrClient(this); - } - - @Override - public Builder getThis() { - return this; - } - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpClientUtil.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpClientUtil.java deleted file mode 100644 index 59eea17c280c..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpClientUtil.java +++ /dev/null @@ -1,621 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.invoke.MethodHandles; -import java.lang.reflect.InvocationTargetException; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.zip.GZIPInputStream; -import java.util.zip.InflaterInputStream; -import org.apache.http.Header; -import org.apache.http.HeaderElement; -import org.apache.http.HttpEntity; -import org.apache.http.HttpException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.HttpResponse; -import org.apache.http.HttpResponseInterceptor; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.config.RequestConfig.Builder; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.ConnectionKeepAliveStrategy; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.HttpEntityWrapper; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.protocol.HttpContext; -import org.apache.http.protocol.HttpRequestExecutor; -import org.apache.http.ssl.SSLContexts; -import org.apache.http.util.EntityUtils; -import org.apache.solr.client.solrj.impl.SolrHttpConstants; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.ModifiableSolrParams; -import org.apache.solr.common.params.SolrParams; -import org.apache.solr.common.util.IOUtils; -import org.apache.solr.common.util.ObjectReleaseTracker; -import org.apache.solr.common.util.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Utility class for creating/configuring Apache {@link HttpClient} instances. - * - *

This class can touch internal HttpClient details and is subject to change. - * - * @lucene.experimental - * @deprecated Used to configure the Apache HTTP client. Please use another client - */ -@Deprecated(since = "9.0") -public class HttpClientUtil implements SolrHttpConstants { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private static final int VALIDATE_AFTER_INACTIVITY_DEFAULT = 3000; - private static final int EVICT_IDLE_CONNECTIONS_DEFAULT = 50000; - private static final String VALIDATE_AFTER_INACTIVITY = "validateAfterInactivity"; - private static final String EVICT_IDLE_CONNECTIONS = "evictIdleConnections"; - - // Retry http requests on error - public static final String PROP_USE_RETRY = "retry"; - // Allow compression (deflate,gzip) if server supports it - public static final String PROP_ALLOW_COMPRESSION = "allowCompression"; - - // * NOTE* The following params configure the default request config and this - // is overridden by SolrJ clients. Use the setters on the SolrJ clients - // to configure these settings if that is the intent. - - // Follow redirects - public static final String PROP_FOLLOW_REDIRECTS = "followRedirects"; - - /** - * A Java system property to select the {@linkplain SocketFactoryRegistryProvider} used for - * configuring the Apache HTTP clients. - */ - public static final String SYS_PROP_SOCKET_FACTORY_REGISTRY_PROVIDER = - "solr.httpclient.socketFactory.registry.provider"; - - static final DefaultHttpRequestRetryHandler NO_RETRY = - new DefaultHttpRequestRetryHandler(0, false); - - private static volatile SolrHttpClientBuilder httpClientBuilder; - - private static SolrHttpClientContextBuilder httpClientRequestContextBuilder = - new SolrHttpClientContextBuilder(); - - private static volatile SocketFactoryRegistryProvider socketFactoryRegistryProvider; - private static volatile String cookiePolicy; - private static final List interceptors = new CopyOnWriteArrayList<>(); - - static { - resetHttpClientBuilder(); - - // Configure the SocketFactoryRegistryProvider if user has specified the provider type. - String socketFactoryRegistryProviderClassName = - System.getProperty(SYS_PROP_SOCKET_FACTORY_REGISTRY_PROVIDER); - if (socketFactoryRegistryProviderClassName != null) { - log.debug("Using {}", socketFactoryRegistryProviderClassName); - try { - socketFactoryRegistryProvider = - Class.forName(socketFactoryRegistryProviderClassName) - .asSubclass(SocketFactoryRegistryProvider.class) - .getDeclaredConstructor() - .newInstance(); - } catch (InstantiationException - | IllegalAccessException - | ClassNotFoundException - | InvocationTargetException - | NoSuchMethodException e) { - throw new RuntimeException("Unable to instantiate Solr SocketFactoryRegistryProvider", e); - } - } - } - - public static T executeGET( - HttpClient client, String url, Utils.InputStreamConsumer consumer) throws SolrException { - return executeHttpMethod(client, url, consumer, new HttpGet(url)); - } - - public static T executeHttpMethod( - HttpClient client, - String url, - Utils.InputStreamConsumer consumer, - HttpRequestBase httpMethod) { - T result = null; - HttpResponse rsp; - try { - rsp = client.execute(httpMethod); - } 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)); // nowarn - } 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 { - consumeFully(entity); - } - return result; - } - - /** - * 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 - Utils.readFully(entity.getContent()); - } catch (UnsupportedOperationException e) { - // nothing to do then - } catch (IOException e) { - // quiet - } finally { - // close the stream - EntityUtils.consumeQuietly(entity); - } - } - } - - public abstract static class SocketFactoryRegistryProvider { - /** Must be non-null */ - public abstract Registry getSocketFactoryRegistry(); - } - - private static class DynamicInterceptor implements HttpRequestInterceptor { - - @Override - public void process(HttpRequest request, HttpContext context) - throws HttpException, IOException { - // don't synchronize traversal - can lead to deadlock - CopyOnWriteArrayList is critical - // we also do not want to have to acquire the mutex when the list is empty or put a global - // mutex around the process calls - interceptors.forEach( - new Consumer() { - - @Override - public void accept(HttpRequestInterceptor interceptor) { - try { - interceptor.process(request, context); - } catch (Exception e) { - log.error("", e); - } - } - }); - } - } - - public static void setHttpClientBuilder(SolrHttpClientBuilder newHttpClientBuilder) { - httpClientBuilder = newHttpClientBuilder; - } - - public static void setHttpClientProvider(SolrHttpClientBuilder newHttpClientBuilder) { - httpClientBuilder = newHttpClientBuilder; - } - - /** - * @see #SYS_PROP_CHECK_PEER_NAME - */ - public static void setSocketFactoryRegistryProvider( - SocketFactoryRegistryProvider newRegistryProvider) { - socketFactoryRegistryProvider = newRegistryProvider; - } - - public static SolrHttpClientBuilder getHttpClientBuilder() { - return httpClientBuilder; - } - - /** - * @see #SYS_PROP_CHECK_PEER_NAME - */ - public static SocketFactoryRegistryProvider getSocketFactoryRegistryProvider() { - return socketFactoryRegistryProvider; - } - - public static void resetHttpClientBuilder() { - socketFactoryRegistryProvider = new DefaultSocketFactoryRegistryProvider(); - httpClientBuilder = SolrHttpClientBuilder.create(); - } - - private static final class DefaultSocketFactoryRegistryProvider - extends SocketFactoryRegistryProvider { - @Override - public Registry getSocketFactoryRegistry() { - // this mimics PoolingHttpClientConnectionManager's default behavior, - // except that we explicitly use SSLConnectionSocketFactory.getSystemSocketFactory() - // to pick up the system level default SSLContext (where javax.net.ssl.* properties - // related to keystore & truststore are specified) - RegistryBuilder builder = - RegistryBuilder.create(); - builder.register("http", PlainConnectionSocketFactory.getSocketFactory()); - - // logic to turn off peer host check - SSLConnectionSocketFactory sslConnectionSocketFactory = null; - boolean sslCheckPeerName = - toBooleanDefaultIfNull( - toBooleanObject(System.getProperty(HttpClientUtil.SYS_PROP_CHECK_PEER_NAME)), true); - if (sslCheckPeerName) { - sslConnectionSocketFactory = SSLConnectionSocketFactory.getSystemSocketFactory(); - } else { - sslConnectionSocketFactory = - new SSLConnectionSocketFactory( - SSLContexts.createSystemDefault(), NoopHostnameVerifier.INSTANCE); - log.debug( - "{} is false, hostname checks disabled.", HttpClientUtil.SYS_PROP_CHECK_PEER_NAME); - } - builder.register("https", sslConnectionSocketFactory); - - return builder.build(); - } - } - - /** - * Creates new http client by using the provided configuration. - * - * @param params http client configuration, if null a client with default configuration (no - * additional configuration) is created. - */ - public static CloseableHttpClient createClient(SolrParams params) { - return createClient(params, createPoolingConnectionManager()); - } - - /** test usage subject to change @lucene.experimental */ - static PoolingHttpClientConnectionManager createPoolingConnectionManager() { - return new PoolingHttpClientConnectionManager( - socketFactoryRegistryProvider.getSocketFactoryRegistry()); - } - - public static CloseableHttpClient createClient( - SolrParams params, PoolingHttpClientConnectionManager cm) { - if (params == null) { - params = new ModifiableSolrParams(); - } - - return createClient(params, cm, false); - } - - public static CloseableHttpClient createClient( - final SolrParams params, - PoolingHttpClientConnectionManager cm, - boolean sharedConnectionManager, - HttpRequestExecutor httpRequestExecutor) { - final ModifiableSolrParams config = new ModifiableSolrParams(params); - if (log.isDebugEnabled()) { - log.debug("Creating new http client, config: {}", config); - } - - cm.setMaxTotal(params.getInt(HttpClientUtil.PROP_MAX_CONNECTIONS, 10000)); - cm.setDefaultMaxPerRoute(params.getInt(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 10000)); - cm.setValidateAfterInactivity( - Integer.getInteger(VALIDATE_AFTER_INACTIVITY, VALIDATE_AFTER_INACTIVITY_DEFAULT)); - - HttpClientBuilder newHttpClientBuilder = HttpClientBuilder.create(); - - if (sharedConnectionManager) { - newHttpClientBuilder.setConnectionManagerShared(true); - } else { - newHttpClientBuilder.setConnectionManagerShared(false); - } - - ConnectionKeepAliveStrategy keepAliveStrat = - new ConnectionKeepAliveStrategy() { - @Override - public long getKeepAliveDuration(HttpResponse response, HttpContext context) { - // we only close connections based on idle time, not ttl expiration - return -1; - } - }; - - if (httpClientBuilder.getAuthSchemeRegistryProvider() != null) { - newHttpClientBuilder.setDefaultAuthSchemeRegistry( - httpClientBuilder.getAuthSchemeRegistryProvider().getAuthSchemeRegistry()); - } - if (httpClientBuilder.getCookieSpecRegistryProvider() != null) { - newHttpClientBuilder.setDefaultCookieSpecRegistry( - httpClientBuilder.getCookieSpecRegistryProvider().getCookieSpecRegistry()); - } - if (httpClientBuilder.getCredentialsProviderProvider() != null) { - newHttpClientBuilder.setDefaultCredentialsProvider( - httpClientBuilder.getCredentialsProviderProvider().getCredentialsProvider()); - } - - newHttpClientBuilder.addInterceptorLast(new DynamicInterceptor()); - - newHttpClientBuilder = - newHttpClientBuilder - .setKeepAliveStrategy(keepAliveStrat) - .evictIdleConnections( - (long) Integer.getInteger(EVICT_IDLE_CONNECTIONS, EVICT_IDLE_CONNECTIONS_DEFAULT), - TimeUnit.MILLISECONDS); - - if (httpRequestExecutor != null) { - newHttpClientBuilder.setRequestExecutor(httpRequestExecutor); - } - - HttpClientBuilder builder = setupBuilder(newHttpClientBuilder, params); - - HttpClient httpClient = builder.setConnectionManager(cm).build(); - - assert ObjectReleaseTracker.track(httpClient); - return (CloseableHttpClient) httpClient; - } - - /** Creates new http client by using the provided configuration. */ - public static CloseableHttpClient createClient( - final SolrParams params, - PoolingHttpClientConnectionManager cm, - boolean sharedConnectionManager) { - return createClient(params, cm, sharedConnectionManager, null); - } - - private static HttpClientBuilder setupBuilder(HttpClientBuilder builder, SolrParams config) { - - Builder requestConfigBuilder = - RequestConfig.custom() - .setRedirectsEnabled(config.getBool(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false)) - .setDecompressionEnabled(false) - .setConnectTimeout( - config.getInt(HttpClientUtil.PROP_CONNECTION_TIMEOUT, DEFAULT_CONNECT_TIMEOUT)) - .setSocketTimeout(config.getInt(HttpClientUtil.PROP_SO_TIMEOUT, DEFAULT_SO_TIMEOUT)); - - String cpolicy = cookiePolicy; - if (cpolicy != null) { - requestConfigBuilder.setCookieSpec(cpolicy); - } - - RequestConfig requestConfig = requestConfigBuilder.build(); - - HttpClientBuilder retBuilder = builder.setDefaultRequestConfig(requestConfig); - - if (config.getBool(HttpClientUtil.PROP_USE_RETRY, true)) { - retBuilder = - retBuilder.setRetryHandler( - new SolrHttpRequestRetryHandler(Integer.getInteger("solr.httpclient.retries", 3))); - - } else { - retBuilder = retBuilder.setRetryHandler(NO_RETRY); - } - - final String basicAuthUser = config.get(HttpClientUtil.PROP_BASIC_AUTH_USER); - final String basicAuthPass = config.get(HttpClientUtil.PROP_BASIC_AUTH_PASS); - - if (basicAuthUser != null && basicAuthPass != null) { - CredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(basicAuthUser, basicAuthPass)); - retBuilder.setDefaultCredentialsProvider(credsProvider); - } - - if (config.getBool(HttpClientUtil.PROP_ALLOW_COMPRESSION, false)) { - retBuilder.addInterceptorFirst(new UseCompressionRequestInterceptor()); - retBuilder.addInterceptorFirst(new UseCompressionResponseInterceptor()); - } else { - retBuilder.disableContentCompression(); - } - - retBuilder.useSystemProperties(); - return retBuilder; - } - - public static void close(HttpClient httpClient) { - - IOUtils.closeQuietly((CloseableHttpClient) httpClient); - - assert ObjectReleaseTracker.release(httpClient); - } - - public static void addRequestInterceptor(HttpRequestInterceptor interceptor) { - interceptors.add(interceptor); - } - - public static void removeRequestInterceptor(HttpRequestInterceptor interceptor) { - interceptors.remove(interceptor); - } - - public static void clearRequestInterceptors() { - interceptors.clear(); - } - - private static class UseCompressionRequestInterceptor implements HttpRequestInterceptor { - - @Override - public void process(HttpRequest request, HttpContext context) - throws HttpException, IOException { - if (!request.containsHeader("Accept-Encoding")) { - request.addHeader("Accept-Encoding", "gzip, deflate"); - } - } - } - - private static class UseCompressionResponseInterceptor implements HttpResponseInterceptor { - - @Override - public void process(final HttpResponse response, final HttpContext context) - throws HttpException, IOException { - - HttpEntity entity = response.getEntity(); - Header ceheader = entity.getContentEncoding(); - if (ceheader != null) { - HeaderElement[] codecs = ceheader.getElements(); - for (int i = 0; i < codecs.length; i++) { - if (codecs[i].getName().equalsIgnoreCase("gzip")) { - response.setEntity(new GzipDecompressingEntity(response.getEntity())); - return; - } - if (codecs[i].getName().equalsIgnoreCase("deflate")) { - response.setEntity(new DeflateDecompressingEntity(response.getEntity())); - return; - } - } - } - } - } - - protected static class GzipDecompressingEntity extends HttpEntityWrapper { - private boolean gzipInputStreamCreated = false; - private InputStream gzipInputStream = null; - - public GzipDecompressingEntity(final HttpEntity entity) { - super(entity); - } - - /** - * Return a InputStream of uncompressed data. If there is an issue with the compression of the - * data, a null InputStream will be returned, and the underlying compressed InputStream will be - * closed. - * - *

The same input stream will be returned if the underlying entity is not repeatable. If the - * underlying entity is repeatable, then a new input stream will be created. - */ - @Override - public InputStream getContent() throws IOException, IllegalStateException { - if (!gzipInputStreamCreated || wrappedEntity.isRepeatable()) { - gzipInputStreamCreated = true; - InputStream wrappedContent = wrappedEntity.getContent(); - if (wrappedContent != null) { - try { - gzipInputStream = new GZIPInputStream(wrappedContent); - } catch (IOException ioException) { - try (wrappedContent) { - Utils.readFully(wrappedContent); - } catch (IOException ignored) { - } - throw new IOException("Cannot open GZipInputStream for response", ioException); - } - } - } - return gzipInputStream; - } - - @Override - public long getContentLength() { - return -1; - } - } - - private static class DeflateDecompressingEntity extends GzipDecompressingEntity { - public DeflateDecompressingEntity(final HttpEntity entity) { - super(entity); - } - - @Override - public InputStream getContent() throws IOException, IllegalStateException { - // InflaterInputStream does not throw a ZipException in the constructor, - // so it does not need the same checks as the GZIPInputStream. - return new InflaterInputStream(wrappedEntity.getContent()); - } - } - - public static void setHttpClientRequestContextBuilder( - SolrHttpClientContextBuilder httpClientContextBuilder) { - httpClientRequestContextBuilder = httpClientContextBuilder; - } - - /** - * Create a HttpClientContext object and {@link HttpClientContext#setUserToken(Object)} to an - * internal singleton. It allows reusing underlying {@link HttpClient} in connection pools if - * client authentication is enabled. - */ - public static HttpClientContext createNewHttpClientRequestContext() { - HttpClientContext context = - httpClientRequestContextBuilder.createContext(HttpSolrClient.cacheKey); - - return context; - } - - public static Builder createDefaultRequestConfigBuilder() { - String cpolicy = cookiePolicy; - Builder builder = RequestConfig.custom(); - - builder - .setSocketTimeout(DEFAULT_SO_TIMEOUT) - .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT) - .setRedirectsEnabled(false) - .setDecompressionEnabled(false); // we do our own compression / decompression - if (cpolicy != null) { - builder.setCookieSpec(cpolicy); - } - return builder; - } - - public static void setCookiePolicy(String policyName) { - cookiePolicy = policyName; - } - - /** - * @lucene.internal - */ - static boolean toBooleanDefaultIfNull(Boolean bool, boolean valueIfNull) { - if (bool == null) { - return valueIfNull; - } - return bool.booleanValue() ? true : false; - } - - /** - * @lucene.internal - */ - static Boolean toBooleanObject(String str) { - if ("true".equalsIgnoreCase(str)) { - return Boolean.TRUE; - } else if ("false".equalsIgnoreCase(str)) { - return Boolean.FALSE; - } - // no match - return null; - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpClusterStateProvider.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpClusterStateProvider.java deleted file mode 100644 index 9cbc41899f46..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpClusterStateProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.io.IOException; -import java.util.List; -import org.apache.http.client.HttpClient; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.impl.BaseHttpClusterStateProvider; - -/** - * Retrieves cluster state via Solr HTTP APIs - * - * @deprecated Please use {@link org.apache.solr.client.solrj.impl.HttpClusterStateProvider} - */ -@Deprecated(since = "9.0") -public class HttpClusterStateProvider extends BaseHttpClusterStateProvider { - - private final HttpClient httpClient; - private final boolean clientIsInternal; - - public HttpClusterStateProvider(List solrUrls, HttpClient httpClient) throws Exception { - this.httpClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient; - this.clientIsInternal = httpClient == null; - initConfiguredNodes(solrUrls); - } - - @Override - protected SolrClient getSolrClient(String baseUrl) { - return new HttpSolrClient.Builder().withBaseSolrUrl(baseUrl).withHttpClient(httpClient).build(); - } - - @Override - public void close() throws IOException { - if (this.clientIsInternal && this.httpClient != null) { - HttpClientUtil.close(httpClient); - } - super.close(); - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpSolrClient.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpSolrClient.java deleted file mode 100644 index 76bcd7749a3f..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/HttpSolrClient.java +++ /dev/null @@ -1,873 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.lang.invoke.MethodHandles; -import java.net.ConnectException; -import java.net.SocketTimeoutException; -import java.net.URLDecoder; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Base64; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.stream.Collectors; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpMessage; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.entity.BasicHttpEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.InputStreamEntity; -import org.apache.http.entity.mime.FormBodyPart; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MultipartEntity; -import org.apache.http.entity.mime.content.InputStreamBody; -import org.apache.http.entity.mime.content.StringBody; -import org.apache.http.message.BasicHeader; -import org.apache.http.message.BasicNameValuePair; -import org.apache.solr.client.api.util.SolrVersion; -import org.apache.solr.client.solrj.RemoteSolrException; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.SolrRequest; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.HttpJdkSolrClient; -import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; -import org.apache.solr.client.solrj.request.JavaBinRequestWriter; -import org.apache.solr.client.solrj.request.RequestWriter; -import org.apache.solr.client.solrj.response.InputStreamResponseParser; -import org.apache.solr.client.solrj.response.JavaBinResponseParser; -import org.apache.solr.client.solrj.response.ResponseParser; -import org.apache.solr.client.solrj.util.ClientUtils; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.CommonParams; -import org.apache.solr.common.params.ModifiableSolrParams; -import org.apache.solr.common.params.SolrParams; -import org.apache.solr.common.util.ContentStream; -import org.apache.solr.common.util.ExecutorUtil; -import org.apache.solr.common.util.NamedList; -import org.apache.solr.common.util.SolrNamedThreadFactory; -import org.slf4j.MDC; - -/** - * A SolrClient implementation that talks directly to a Solr server via Apache HTTP client - * - * @deprecated Please use {@link HttpJettySolrClient} or {@link HttpJdkSolrClient} - */ -@Deprecated(since = "9.0") -public class HttpSolrClient extends SolrClient { - - private static final Charset FALLBACK_CHARSET = StandardCharsets.UTF_8; - private static final long serialVersionUID = -946812319974801896L; - - protected static final Set UNMATCHED_ACCEPTED_ERROR_CODES = Set.of(429); - - static final String USER_AGENT = - "Solr[" + MethodHandles.lookup().lookupClass().getName() + "] " + SolrVersion.LATEST_STRING; - - static final Class cacheKey = HttpSolrClient.class; - - /** The URL of the Solr server. */ - protected volatile String baseUrl; - - /** - * Default value: null / empty. - * - *

Parameters that are added to every request regardless. This may be a place to add something - * like an authentication token. - */ - protected ModifiableSolrParams invariantParams; - - /** - * Default response parser is BinaryResponseParser - * - *

This parser represents the default Response Parser chosen to parse the response if the - * parser were not specified as part of the request. - * - * @see JavaBinResponseParser - */ - protected volatile ResponseParser parser; - - /** - * The RequestWriter used to write all requests to Solr - * - * @see org.apache.solr.client.solrj.request.RequestWriter - */ - protected volatile RequestWriter requestWriter = new JavaBinRequestWriter(); - - private final HttpClient httpClient; - - private volatile Boolean followRedirects = false; - - private volatile boolean useMultiPartPost; - private final boolean internalClient; - - private volatile Set urlParamNames = Set.of(); - private final int connectionTimeout; - private final int soTimeout; - - protected HttpSolrClient(Builder builder) { - this.baseUrl = builder.baseSolrUrl; - if (baseUrl.endsWith("/")) { - baseUrl = baseUrl.substring(0, baseUrl.length() - 1); - } - - if (baseUrl.indexOf('?') >= 0) { - throw new RuntimeException( - "Invalid base url for solrj. The base URL must not contain parameters: " + baseUrl); - } - - if (builder.httpClient != null) { - this.internalClient = false; - this.followRedirects = builder.followRedirects; - this.httpClient = builder.httpClient; - } else { - this.internalClient = true; - this.followRedirects = builder.followRedirects; - ModifiableSolrParams params = new ModifiableSolrParams(); - params.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, followRedirects); - params.set(HttpClientUtil.PROP_ALLOW_COMPRESSION, builder.compression); - params.set(HttpClientUtil.PROP_CONNECTION_TIMEOUT, builder.connectionTimeoutMillis); - params.set(HttpClientUtil.PROP_SO_TIMEOUT, builder.socketTimeoutMillis); - httpClient = HttpClientUtil.createClient(params); - } - - if (builder.requestWriter != null) { - this.requestWriter = builder.requestWriter; - } - - this.parser = builder.responseParser; - this.invariantParams = builder.invariantParams; - this.connectionTimeout = builder.connectionTimeoutMillis; - this.soTimeout = builder.socketTimeoutMillis; - this.useMultiPartPost = builder.useMultiPartPost; - this.urlParamNames = builder.urlParamNames; - this.defaultCollection = builder.defaultCollection; - } - - public Set getUrlParamNames() { - return urlParamNames; - } - - /** - * Returns the connection timeout, and should be based on httpClient overriding the solrClient. - * For unit testing. - * - * @return the connection timeout - */ - int getConnectionTimeout() { - return this.connectionTimeout; - } - - /** - * Returns the socket timeout, and should be based on httpClient overriding the solrClient. For - * unit testing. - * - * @return the socket timeout - */ - int getSocketTimeout() { - return this.soTimeout; - } - - /** - * Process the request. If {@link org.apache.solr.client.solrj.SolrRequest#getResponseParser()} is - * null, then use {@link #getParser()} - * - * @param request The {@link org.apache.solr.client.solrj.SolrRequest} to process - * @return The {@link org.apache.solr.common.util.NamedList} result - * @throws IOException If there is a low-level I/O error. - * @see #request(org.apache.solr.client.solrj.SolrRequest, - * org.apache.solr.client.solrj.response.ResponseParser) - */ - @Override - public NamedList request(final SolrRequest request, String collection) - throws SolrServerException, IOException { - ResponseParser responseParser = request.getResponseParser(); - if (responseParser == null) { - responseParser = parser; - } - return request(request, responseParser, collection); - } - - public NamedList request(final SolrRequest request, final ResponseParser processor) - throws SolrServerException, IOException { - return request(request, processor, null); - } - - public NamedList request( - final SolrRequest request, final ResponseParser processor, String collection) - throws SolrServerException, IOException { - if (ClientUtils.shouldApplyDefaultCollection(collection, request)) - collection = defaultCollection; - HttpRequestBase method = createMethod(request, collection); - setBasicAuthHeader(request, method); - if (request.getHeaders() != null) { - Map headers = request.getHeaders(); - for (Map.Entry entry : headers.entrySet()) { - method.setHeader(entry.getKey(), entry.getValue()); - } - } - return executeMethod(method, request.getUserPrincipal(), processor, isV2ApiRequest(request)); - } - - private boolean isV2ApiRequest(final SolrRequest request) { - return request.getApiVersion() == SolrRequest.ApiVersion.V2; - } - - private void setBasicAuthHeader(SolrRequest request, HttpRequestBase method) - throws UnsupportedEncodingException { - if (request.getBasicAuthUser() != null && request.getBasicAuthPassword() != null) { - String userPass = request.getBasicAuthUser() + ":" + request.getBasicAuthPassword(); - String encoded = Base64.getEncoder().encodeToString(userPass.getBytes(FALLBACK_CHARSET)); - method.setHeader(new BasicHeader("Authorization", "Basic " + encoded)); - } - } - - /** - * @lucene.experimental - */ - public static class HttpUriRequestResponse { - public HttpUriRequest httpUriRequest; - public Future> future; - } - - /** - * @lucene.experimental - */ - public HttpUriRequestResponse httpUriRequest(final SolrRequest request) - throws SolrServerException, IOException { - ResponseParser responseParser = request.getResponseParser(); - if (responseParser == null) { - responseParser = parser; - } - return httpUriRequest(request, responseParser); - } - - /** - * @lucene.experimental - */ - public HttpUriRequestResponse httpUriRequest( - final SolrRequest request, final ResponseParser processor) - throws SolrServerException, IOException { - HttpUriRequestResponse mrr = new HttpUriRequestResponse(); - final HttpRequestBase method = createMethod(request, defaultCollection); - ExecutorService pool = - ExecutorUtil.newMDCAwareFixedThreadPool(1, new SolrNamedThreadFactory("httpUriRequest")); - try { - MDC.put("HttpSolrClient.url", baseUrl); - mrr.future = - pool.submit( - () -> - executeMethod( - method, request.getUserPrincipal(), processor, isV2ApiRequest(request))); - - } finally { - pool.shutdown(); - MDC.remove("HttpSolrClient.url"); - } - assert method != null; - mrr.httpUriRequest = method; - return mrr; - } - - protected ModifiableSolrParams calculateQueryParams( - Set queryParamNames, ModifiableSolrParams wparams) { - ModifiableSolrParams queryModParams = new ModifiableSolrParams(); - if (queryParamNames != null) { - for (String param : queryParamNames) { - String[] value = wparams.getParams(param); - if (value != null) { - for (String v : value) { - queryModParams.add(param, v); - } - wparams.remove(param); - } - } - } - return queryModParams; - } - - protected HttpRequestBase createMethod(SolrRequest request, String collection) - throws IOException, SolrServerException { - SolrParams params = request.getParams(); - RequestWriter.ContentWriter contentWriter = requestWriter.getContentWriter(request); - Collection streams = - contentWriter == null ? requestWriter.getContentStreams(request) : null; - - final String requestUrlBeforeParams = ClientUtils.buildRequestUrl(request, baseUrl, collection); - - ResponseParser parser = request.getResponseParser(); - if (parser == null) { - parser = this.parser; - } - - Header[] contextHeaders = buildRequestSpecificHeaders(request); - - // The parser 'wt=' param is used instead of the original params - ModifiableSolrParams wparams = new ModifiableSolrParams(params); - if (parser != null) { - wparams.set(CommonParams.WT, parser.getWriterType()); - } - if (invariantParams != null) { - wparams.add(invariantParams); - } - - if (SolrRequest.METHOD.GET == request.getMethod()) { - if (streams != null || contentWriter != null) { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "GET can't send streams!"); - } - - HttpGet result = new HttpGet(requestUrlBeforeParams + wparams.toQueryString()); - - populateHeaders(result, contextHeaders); - return result; - } - - if (SolrRequest.METHOD.DELETE == request.getMethod()) { - return new HttpDelete(requestUrlBeforeParams + wparams.toQueryString()); - } - - if (SolrRequest.METHOD.POST == request.getMethod() - || SolrRequest.METHOD.PUT == request.getMethod()) { - - boolean hasNullStreamName = false; - if (streams != null) { - for (ContentStream cs : streams) { - if (cs.getName() == null) { - hasNullStreamName = true; - break; - } - } - } - boolean isMultipart = - ((this.useMultiPartPost && SolrRequest.METHOD.POST == request.getMethod()) - || (streams != null && streams.size() > 1)) - && !hasNullStreamName; - - List postOrPutParams = new ArrayList<>(); - - if (contentWriter != null) { - String fullQueryUrl = requestUrlBeforeParams + wparams.toQueryString(); - HttpEntityEnclosingRequestBase postOrPut = - SolrRequest.METHOD.POST == request.getMethod() - ? new HttpPost(fullQueryUrl) - : new HttpPut(fullQueryUrl); - postOrPut.addHeader("Content-Type", contentWriter.getContentType()); - postOrPut.setEntity( - new BasicHttpEntity() { - @Override - public boolean isStreaming() { - return true; - } - - @Override - public void writeTo(OutputStream outstream) throws IOException { - contentWriter.write(outstream); - } - }); - - populateHeaders(postOrPut, contextHeaders); - - return postOrPut; - - } else if (streams == null || isMultipart) { - // send server list and request list as query string params - ModifiableSolrParams queryParams = calculateQueryParams(this.urlParamNames, wparams); - queryParams.add(calculateQueryParams(request.getQueryParams(), wparams)); - String fullQueryUrl = requestUrlBeforeParams + queryParams.toQueryString(); - HttpEntityEnclosingRequestBase postOrPut = - fillContentStream( - request, streams, wparams, isMultipart, postOrPutParams, fullQueryUrl); - return postOrPut; - } - // It is has one stream, it is the post body, put the params in the URL - else { - String fullQueryUrl = requestUrlBeforeParams + wparams.toQueryString(); - HttpEntityEnclosingRequestBase postOrPut = - SolrRequest.METHOD.POST == request.getMethod() - ? new HttpPost(fullQueryUrl) - : new HttpPut(fullQueryUrl); - fillSingleContentStream(streams, postOrPut); - - return postOrPut; - } - } - - throw new SolrServerException("Unsupported method: " + request.getMethod()); - } - - private void fillSingleContentStream( - Collection streams, HttpEntityEnclosingRequestBase postOrPut) - throws IOException { - // Single stream as body - // Using a loop just to get the first one - final ContentStream[] contentStream = new ContentStream[1]; - for (ContentStream content : streams) { - contentStream[0] = content; - break; - } - Long size = contentStream[0].getSize(); - postOrPut.setEntity( - new InputStreamEntity(contentStream[0].getStream(), size == null ? -1 : size) { - @Override - public Header getContentType() { - return new BasicHeader("Content-Type", contentStream[0].getContentType()); - } - - @Override - public boolean isRepeatable() { - return false; - } - }); - } - - private HttpEntityEnclosingRequestBase fillContentStream( - SolrRequest request, - Collection streams, - ModifiableSolrParams wparams, - boolean isMultipart, - List postOrPutParams, - String fullQueryUrl) - throws IOException { - HttpEntityEnclosingRequestBase postOrPut = - SolrRequest.METHOD.POST == request.getMethod() - ? new HttpPost(fullQueryUrl) - : new HttpPut(fullQueryUrl); - - if (!isMultipart) { - postOrPut.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); - } - - List parts = new ArrayList<>(); - Iterator iter = wparams.getParameterNamesIterator(); - while (iter.hasNext()) { - String p = iter.next(); - String[] vals = wparams.getParams(p); - if (vals != null) { - for (String v : vals) { - if (isMultipart) { - parts.add(new FormBodyPart(p, new StringBody(v, StandardCharsets.UTF_8))); - } else { - postOrPutParams.add(new BasicNameValuePair(p, v)); - } - } - } - } - - // TODO: remove deprecated - first simple attempt failed, see {@link MultipartEntityBuilder} - if (isMultipart && streams != null) { - for (ContentStream content : streams) { - String contentType = content.getContentType(); - if (contentType == null) { - contentType = "multipart/form-data"; // default - } - String name = content.getName(); - if (name == null) { - name = ""; - } - parts.add( - new FormBodyPart( - name, - new InputStreamBody( - content.getStream(), ContentType.parse(contentType), content.getName()))); - } - } - - if (parts.size() > 0) { - MultipartEntity entity = new MultipartEntity(HttpMultipartMode.STRICT); - for (FormBodyPart p : parts) { - entity.addPart(p); - } - postOrPut.setEntity(entity); - } else { - // not using multipart - postOrPut.setEntity(new UrlEncodedFormEntity(postOrPutParams, StandardCharsets.UTF_8)); - } - return postOrPut; - } - - // Utils.getObjectByPath(err, false,"metadata/error-class") - private static final List errPath = Arrays.asList("metadata", "error-class"); - - @SuppressWarnings({"unchecked", "rawtypes"}) - protected NamedList executeMethod( - HttpRequestBase method, - Principal userPrincipal, - final ResponseParser processor, - final boolean isV2Api) - throws SolrServerException { - method.addHeader("User-Agent", USER_AGENT); - - RequestConfig.Builder requestConfigBuilder = HttpClientUtil.createDefaultRequestConfigBuilder(); - requestConfigBuilder.setSocketTimeout(soTimeout); - requestConfigBuilder.setConnectTimeout(connectionTimeout); - - if (followRedirects != null) { - requestConfigBuilder.setRedirectsEnabled(followRedirects); - } - - method.setConfig(requestConfigBuilder.build()); - - HttpEntity entity = null; - boolean shouldClose = true; - try { - // Execute the method. - HttpClientContext httpClientRequestContext = - HttpClientUtil.createNewHttpClientRequestContext(); - if (userPrincipal != null) { - // Normally the context contains a static userToken to enable reuse resources. However, if a - // personal Principal object exists, we use that instead, also as a means to transfer - // authentication information to Auth plugins that wish to intercept the request later - httpClientRequestContext.setUserToken(userPrincipal); - } - final HttpResponse response = httpClient.execute(method, httpClientRequestContext); - - int httpStatus = response.getStatusLine().getStatusCode(); - - // Read the contents - entity = response.getEntity(); - String mimeType = null; - Charset charset = null; - String charsetName = null; - - ContentType contentType = ContentType.get(entity); - if (contentType != null) { - mimeType = contentType.getMimeType().trim().toLowerCase(Locale.ROOT); - charset = contentType.getCharset(); - - if (charset != null) { - charsetName = charset.name(); - } - } - - // handle some http level checks before trying to parse the response - switch (httpStatus) { - case HttpStatus.SC_OK: - case HttpStatus.SC_BAD_REQUEST: - case HttpStatus.SC_CONFLICT: // 409 - break; - case HttpStatus.SC_MOVED_PERMANENTLY: - case HttpStatus.SC_MOVED_TEMPORARILY: - if (!followRedirects) { - throw new SolrServerException( - "Server at " + getBaseURL() + " sent back a redirect (" + httpStatus + ")."); - } - break; - default: - if (processor == null || contentType == null) { - throw new RemoteSolrException( - baseUrl, - httpStatus, - "non ok status: " - + httpStatus - + ", message:" - + response.getStatusLine().getReasonPhrase(), - null); - } - } - - InputStream respBody = - (entity == null ? new ByteArrayInputStream(new byte[0]) : entity.getContent()); - if (processor == null || processor instanceof InputStreamResponseParser) { - // no processor specified, return raw stream - final var rsp = - InputStreamResponseParser.createInputStreamNamedList( - response.getStatusLine().getStatusCode(), respBody); - rsp.add("closeableResponse", response); - // Only case where stream should not be closed - shouldClose = false; - return rsp; - } - - final Collection processorSupportedContentTypes = processor.getContentTypes(); - if (!processorSupportedContentTypes.isEmpty()) { - final Collection processorMimeTypes = - processorSupportedContentTypes.stream() - .map(ct -> ContentType.parse(ct).getMimeType().trim().toLowerCase(Locale.ROOT)) - .collect(Collectors.toSet()); - if (!processorMimeTypes.contains(mimeType)) { - if (isUnmatchedErrorCode(mimeType, httpStatus)) { - throw new RemoteSolrException( - baseUrl, - httpStatus, - "non ok status: " - + httpStatus - + ", message:" - + response.getStatusLine().getReasonPhrase(), - null); - } - - // unexpected mime type - final String combinedMimeTypes = String.join(", ", processorMimeTypes); - String prefix = - "Expected mime type in [" + combinedMimeTypes + "] but got " + mimeType + ". "; - Charset exceptionCharset = charset != null ? charset : FALLBACK_CHARSET; - try { - ByteArrayOutputStream body = new ByteArrayOutputStream(); - respBody.transferTo(body); - throw new RemoteSolrException( - baseUrl, httpStatus, prefix + body.toString(exceptionCharset), null); - } catch (IOException e) { - throw new RemoteSolrException( - baseUrl, - httpStatus, - "Could not parse response with encoding " + exceptionCharset, - e); - } - } - } - - NamedList rsp = null; - try { - rsp = processor.processResponse(respBody, charsetName); - } catch (Exception e) { - throw new RemoteSolrException(baseUrl, httpStatus, e.getMessage(), e); - } - Object error = rsp == null ? null : rsp.get("error"); - if (error != null && isV2Api) { - throw new RemoteSolrException(baseUrl, httpStatus, error, true); - } - if (httpStatus != 200 && !isV2Api) { - if (error == null) { - StringBuilder msg = new StringBuilder(); - msg.append(response.getStatusLine().getReasonPhrase()) - .append("\n\n") - .append("request: ") - .append(method.getURI()); - String reason = URLDecoder.decode(msg.toString(), FALLBACK_CHARSET); - throw new RemoteSolrException(baseUrl, httpStatus, reason, null); - } else { - throw new RemoteSolrException(baseUrl, httpStatus, error); - } - } - return rsp; - } catch (ConnectException e) { - throw new SolrServerException("Server refused connection at: " + getBaseURL(), e); - } catch (SocketTimeoutException e) { - throw new SolrServerException( - "Timeout occurred while waiting response from server at: " + getBaseURL(), e); - } catch (IOException e) { - throw new SolrServerException( - "IOException occurred when talking to server at: " + getBaseURL(), e); - } finally { - if (shouldClose) { - HttpClientUtil.consumeFully(entity); - } - } - } - - // When raising an error using HTTP sendError, mime types can be mismatched. This is specifically - // true when SolrServlet uses the sendError mechanism since the expected MIME type of - // response is not HTML but HTTP sendError generates an HTML output, which can lead to mismatch - private boolean isUnmatchedErrorCode(String mimeType, int httpStatus) { - if (mimeType == null) { - return false; - } - - if (mimeType.equalsIgnoreCase("text/html") - && UNMATCHED_ACCEPTED_ERROR_CODES.contains(httpStatus)) { - return true; - } - - return false; - } - - private Header[] buildRequestSpecificHeaders(final SolrRequest request) { - Header[] contextHeaders = new Header[2]; - - // TODO: validate request context here: https://issues.apache.org/jira/browse/SOLR-14720 - contextHeaders[0] = - new BasicHeader(CommonParams.SOLR_REQUEST_CONTEXT_PARAM, getContext().toString()); - - contextHeaders[1] = - new BasicHeader(CommonParams.SOLR_REQUEST_TYPE_PARAM, request.getRequestType().toString()); - - return contextHeaders; - } - - private void populateHeaders(HttpMessage message, Header[] contextHeaders) { - message.addHeader(contextHeaders[0]); - message.addHeader(contextHeaders[1]); - } - - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - - /** - * Retrieve the default list of parameters are added to every request regardless. - * - * @see #invariantParams - */ - public ModifiableSolrParams getInvariantParams() { - return invariantParams; - } - - /** Typically looks like {@code http://localhost:8983/solr} (no core or collection) */ - public String getBaseURL() { - return baseUrl; - } - - public ResponseParser getParser() { - return parser; - } - - /** Return the HttpClient this instance uses. */ - public HttpClient getHttpClient() { - return httpClient; - } - - /** Close the {@link HttpClientConnectionManager} from the internal client. */ - @Override - public void close() throws IOException { - if (httpClient != null && internalClient) { - HttpClientUtil.close(httpClient); - } - } - - public boolean isUseMultiPartPost() { - return useMultiPartPost; - } - - /** - * Constructs {@link HttpSolrClient} instances from provided configuration. - * - * @deprecated Please use {@link HttpJettySolrClient} - */ - @Deprecated(since = "9.0") - public static class Builder extends SolrClientBuilder { - protected String baseSolrUrl; - protected boolean compression; - protected ModifiableSolrParams invariantParams = new ModifiableSolrParams(); - - public Builder() { - this.responseParser = new JavaBinResponseParser(); - } - - /** - * Specify the base-url for the created client to use when sending requests to Solr. - * - *

The provided URL must point to the root Solr path ("/solr"), for example: - * - *

-     *   SolrClient client = new HttpSolrClient.Builder()
-     *       .withBaseSolrUrl("http://my-solr-server:8983/solr")
-     *       .withDefaultCollection("core1")
-     *       .build();
-     *   QueryResponse resp = client.query(new SolrQuery("*:*"));
-     * 
- */ - public Builder withBaseSolrUrl(String baseSolrUrl) { - this.baseSolrUrl = baseSolrUrl; - return this; - } - - /** - * Initialize a Builder object, based on the provided Solr URL. - * - *

The provided URL must point to the root Solr path ("/solr"), for example: - * - *

-     *   SolrClient client = new HttpSolrClient.Builder("http://my-solr-server:8983/solr")
-     *       .withDefaultCollection("core1")
-     *       .build();
-     *   QueryResponse resp = client.query(new SolrQuery("*:*"));
-     * 
- * - *

By default, compression is not enabled on created HttpSolrClient objects. By default, - * redirects are not followed in created HttpSolrClient objects. By default, {@link - * JavaBinRequestWriter} is used for composing requests. By default, {@link - * JavaBinResponseParser} is used for parsing responses. - * - * @param baseSolrUrl a URL to the root Solr path (i.e. "/solr") that will be targeted by any - * created clients. - */ - public Builder(String baseSolrUrl) { - this.baseSolrUrl = baseSolrUrl; - this.responseParser = new JavaBinResponseParser(); - } - - /** Chooses whether created clients use compression by default. */ - public Builder allowCompression(boolean compression) { - this.compression = compression; - return this; - } - - /** - * Adds to the set of params that the created client will add on all requests - * - * @param params a set of parameters to add to the invariant-params list. These params must be - * unique and may not duplicate a param already in the invariant list. - */ - public Builder withInvariantParams(ModifiableSolrParams params) { - Objects.requireNonNull(params, "params must be non null!"); - - for (String name : params.getParameterNames()) { - if (this.invariantParams.get(name) != null) { - throw new IllegalStateException("parameter " + name + " is redefined."); - } - } - - this.invariantParams.add(params); - return this; - } - - /** Create a {@link HttpSolrClient} based on provided configuration. */ - public HttpSolrClient build() { - if (baseSolrUrl == null) { - throw new IllegalArgumentException( - "Cannot create HttpSolrClient without a valid baseSolrUrl!"); - } - - return new HttpSolrClient(this); - } - - @Override - public Builder getThis() { - return this; - } - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/LBHttpSolrClient.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/LBHttpSolrClient.java deleted file mode 100644 index 7a9670722e39..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/LBHttpSolrClient.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import org.apache.http.client.HttpClient; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.impl.CloudSolrClient; -import org.apache.solr.client.solrj.impl.LBSolrClient; -import org.apache.solr.client.solrj.response.JavaBinResponseParser; -import org.apache.solr.common.params.ModifiableSolrParams; - -/** - * LBHttpSolrClient or "LoadBalanced HttpSolrClient" is a load balancing wrapper around {@link - * HttpSolrClient}. This is useful when you have multiple Solr servers (also called endpoints) and - * requests need to be Load Balanced among them. - * - *

Do NOT use this class for indexing in leader/follower scenarios since documents must be - * sent to the correct leader; no inter-node routing is done. - * - *

In SolrCloud (leader/replica) scenarios, it is usually better to use {@link CloudSolrClient}, - * but this class may be used for updates because the server will forward them to the appropriate - * leader. - * - *

It offers automatic failover when a server goes down, and it detects when the server comes - * back up. - * - *

Load balancing is done using a simple round-robin on the list of endpoints. Endpoint URLs are - * expected to point to the Solr "root" path (i.e. "/solr"). - * - *

- * - *
- * SolrClient lbHttpSolrClient = new LBHttpSolrClient.Builder()
- *     .withBaseEndpoints("http://host1:8080/solr", "http://host2:8080/solr", "http://host3:8080/solr")
- *     .build();
- * 
- * - *
- * - * Users who wish to balance traffic across a specific set of replicas or cores may specify each - * endpoint as a root-URL and core-name pair. For example: - * - *
- * - *
- * SolrClient lbHttpSolrClient = new LBHttpSolrClient.Builder()
- *     .withCollectionEndpoint("http://host1:8080/solr", "coreA")
- *     .withCollectionEndpoint("http://host2:8080/solr", "coreB")
- *     .withCollectionEndpoint("http://host3:8080/solr", "coreC")
- *     .build();
- * // Or, if you wish to provide all endpoints together:
- * lbHttpSolrClient = new LBHttpSolrClient.Builder()
- *     .withCollectionEndpoints(
- *         new LBSolrClient.Endpoint("http://host1:8080/solr", "coreA"),
- *         new LBSolrClient.Endpoint("http://host2:8080/solr", "coreB"),
- *         new LBSolrClient.Endpoint("http://host3:8080/solr", "coreC"))
- *     .build();
- * 
- * - *
- * - *

If a request to an endpoint fails by an IOException due to a connection timeout or read - * timeout then the host is taken off the list of live endpoints and moved to a 'dead endpoint list' - * and the request is resent to the next live endpoint. This process is continued till it tries all - * the live endpoints. If at least one endpoint is alive, the request succeeds, and if not it fails. - * - *

Dead endpoints are periodically healthchecked on a fixed interval controlled by {@link - * LBHttpSolrClient.Builder#setAliveCheckInterval(int)}. The default is set to one minute. - * - *

When to use this?
- * This can be used as a software load balancer when you do not wish to set up an external load - * balancer. Alternatives to this code are to use a dedicated hardware load balancer or using Apache - * httpd with mod_proxy_balancer as a load balancer. See Load balancing on Wikipedia - * - * @since solr 1.4 - * @deprecated Not supporting Apache HttpClient based implementations anymore - */ -@Deprecated(since = "9.0") -public class LBHttpSolrClient extends LBSolrClient { - - private final HttpClient httpClient; - private final boolean clientIsInternal; - private final ConcurrentHashMap urlToClient = new ConcurrentHashMap<>(); - private final HttpSolrClient.Builder httpSolrClientBuilder; - private volatile Set urlParamNames = new HashSet<>(); - - final int connectionTimeoutMillis; - final int soTimeoutMillis; - - /** The provided httpClient should use a multi-threaded connection manager */ - protected LBHttpSolrClient(Builder builder) { - super(builder.solrEndpoints); - this.clientIsInternal = builder.httpClient == null; - this.httpSolrClientBuilder = builder.httpSolrClientBuilder; - this.httpClient = - builder.httpClient == null ? constructClient(builder.solrEndpoints) : builder.httpClient; - this.defaultCollection = builder.defaultCollection; - if (httpSolrClientBuilder != null && this.defaultCollection != null) { - httpSolrClientBuilder.defaultCollection = this.defaultCollection; - } - this.connectionTimeoutMillis = builder.connectionTimeoutMillis; - this.soTimeoutMillis = builder.socketTimeoutMillis; - this.parser = builder.responseParser; - this.aliveCheckIntervalMillis = builder.aliveCheckInterval; - for (Endpoint endpoint : builder.solrEndpoints) { - urlToClient.put(endpoint.toString(), makeSolrClient(endpoint)); - } - } - - private HttpClient constructClient(List solrEndpoints) { - ModifiableSolrParams params = new ModifiableSolrParams(); - if (solrEndpoints != null && solrEndpoints.size() > 1) { - // we prefer retrying another server - params.set(HttpClientUtil.PROP_USE_RETRY, false); - } else { - params.set(HttpClientUtil.PROP_USE_RETRY, true); - } - return HttpClientUtil.createClient(params); - } - - protected HttpSolrClient makeSolrClient(Endpoint server) { - HttpSolrClient client; - if (httpSolrClientBuilder != null) { - synchronized (this) { - httpSolrClientBuilder - .withBaseSolrUrl(server.getBaseUrl()) - .withDefaultCollection(server.getCore()) - .withHttpClient(httpClient) - .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS) - .withSocketTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS); - if (defaultCollection != null) { - httpSolrClientBuilder.withDefaultCollection(defaultCollection); - } - if (requestWriter != null) { - httpSolrClientBuilder.withRequestWriter(requestWriter); - } - if (urlParamNames != null) { - httpSolrClientBuilder.withTheseParamNamesInTheUrl(urlParamNames); - } - client = httpSolrClientBuilder.build(); - } - } else { - final var clientBuilder = - new HttpSolrClient.Builder(server.getBaseUrl()) - .withDefaultCollection(server.getCore()) - .withHttpClient(httpClient) - .withResponseParser(parser) - .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS) - .withSocketTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS); - if (defaultCollection != null) { - clientBuilder.withDefaultCollection(defaultCollection); - } - if (requestWriter != null) { - clientBuilder.withRequestWriter(requestWriter); - } - if (urlParamNames != null) { - clientBuilder.withTheseParamNamesInTheUrl(urlParamNames); - } - client = clientBuilder.build(); - } - - return client; - } - - @Override - protected SolrClient getClient(Endpoint endpoint) { - SolrClient client = urlToClient.get(endpoint.toString()); - if (client == null) { - return makeSolrClient(endpoint); - } else { - return client; - } - } - - @Override - public synchronized String removeSolrServer(Endpoint server) { - urlToClient.remove(server.toString()); - return super.removeSolrServer(server); - } - - @Override - public void close() { - super.close(); - if (clientIsInternal) { - HttpClientUtil.close(httpClient); - } - } - - /** Return the HttpClient this instance uses. */ - public HttpClient getHttpClient() { - return httpClient; - } - - /** Constructs {@link LBHttpSolrClient} instances from provided configuration. */ - public static class Builder extends SolrClientBuilder { - - public static final int CHECK_INTERVAL = 60 * 1000; // 1 minute between checks - protected final List solrEndpoints; - protected HttpSolrClient.Builder httpSolrClientBuilder; - private int aliveCheckInterval = CHECK_INTERVAL; - - public Builder() { - this.solrEndpoints = new ArrayList<>(); - this.responseParser = new JavaBinResponseParser(); - } - - public HttpSolrClient.Builder getHttpSolrClientBuilder() { - return httpSolrClientBuilder; - } - - /** - * Provide a "base" Solr URL to be used when configuring {@link LBHttpSolrClient} instances. - * - *

Method may be called multiple times. All provided values will be used. However, all - * endpoints must be of the same type: providing a mix of"base" endpoints via this method and - * core/collection endpoints via {@link #withCollectionEndpoint(String, String)} is prohibited. - * - *

Users who use this method to provide base Solr URLs may specify a "default collection" for - * their requests using {@link #withDefaultCollection(String)} if they wish to avoid needing to - * specify a collection or core on relevant requests. - * - * @param baseSolrUrl the base URL for a Solr node, in the form "http[s]://hostname:port/solr" - */ - public Builder withBaseEndpoint(String baseSolrUrl) { - solrEndpoints.add(new Endpoint(baseSolrUrl)); - return this; - } - - /** - * Provide multiple "base" Solr URLs to be used when configuring {@link LBHttpSolrClient} - * instances. - * - *

Method may be called multiple times. All provided values will be used. However, all - * endpoints must be of the same type: providing a mix of"base" endpoints via this method and - * core/collection endpoints via {@link #withCollectionEndpoint(String, String)} is prohibited. - * - *

Users who use this method to provide base Solr URLs may specify a "default collection" for - * their requests using {@link #withDefaultCollection(String)} if they wish to avoid needing to - * specify a collection or core on relevant requests. - * - * @param baseSolrUrls Solr base URLs, in the form "http[s]://hostname:port/solr" - */ - public Builder withBaseEndpoints(String... baseSolrUrls) { - for (String baseSolrUrl : baseSolrUrls) { - solrEndpoints.add(new Endpoint(baseSolrUrl)); - } - return this; - } - - /** - * Provide a core/collection Solr endpoint to be used when configuring {@link LBHttpSolrClient} - * instances. - * - *

Method may be called multiple times. All provided values will be used. However, all - * endpoints must be of the same type: providing a mix of "core" endpoints via this method and - * base endpoints via {@link #withBaseEndpoint(String)} is prohibited. - * - * @param baseSolrUrl the base URL for a Solr node, in the form "http[s]://hostname:port/solr" - * @param core the Solr core or collection to target - */ - public Builder withCollectionEndpoint(String baseSolrUrl, String core) { - solrEndpoints.add(new Endpoint(baseSolrUrl, core)); - return this; - } - - /** - * Provide multiple core/collection endpoints to be used when configuring {@link - * LBHttpSolrClient} instances. - * - *

Method may be called multiple times. All provided values will be used. However, all - * endpoints must be of the same type: providing a mix of "core" endpoints via this method and - * base endpoints via {@link #withBaseEndpoint(String)} is prohibited. - * - * @param endpoints endpoint instances pointing to distinct cores/collections - */ - public Builder withCollectionEndpoints(Endpoint... endpoints) { - if (endpoints != null) { - for (Endpoint e : endpoints) { - solrEndpoints.add(e); - } - } - - return this; - } - - /** - * LBHttpSolrServer keeps pinging the dead servers at fixed interval to find if it is alive. Use - * this to set that interval - * - * @param aliveCheckInterval time in milliseconds - */ - public Builder setAliveCheckInterval(int aliveCheckInterval) { - if (aliveCheckInterval <= 0) { - throw new IllegalArgumentException( - "Alive check interval must be " + "positive, specified value = " + aliveCheckInterval); - } - this.aliveCheckInterval = aliveCheckInterval; - return this; - } - - /** - * Provides a {@link HttpSolrClient.Builder} to be used for building the internally used - * clients. - */ - public Builder withHttpSolrClientBuilder(HttpSolrClient.Builder builder) { - this.httpSolrClientBuilder = builder; - return this; - } - - /** Create a {@link LBHttpSolrClient} based on provided configuration. */ - public LBHttpSolrClient build() { - return new LBHttpSolrClient(this); - } - - @Override - public Builder getThis() { - return this; - } - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/PreemptiveAuth.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/PreemptiveAuth.java deleted file mode 100644 index 26d02e20b07d..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/PreemptiveAuth.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.io.IOException; -import org.apache.http.HttpException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.auth.AuthScheme; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.AuthState; -import org.apache.http.auth.Credentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.protocol.ClientContext; -import org.apache.http.protocol.HttpContext; - -/** - * This HTTP request interceptor adds HTTP authentication credentials to every outgoing request. - * This implementation is required since Solr client is not capable of performing non preemptive - * authentication. By adding the Http authentication credentials to every request, this interceptor - * enables "preemptive" authentication. - * - * @deprecated Please look into using Solr's new Http2 clients - */ -@Deprecated(since = "9.0") -public class PreemptiveAuth implements HttpRequestInterceptor { - private AuthScheme authScheme = null; - - public PreemptiveAuth(AuthScheme authScheme) { - this.authScheme = authScheme; - } - - @Override - public void process(final HttpRequest request, final HttpContext context) - throws HttpException, IOException { - - AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); - // If no auth scheme available yet, try to initialize it preemptively - if (authState.getAuthScheme() == null) { - CredentialsProvider credsProvider = - (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER); - Credentials creds = credsProvider.getCredentials(AuthScope.ANY); - authState.update(authScheme, creds); - } - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrClientBuilder.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrClientBuilder.java deleted file mode 100644 index c12bafd88e36..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrClientBuilder.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.util.Set; -import java.util.concurrent.TimeUnit; -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.Configurable; -import org.apache.solr.client.solrj.apache.HttpSolrClient.Builder; -import org.apache.solr.client.solrj.request.RequestWriter; -import org.apache.solr.client.solrj.response.ResponseParser; - -/** - * @deprecated Please look into using Solr's new Http2 clients - */ -@Deprecated(since = "9.0") -public abstract class SolrClientBuilder> { - - protected int timeToLiveSeconds = 60; - protected HttpClient httpClient; - protected ResponseParser responseParser; - protected RequestWriter requestWriter; - protected boolean useMultiPartPost; - protected int connectionTimeoutMillis = 15000; // 15 seconds - private boolean connectionTimeoutMillisUpdate = false; - protected int socketTimeoutMillis = 120000; // 120 seconds - private boolean socketTimeoutMillisUpdate = false; - protected boolean followRedirects = false; - protected String defaultCollection; - protected Set urlParamNames; - - /** The solution for the unchecked cast warning. */ - public abstract B getThis(); - - /** Provides a {@link HttpClient} for the builder to use when creating clients. */ - public B withHttpClient(HttpClient httpClient) { - this.httpClient = httpClient; - - if (this.httpClient instanceof Configurable) { - RequestConfig conf = ((Configurable) httpClient).getConfig(); - // only update values that were not already manually changed - if (!connectionTimeoutMillisUpdate && conf.getConnectTimeout() > 0) { - this.connectionTimeoutMillis = conf.getConnectTimeout(); - } - if (!socketTimeoutMillisUpdate && conf.getSocketTimeout() > 0) { - this.socketTimeoutMillis = conf.getSocketTimeout(); - } - } - return getThis(); - } - - /** Provides a {@link ResponseParser} for created clients to use when handling requests. */ - public B withResponseParser(ResponseParser responseParser) { - this.responseParser = responseParser; - return getThis(); - } - - /** Provides a {@link RequestWriter} for created clients to use when handing requests. */ - public B withRequestWriter(RequestWriter requestWriter) { - this.requestWriter = requestWriter; - return getThis(); - } - - /** Enables or disables splitting POST requests into pieces. */ - public B allowMultiPartPost(Boolean useMultiPartPost) { - this.useMultiPartPost = useMultiPartPost; - return getThis(); - } - - /** - * Provides a set of keys which the created client will send as a part of the query string. - * - * @param queryParams set of param keys to only send via the query string Note that the param will - * be sent as a query string if the key is part of this Set or the SolrRequest's query params. - */ - public B withTheseParamNamesInTheUrl(Set queryParams) { - this.urlParamNames = queryParams; - return getThis(); - } - - public B withFollowRedirects(boolean followRedirects) { - this.followRedirects = followRedirects; - return getThis(); - } - - /** Sets a default for core or collection based requests. */ - public B withDefaultCollection(String defaultCoreOrCollection) { - this.defaultCollection = defaultCoreOrCollection; - return getThis(); - } - - /** - * Tells {@link Builder} that created clients should obey the following timeout when connecting to - * Solr servers. - * - *

For valid values see {@link org.apache.http.client.config.RequestConfig#getConnectTimeout()} - * - * @deprecated Please use {@link #withConnectionTimeout(int, TimeUnit)} - */ - @Deprecated(since = "9.2") - public B withConnectionTimeout(int connectionTimeoutMillis) { - withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS); - return getThis(); - } - - /** - * Tells {@link Builder} that created clients should obey the following timeout when connecting to - * Solr servers. - * - *

For valid values see {@link org.apache.http.client.config.RequestConfig#getConnectTimeout()} - */ - public B withConnectionTimeout(int connectionTimeout, TimeUnit unit) { - if (connectionTimeout < 0) { - throw new IllegalArgumentException("connectionTimeout must be a non-negative integer."); - } - this.connectionTimeoutMillis = - Math.toIntExact(TimeUnit.MILLISECONDS.convert(connectionTimeout, unit)); - connectionTimeoutMillisUpdate = true; - return getThis(); - } - - public int getConnectionTimeoutMillis() { - return this.connectionTimeoutMillis; - } - - /** - * Tells {@link Builder} that created clients should set the following read timeout on all - * sockets. - * - *

For valid values see {@link org.apache.http.client.config.RequestConfig#getSocketTimeout()} - * - *

* @deprecated Please use {@link #withSocketTimeout(int, TimeUnit)} - */ - @Deprecated(since = "9.2") - public B withSocketTimeout(int socketTimeoutMillis) { - withSocketTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS); - return getThis(); - } - - /** - * Tells {@link Builder} that created clients should set the following read timeout on all - * sockets. - * - *

For valid values see {@link org.apache.http.client.config.RequestConfig#getSocketTimeout()} - */ - public B withSocketTimeout(int socketTimeout, TimeUnit unit) { - if (socketTimeout < 0) { - throw new IllegalArgumentException("socketTimeout must be a non-negative integer."); - } - this.socketTimeoutMillis = Math.toIntExact(TimeUnit.MILLISECONDS.convert(socketTimeout, unit)); - socketTimeoutMillisUpdate = true; - return getThis(); - } - - public int getSocketTimeoutMillis() { - return this.socketTimeoutMillis; - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpClientBuilder.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpClientBuilder.java deleted file mode 100644 index 6139c8d19b8b..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpClientBuilder.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.client.solrj.apache; - -import org.apache.http.auth.AuthSchemeProvider; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.config.Lookup; -import org.apache.http.cookie.CookieSpecProvider; - -/** - * Builder class for configuring internal HttpClients. This relies on the internal HttpClient - * implementation and is subject to change. - * - * @lucene.experimental - * @deprecated Please look into using Solr's new Http2 clients - */ -@Deprecated(since = "9.0") -public class SolrHttpClientBuilder { - public static SolrHttpClientBuilder create() { - return new SolrHttpClientBuilder(); - } - - public interface CredentialsProviderProvider { - CredentialsProvider getCredentialsProvider(); - } - - public interface AuthSchemeRegistryProvider { - Lookup getAuthSchemeRegistry(); - } - - public interface CookieSpecRegistryProvider { - Lookup getCookieSpecRegistry(); - } - - private CookieSpecRegistryProvider cookieSpecRegistryProvider; - private AuthSchemeRegistryProvider authSchemeRegistryProvider; - private CredentialsProviderProvider credentialsProviderProvider; - - protected SolrHttpClientBuilder() { - super(); - } - - public final SolrHttpClientBuilder setCookieSpecRegistryProvider( - final CookieSpecRegistryProvider cookieSpecRegistryProvider) { - this.cookieSpecRegistryProvider = cookieSpecRegistryProvider; - return this; - } - - public final SolrHttpClientBuilder setDefaultCredentialsProvider( - final CredentialsProviderProvider credentialsProviderProvider) { - this.credentialsProviderProvider = credentialsProviderProvider; - return this; - } - - public final SolrHttpClientBuilder setAuthSchemeRegistryProvider( - final AuthSchemeRegistryProvider authSchemeRegistryProvider) { - this.authSchemeRegistryProvider = authSchemeRegistryProvider; - return this; - } - - public AuthSchemeRegistryProvider getAuthSchemeRegistryProvider() { - return authSchemeRegistryProvider; - } - - public CookieSpecRegistryProvider getCookieSpecRegistryProvider() { - return cookieSpecRegistryProvider; - } - - public CredentialsProviderProvider getCredentialsProviderProvider() { - return credentialsProviderProvider; - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpClientContextBuilder.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpClientContextBuilder.java deleted file mode 100644 index 5f50d309cc38..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpClientContextBuilder.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.client.solrj.apache; - -import org.apache.http.auth.AuthSchemeProvider; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.config.Lookup; -import org.apache.http.cookie.CookieSpecProvider; - -/** - * @deprecated Please look into using Solr's new Http2 clients - */ -@Deprecated(since = "9.0") -public class SolrHttpClientContextBuilder { - public static SolrHttpClientContextBuilder create() { - return new SolrHttpClientContextBuilder(); - } - - public abstract static class CredentialsProviderProvider { - public abstract CredentialsProvider getCredentialsProvider(); - } - - public abstract static class AuthSchemeRegistryProvider { - public abstract Lookup getAuthSchemeRegistry(); - } - - public abstract static class CookieSpecRegistryProvider { - public abstract Lookup getCookieSpecRegistry(); - } - - private CookieSpecRegistryProvider cookieSpecRegistryProvider; - private AuthSchemeRegistryProvider authSchemeRegistryProvider; - private CredentialsProviderProvider credentialsProviderProvider; - - public SolrHttpClientContextBuilder() { - super(); - } - - public final SolrHttpClientContextBuilder setCookieSpecRegistryProvider( - final CookieSpecRegistryProvider cookieSpecRegistryProvider) { - this.cookieSpecRegistryProvider = cookieSpecRegistryProvider; - return this; - } - - public final SolrHttpClientContextBuilder setDefaultCredentialsProvider( - final CredentialsProviderProvider credentialsProviderProvider) { - this.credentialsProviderProvider = credentialsProviderProvider; - return this; - } - - public final SolrHttpClientContextBuilder setAuthSchemeRegistryProvider( - final AuthSchemeRegistryProvider authSchemeRegistryProvider) { - this.authSchemeRegistryProvider = authSchemeRegistryProvider; - return this; - } - - public AuthSchemeRegistryProvider getAuthSchemeRegistryProvider() { - return authSchemeRegistryProvider; - } - - public CookieSpecRegistryProvider getCookieSpecRegistryProvider() { - return cookieSpecRegistryProvider; - } - - public CredentialsProviderProvider getCredentialsProviderProvider() { - return credentialsProviderProvider; - } - - public HttpClientContext createContext(Object userToken) { - HttpClientContext context = new HttpClientContext(); - if (getCredentialsProviderProvider() != null) { - context.setCredentialsProvider(getCredentialsProviderProvider().getCredentialsProvider()); - } - if (getAuthSchemeRegistryProvider() != null) { - context.setAuthSchemeRegistry(getAuthSchemeRegistryProvider().getAuthSchemeRegistry()); - } - - if (getCookieSpecRegistryProvider() != null) { - context.setCookieSpecRegistry(getCookieSpecRegistryProvider().getCookieSpecRegistry()); - } - - context.setUserToken(userToken); - - return context; - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpRequestRetryHandler.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpRequestRetryHandler.java deleted file mode 100644 index b3bb70a014ca..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrHttpRequestRetryHandler.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.lang.invoke.MethodHandles; -import java.net.ConnectException; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import javax.net.ssl.SSLException; -import org.apache.http.HttpRequest; -import org.apache.http.client.HttpRequestRetryHandler; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.impl.client.RequestWrapper; -import org.apache.http.protocol.HttpContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @deprecated Please look into using Solr's new Http2 clients - */ -@Deprecated(since = "9.0") -public class SolrHttpRequestRetryHandler implements HttpRequestRetryHandler { - - private static final String GET = "GET"; - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - public static final SolrHttpRequestRetryHandler INSTANCE = new SolrHttpRequestRetryHandler(); - - /** the number of times a method will be retried */ - private final int retryCount; - - private final Set> nonRetryableClasses; - - /** - * Create the request retry handler using the specified IOException classes - * - * @param retryCount how many times to retry; 0 means no retries true if it's OK to retry requests - * that have been sent - * @param clazzes the IOException types that should not be retried - */ - protected SolrHttpRequestRetryHandler( - final int retryCount, final Collection> clazzes) { - super(); - this.retryCount = retryCount; - this.nonRetryableClasses = new HashSet<>(); - for (final Class clazz : clazzes) { - this.nonRetryableClasses.add(clazz); - } - } - - /** - * Create the request retry handler using the following list of non-retryable IOException classes: - *
- * - *

    - *
  • InterruptedIOException - *
  • UnknownHostException - *
  • ConnectException - *
  • SSLException - *
- * - * @param retryCount how many times to retry; 0 means no retries true if it's OK to retry - * non-idempotent requests that have been sent - */ - public SolrHttpRequestRetryHandler(final int retryCount) { - this( - retryCount, - Arrays.asList( - InterruptedIOException.class, - UnknownHostException.class, - ConnectException.class, - SSLException.class)); - } - - /** - * Create the request retry handler with a retry count of 3, requestSentRetryEnabled false and - * using the following list of non-retryable IOException classes:
- * - *
    - *
  • InterruptedIOException - *
  • UnknownHostException - *
  • ConnectException - *
  • SSLException - *
- */ - public SolrHttpRequestRetryHandler() { - this(3); - } - - @Override - public boolean retryRequest( - final IOException exception, final int executionCount, final HttpContext context) { - log.debug("Retry http request {} out of {}", executionCount, this.retryCount); - if (executionCount > this.retryCount) { - log.debug("Do not retry, over max retry count"); - return false; - } - - if (!isRetryable(exception)) { - if (log.isDebugEnabled()) { - log.debug("Do not retry, non retryable class {}", exception.getClass().getName()); - } - return false; - } - - final HttpClientContext clientContext = HttpClientContext.adapt(context); - final HttpRequest request = clientContext.getRequest(); - - if (requestIsAborted(request)) { - log.debug("Do not retry, request was aborted"); - return false; - } - - if (handleAsIdempotent(clientContext)) { - log.debug("Retry, request should be idempotent"); - return true; - } - - log.debug("Do not retry, no allow rules matched"); - return false; - } - - private boolean isRetryable(IOException exception) { - // Workaround for "recv failed" issue on hard-aborted sockets on Windows - // (and other operating systems, possibly). - // https://issues.apache.org/jira/browse/SOLR-13778 - if (exception instanceof SSLException - && Arrays.stream(exception.getSuppressed()).anyMatch((t) -> t instanceof SocketException)) { - return true; - } - - // Fast check for exact class followed by slow-check with instanceof. - if (nonRetryableClasses.contains(exception.getClass()) - || nonRetryableClasses.stream() - .anyMatch(rejectException -> rejectException.isInstance(exception))) { - return false; - } - - return true; - } - - public int getRetryCount() { - return retryCount; - } - - protected boolean handleAsIdempotent(final HttpClientContext context) { - String method = context.getRequest().getRequestLine().getMethod(); - // do not retry admin requests, even if they are GET requests as they are not idempotent - if (context.getRequest().getRequestLine().getUri().startsWith("/admin/")) { - log.debug("Do not retry, this is an admin request"); - return false; - } - return method.equals(GET); - } - - protected boolean requestIsAborted(final HttpRequest request) { - HttpRequest req = request; - if (request instanceof RequestWrapper) { // does not forward request to original - req = ((RequestWrapper) request).getOriginal(); - } - return (req instanceof HttpUriRequest && ((HttpUriRequest) req).isAborted()); - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrPortAwareCookieSpecFactory.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrPortAwareCookieSpecFactory.java deleted file mode 100644 index aadcf2ad9ac3..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/SolrPortAwareCookieSpecFactory.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.client.solrj.apache; - -import java.util.Collection; -import org.apache.http.cookie.ClientCookie; -import org.apache.http.cookie.Cookie; -import org.apache.http.cookie.CookieOrigin; -import org.apache.http.cookie.CookieSpec; -import org.apache.http.cookie.CookieSpecFactory; -import org.apache.http.cookie.CookieSpecProvider; -import org.apache.http.cookie.MalformedCookieException; -import org.apache.http.cookie.params.CookieSpecPNames; -import org.apache.http.impl.cookie.NetscapeDomainHandler; -import org.apache.http.impl.cookie.NetscapeDraftSpec; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.HttpContext; - -@SuppressWarnings("deprecation") -@Deprecated -public class SolrPortAwareCookieSpecFactory implements CookieSpecFactory, CookieSpecProvider { - public static final String POLICY_NAME = "solr-portaware"; - private final CookieSpec cookieSpec; - - public SolrPortAwareCookieSpecFactory(final String[] datepatterns) { - super(); - this.cookieSpec = new PortAwareCookieSpec(datepatterns); - } - - public SolrPortAwareCookieSpecFactory() { - this(null); - } - - @Override - public CookieSpec newInstance(final HttpParams params) { - if (params != null) { - String[] patterns = null; - final Collection param = - (Collection) params.getParameter(CookieSpecPNames.DATE_PATTERNS); - if (param != null) { - patterns = new String[param.size()]; - patterns = param.toArray(patterns); - } - return new PortAwareCookieSpec(patterns); - } else { - return new PortAwareCookieSpec(null); - } - } - - @Override - public CookieSpec create(final HttpContext context) { - return this.cookieSpec; - } - - public static class PortAwareCookieSpec extends NetscapeDraftSpec { - public PortAwareCookieSpec(String patterns[]) { - super(patterns); - super.registerAttribHandler(ClientCookie.DOMAIN_ATTR, new PortAwareDomainHandler()); - } - - public PortAwareCookieSpec() { - this(null); - } - } - - /** - * A domain handler to validate and match cookies based on the domain and origin. The domain is - * tested against host and port both, and if it doesn't match, it delegates the handling to the - * base class' matching/validation logic. - */ - public static class PortAwareDomainHandler extends NetscapeDomainHandler { - - @Override - public void validate(final Cookie cookie, final CookieOrigin origin) - throws MalformedCookieException { - if (origin != null && origin.getHost() != null && cookie != null) { - String hostPort = origin.getHost() + ":" + origin.getPort(); - String domain = cookie.getDomain(); - - if (hostPort.equals(domain)) { - return; - } - } - super.validate(cookie, origin); - } - - @Override - public boolean match(final Cookie cookie, final CookieOrigin origin) { - if (origin != null && origin.getHost() != null && cookie != null) { - String hostPort = origin.getHost() + ":" + origin.getPort(); - String domain = cookie.getDomain(); - if (hostPort.equals(domain)) { - return true; - } - } - return super.match(cookie, origin); - } - } -} diff --git a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/package-info.java b/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/package-info.java deleted file mode 100644 index 31cd26e17ead..000000000000 --- a/solr/test-framework/src/java/org/apache/solr/client/solrj/apache/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -/** Apache HttpClient based {@link org.apache.solr.client.solrj.SolrClient} implementations */ -@Deprecated -package org.apache.solr.client.solrj.apache; diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java index d4b81d99ea6d..ef9159a38d59 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java @@ -16,6 +16,7 @@ */ package org.apache.solr.cloud; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.solr.common.cloud.ZkStateReader.HTTPS; import static org.apache.solr.common.cloud.ZkStateReader.URL_SCHEME; @@ -57,8 +58,9 @@ import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.SolrRequest.SolrRequestType; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.CoreAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; @@ -90,6 +92,7 @@ import org.apache.solr.common.util.ExecutorUtil; import org.apache.solr.common.util.IOUtils; import org.apache.solr.common.util.NamedList; +import org.apache.solr.common.util.RetryUtil; import org.apache.solr.common.util.SolrNamedThreadFactory; import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.TimeSource; @@ -160,7 +163,8 @@ public void beforeTest() { protected volatile CloudSolrClient controlClientCloud; // cloud version of the control client protected volatile CloudSolrClient cloudClient; - protected final List coreClients = Collections.synchronizedList(new ArrayList<>()); + protected final List coreClients = + Collections.synchronizedList(new ArrayList<>()); protected final List cloudJettys = Collections.synchronizedList(new ArrayList<>()); @@ -209,7 +213,7 @@ public String toString() { } public static class CloudSolrServerClient { - SolrClient solrClient; + HttpSolrClient solrClient; String nodeName; int port; @@ -365,7 +369,7 @@ protected boolean useTlogReplicas() { } protected CloudSolrClient createCloudClient(String defaultCollection) { - return getCloudSolrClient( + return createNewCloudSolrClient( zkServer.getZkAddress(), defaultCollection, random().nextBoolean(), 30000, 120000); } @@ -378,17 +382,22 @@ protected void createServers(int numServers) throws Exception { controlJettyDir, useJettyDataDir ? getDataDir(testDir + "/control/data") : null); controlJetty.start(); try (CloudSolrClient client = createCloudClient("control_collection")) { - assertEquals( - 0, - CollectionAdminRequest.createCollection("control_collection", "conf1", 1, 1) - .setCreateNodeSet(controlJetty.getNodeName()) - .process(client) - .getStatus()); + RetryUtil.retryOnException( + SolrException.class, + 30000, + 1000, + () -> + assertEquals( + 0, + CollectionAdminRequest.createCollection("control_collection", "conf1", 1, 1) + .setCreateNodeSet(controlJetty.getNodeName()) + .process(client) + .getStatus())); waitForActiveReplicaCount(client, "control_collection", 1); } controlClient = - new HttpSolrClient.Builder(controlJetty.getBaseUrl().toString()) + HttpSolrClient.builder(controlJetty.getBaseUrl().toString()) .withDefaultCollection("control_collection") .build(); if (sliceCount <= 0) { @@ -442,7 +451,7 @@ public static void waitForCollection(ZkStateReader reader, String collection, in protected List createJettys(int numJettys) throws Exception { List jettys = Collections.synchronizedList(new ArrayList<>()); - List clients = Collections.synchronizedList(new ArrayList<>()); + List clients = Collections.synchronizedList(new ArrayList<>()); List> createReplicaRequests = Collections.synchronizedList(new ArrayList<>()); List> createPullReplicaRequests = @@ -526,7 +535,7 @@ protected List createJettys(int numJettys) throws Exception { .setType(Replica.Type.TLOG)); coreClients.add(createNewSolrClient(coreName, j.getLocalPort())); - SolrClient client = createNewSolrClient(j.getLocalPort()); + var client = createNewSolrClient(j.getLocalPort()); clients.add(client); } catch (Exception e) { @@ -565,8 +574,7 @@ protected List createJettys(int numJettys) throws Exception { .setNode(j.getNodeName()) .setType(Replica.Type.NRT)); coreClients.add(createNewSolrClient(coreName, j.getLocalPort())); - SolrClient client = createNewSolrClient(j.getLocalPort()); - clients.add(client); + clients.add(createNewSolrClient(j.getLocalPort())); } catch (Exception e) { log.error("error creating jetty", e); throw new RuntimeException(e); @@ -601,8 +609,7 @@ protected List createJettys(int numJettys) throws Exception { .setNode(j.getNodeName()) .setType(Replica.Type.PULL)); coreClients.add(createNewSolrClient(coreName, j.getLocalPort())); - SolrClient client = createNewSolrClient(j.getLocalPort()); - clients.add(client); + clients.add(createNewSolrClient(j.getLocalPort())); } catch (Exception e) { log.error("error creating jetty", e); throw new RuntimeException(e); @@ -932,13 +939,13 @@ private Path getRelativeSolrHomePath(Path solrHome) { return relativizedCurDir.resolve(solrHomeRelativeToRoot).toAbsolutePath(); } - protected void updateMappingsFromZk(List jettys, List clients) + protected void updateMappingsFromZk(List jettys, List clients) throws Exception { updateMappingsFromZk(jettys, clients, false); } protected void updateMappingsFromZk( - List jettys, List clients, boolean allowOverSharding) + List jettys, List clients, boolean allowOverSharding) throws Exception { ZkStateReader zkStateReader = ZkStateReader.from(cloudClient); zkStateReader.forceUpdateCollection(DEFAULT_COLLECTION); @@ -949,13 +956,13 @@ protected void updateMappingsFromZk( DocCollection coll = clusterState.getCollection(DEFAULT_COLLECTION); List theClients = new ArrayList<>(); - for (SolrClient client : clients) { + for (var client : clients) { // find info for this client in zk nextClient: // we find out state by simply matching ports... for (Slice slice : coll.getSlices()) { for (Replica replica : slice.getReplicas()) { - int port = new URI(((HttpSolrClient) client).getBaseURL()).getPort(); + int port = new URI(client.getBaseURL()).getPort(); if (replica.getBaseUrl().contains(":" + port)) { CloudSolrServerClient csc = new CloudSolrServerClient(); @@ -2037,8 +2044,7 @@ protected void assertDocCounts(boolean verbose) throws Exception { for (Map.Entry slice : slices.entrySet()) { Map theShards = slice.getValue().getReplicasMap(); for (Map.Entry shard : theShards.entrySet()) { - String shardName = - new URI(((HttpSolrClient) client.solrClient).getBaseURL()).getPort() + "_solr_"; + String shardName = new URI(client.solrClient.getBaseURL()).getPort() + "_solr_"; if (verbose && shard.getKey().endsWith(shardName)) { System.err.println("shard:" + slice.getKey()); System.err.println(shard.getValue()); @@ -2261,12 +2267,14 @@ protected void destroyServers() throws Exception { customThreadPool.execute(() -> IOUtils.closeQuietly(cloudClient)); - ExecutorUtil.shutdownAndAwaitTermination(customThreadPool); - - coreClients.clear(); - solrClientByCollection.clear(); + try { + ExecutorUtil.shutdownAndAwaitTermination(customThreadPool); + } finally { + coreClients.clear(); + solrClientByCollection.clear(); - super.destroyServers(); + super.destroyServers(); + } } @Override @@ -2351,7 +2359,7 @@ protected CollectionAdminResponse createCollection( CollectionAdminResponse res = new CollectionAdminResponse(); if (client == null) { final String baseUrl = getBaseUrl(jettys.get(clientIndex)); - try (SolrClient adminClient = createNewSolrClient("", baseUrl)) { + try (SolrClient adminClient = createNewSolrClient(baseUrl, null)) { res.setResponse(adminClient.request(request)); } } else { @@ -2433,44 +2441,42 @@ ZkStateReader.PULL_REPLICAS, getPullReplicaCount(), * not wish to have any randomized behavior should use the {@link * org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly */ - public static CloudSolrClient getCloudSolrClient( + public static CloudSolrClient createNewCloudSolrClient( String zkHost, String defaultCollection, boolean shardLeadersOnly, int connectionTimeoutMillis, - int socketTimeoutMillis) { - RandomizingCloudSolrClientBuilder builder = - new RandomizingCloudSolrClientBuilder(List.of(zkHost), Optional.empty()); + int idleTimeoutMillis) { + var builder = new RandomizingCloudSolrClientBuilder(List.of(zkHost), Optional.empty()); + builder.withDefaultCollection(defaultCollection); if (shardLeadersOnly) { builder.sendUpdatesOnlyToShardLeaders(); } else { - builder.sendUpdatesToAllReplicasInShard(); + builder.sendUpdatesToAnyReplica(); } - if (defaultCollection != null) { - builder.withDefaultCollection(defaultCollection); - } - return builder - .withConnectionTimeout(connectionTimeoutMillis) - .withSocketTimeout(socketTimeoutMillis) - .build(); + builder.withHttpClientBuilder( + new HttpJettySolrClient.Builder() + .withConnectionTimeout(connectionTimeoutMillis, MILLISECONDS) + .withIdleTimeout(idleTimeoutMillis, MILLISECONDS)); + return builder.build(); } @Override - protected SolrClient createNewSolrClient(int port) { + protected HttpSolrClient createNewSolrClient(int port) { return createNewSolrClient(DEFAULT_COLLECTION, port); } - protected SolrClient createNewSolrClient(String coreName, int port) { + protected HttpSolrClient createNewSolrClient(String coreName, int port) { String baseUrl = buildUrl(port); - return new HttpSolrClient.Builder(baseUrl) + return HttpSolrClient.builder(baseUrl) .withDefaultCollection(coreName) .withConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) - .withSocketTimeout(60000, TimeUnit.MILLISECONDS) + .withIdleTimeout(60000, TimeUnit.MILLISECONDS) .build(); } - protected SolrClient createNewSolrClient(String collection, String baseUrl) { - return getHttpSolrClient(baseUrl, collection); + protected SolrClient createNewSolrClient(String baseUrl, String collection) { + return new HttpJettySolrClient.Builder(baseUrl).withDefaultCollection(collection).build(); } protected String getBaseUrl(JettySolrRunner jetty) { @@ -2544,7 +2550,7 @@ protected CloudSolrClient getCommonCloudSolrClient() { synchronized (this) { if (commonCloudSolrClient == null) { commonCloudSolrClient = - getCloudSolrClient( + createNewCloudSolrClient( zkServer.getZkAddress(), DEFAULT_COLLECTION, random().nextBoolean(), 5000, 120000); commonCloudSolrClient.connect(); if (log.isInfoEnabled()) { @@ -2563,7 +2569,7 @@ protected CloudSolrClient getSolrClient(String collectionName) { collectionName, k -> { CloudSolrClient solrClient = - getCloudSolrClient( + createNewCloudSolrClient( zkServer.getZkAddress(), collectionName, random().nextBoolean(), 5000, 120000); solrClient.connect(); @@ -2992,7 +2998,7 @@ protected void waitForReplicationFromReplicas( protected long getIndexVersion(Replica replica) throws IOException { try (SolrClient client = - new HttpSolrClient.Builder(replica.getBaseUrl()) + HttpSolrClient.builder(replica.getBaseUrl()) .withDefaultCollection(replica.getCoreName()) .build()) { ModifiableSolrParams params = new ModifiableSolrParams(); @@ -3042,7 +3048,7 @@ protected static boolean attemptCollectionDelete(CloudSolrClient client, String protected void logReplicationDetails(Replica replica, StringBuilder builder) throws IOException { try (SolrClient client = - new HttpSolrClient.Builder(replica.getBaseUrl()) + HttpSolrClient.builder(replica.getBaseUrl()) .withDefaultCollection(replica.getCoreName()) .build()) { ModifiableSolrParams params = new ModifiableSolrParams(); diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/FullThrottleStoppableIndexingThread.java b/solr/test-framework/src/java/org/apache/solr/cloud/FullThrottleStoppableIndexingThread.java index 8ca5646f03e8..30c8f67d406a 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/FullThrottleStoppableIndexingThread.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/FullThrottleStoppableIndexingThread.java @@ -23,12 +23,13 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.http.client.HttpClient; import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.ConcurrentUpdateSolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.ConcurrentUpdateBaseSolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.ConcurrentUpdateJettySolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.common.SolrInputDocument; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,19 +39,18 @@ class FullThrottleStoppableIndexingThread extends StoppableIndexingThread { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); /** */ - private final HttpClient httpClient; + private final HttpJettySolrClient httpClient; private volatile boolean stop = false; int clientIndex = 0; - private ConcurrentUpdateSolrClient cusc; - private List clients; + private ConcurrentUpdateBaseSolrClient cusc; + private List clients; private AtomicInteger fails = new AtomicInteger(); public FullThrottleStoppableIndexingThread( - HttpClient httpClient, SolrClient controlClient, CloudSolrClient cloudClient, - List clients, + List clients, String id, boolean doDeletes, int clientSoTimeout) { @@ -58,17 +58,18 @@ public FullThrottleStoppableIndexingThread( setName("FullThrottleStoppableIndexingThread"); setDaemon(true); this.clients = clients; - this.httpClient = httpClient; + this.httpClient = + new HttpJettySolrClient.Builder() + .withConnectionTimeout(10, TimeUnit.SECONDS) + .withIdleTimeout(clientSoTimeout, TimeUnit.MILLISECONDS) + .build(); cusc = new ErrorLoggingConcurrentUpdateSolrClient.Builder( - ((HttpSolrClient) clients.get(0)).getBaseURL()) - .withDefaultCollection(clients.get(0).getDefaultCollection()) - .withHttpClient(httpClient) + clients.getFirst().getBaseURL(), httpClient) + .withDefaultCollection(clients.getFirst().getDefaultCollection()) .withQueueSize(8) .withThreadCount(2) - .withConnectionTimeout(10000, TimeUnit.MILLISECONDS) - .withSocketTimeout(clientSoTimeout, TimeUnit.MILLISECONDS) .build(); } @@ -127,9 +128,8 @@ private void changeUrlOnError(Exception e) { cusc.shutdownNow(); cusc = new ErrorLoggingConcurrentUpdateSolrClient.Builder( - ((HttpSolrClient) clients.get(clientIndex)).getBaseURL()) + clients.get(clientIndex).getBaseURL(), httpClient) .withDefaultCollection(clients.get(clientIndex).getDefaultCollection()) - .withHttpClient(httpClient) .withQueueSize(30) .withThreadCount(3) .build(); @@ -163,7 +163,7 @@ public Set getDeleteFails() { throw new UnsupportedOperationException(); } - static class ErrorLoggingConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient { + static class ErrorLoggingConcurrentUpdateSolrClient extends ConcurrentUpdateJettySolrClient { public ErrorLoggingConcurrentUpdateSolrClient(Builder builder) { super(builder); } @@ -173,10 +173,10 @@ public void handleError(Throwable ex) { log.warn("cusc error", ex); } - static class Builder extends ConcurrentUpdateSolrClient.Builder { + static class Builder extends ConcurrentUpdateJettySolrClient.Builder { - public Builder(String baseSolrUrl) { - super(baseSolrUrl); + public Builder(String baseSolrUrl, HttpJettySolrClient jettySolrClient) { + super(baseSolrUrl, jettySolrClient); } @Override diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java index ae9a8fe87f6b..14dcf0e7b833 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java @@ -54,8 +54,10 @@ import org.apache.solr.SolrBackend; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider; +import org.apache.solr.client.solrj.jetty.CloudJettySolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.jetty.SSLConfig; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.common.SolrException; @@ -655,12 +657,7 @@ public CloudSolrClient getSolrClient(String collectionName) { return solrClientByCollection.computeIfAbsent( collectionName, k -> { - CloudSolrClient solrClient = - new CloudLegacySolrClient.Builder(List.of(zkServer.getZkAddress()), Optional.empty()) - .withDefaultCollection(collectionName) - .withSocketTimeout(90000) - .withConnectionTimeout(15000) - .build(); + CloudSolrClient solrClient = newSolrClient(collectionName); solrClient.connect(); if (log.isInfoEnabled()) { @@ -676,11 +673,13 @@ public CloudSolrClient getSolrClient(String collectionName) { @Override // SolrBackend public CloudSolrClient newSolrClient(String collection) { - return new CloudLegacySolrClient.Builder( - List.of(getZkServer().getZkAddress()), Optional.empty()) - .withSocketTimeout(90000, TimeUnit.MILLISECONDS) - .withConnectionTimeout(15000, TimeUnit.MILLISECONDS) + return new CloudJettySolrClient.Builder( + new ZkClientClusterStateProvider(getZkServer().getZkAddress())) .withDefaultCollection(collection) + .withHttpClientBuilder( + new HttpJettySolrClient.Builder() + .withConnectionTimeout(15, TimeUnit.SECONDS) + .withIdleTimeout(90, TimeUnit.SECONDS)) .build(); // we choose 90 because we run in some harsh envs } diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCloudBackupRestoreTestCase.java b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCloudBackupRestoreTestCase.java index 8acdf9ad9834..3124d5c14511 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCloudBackupRestoreTestCase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCloudBackupRestoreTestCase.java @@ -31,12 +31,11 @@ import java.util.UUID; import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.CloudLegacySolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.jetty.CloudJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.CollectionAdminRequest.ClusterProp; -import org.apache.solr.client.solrj.request.SolrQuery; +import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.response.RequestStatusState; import org.apache.solr.cloud.AbstractFullDistribZkTestBase; import org.apache.solr.cloud.SolrCloudTestCase; @@ -468,21 +467,17 @@ private void testBackupAndRestore(String collectionName) throws Exception { public static Map getShardToDocCountMap( CloudSolrClient client, DocCollection docCollection) throws SolrServerException, IOException { Map shardToDocCount = new TreeMap<>(); + var jettySolrClient = ((CloudJettySolrClient) client).getHttpClient(); for (Slice slice : docCollection.getActiveSlices()) { - String shardName = slice.getName(); - try (var leaderClient = - new HttpSolrClient.Builder(slice.getLeader().getBaseUrl()) - .withDefaultCollection(slice.getLeader().getCoreName()) - .withHttpClient(((CloudLegacySolrClient) client).getHttpClient()) - .build()) { - long docsInShard = - leaderClient - .query(new SolrQuery("*:*").setParam("distrib", "false")) - .getResults() - .getNumFound(); - shardToDocCount.put(shardName, (int) docsInShard); - } + long docsInShard = + new QueryRequest("/select", params("q", "*:*", "distrib", "false")) + .processWithBaseUrl( + jettySolrClient, slice.getLeader().getBaseUrl(), slice.getLeader().getCoreName()) + .getResults() + .getNumFound(); + shardToDocCount.put(slice.getName(), (int) docsInShard); } + return shardToDocCount; } } diff --git a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java index f355b057aa49..4550eabe36fd 100644 --- a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java +++ b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java @@ -42,9 +42,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.solr.SolrBackend; -import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.apache.HttpSolrClient; import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.jetty.SSLConfig; @@ -579,6 +577,10 @@ public synchronized void stop() throws Exception { IOUtils.closeQuietly(jettySolrClient); jettySolrClient = null; + if (enableProxy) { + proxy.close(); + } + QueuedThreadPool qtp = (QueuedThreadPool) server.getThreadPool(); ReservedThreadExecutor rte = qtp.getBean(ReservedThreadExecutor.class); @@ -620,10 +622,6 @@ public synchronized void stop() throws Exception { } while (!server.isStopped()); } finally { - if (enableProxy) { - proxy.close(); - } - if (prevContext != null) { MDC.setContextMap(prevContext); } else { @@ -750,14 +748,15 @@ public URL getProxyBaseUrl() { } } - public SolrClient newClient() { - return new HttpSolrClient.Builder(getBaseUrl().toString()).build(); + @Deprecated + public HttpJettySolrClient newClient() { + return new HttpJettySolrClient.Builder(getBaseUrl().toString()).build(); } - public SolrClient newClient(int connectionTimeoutMillis, int socketTimeoutMillis) { - return new HttpSolrClient.Builder(getBaseUrl().toString()) + public HttpJettySolrClient newClient(int connectionTimeoutMillis, int socketTimeoutMillis) { + return new HttpJettySolrClient.Builder(getBaseUrl().toString()) .withConnectionTimeout(connectionTimeoutMillis, TimeUnit.MILLISECONDS) - .withSocketTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS) + .withIdleTimeout(socketTimeoutMillis, TimeUnit.MILLISECONDS) .build(); } @@ -811,7 +810,7 @@ public RestTestHarness getRestClient(String collection) { // ---- SolrBackend implementation ---- @Override - public SolrClient newSolrClient(String collection) { + public HttpJettySolrClient newSolrClient(String collection) { return new HttpJettySolrClient.Builder(getBaseUrl().toString()) .withDefaultCollection(collection) .build(); diff --git a/solr/test-framework/src/java/org/apache/solr/util/RandomizeSSL.java b/solr/test-framework/src/java/org/apache/solr/util/RandomizeSSL.java index 54e192853633..1e8afd0a5064 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/RandomizeSSL.java +++ b/solr/test-framework/src/java/org/apache/solr/util/RandomizeSSL.java @@ -126,6 +126,10 @@ public SSLTestConfig createSSLTestConfig() { LuceneTestCase.TEST_NIGHTLY, LuceneTestCase.RANDOM_MULTIPLIER)); + if (Boolean.getBoolean("tests.ssl") && ssl > 0.0D) { + return new SSLTestConfig(true, useClientAuth); + } + return new SSLTestConfig(useSSL, useClientAuth); } diff --git a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java index 70f26d6405ed..9a62ecb2afba 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java +++ b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java @@ -24,19 +24,19 @@ import java.security.SecureRandomParameters; import java.security.SecureRandomSpi; import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.TrustSelfSignedStrategy; -import org.apache.http.ssl.SSLContextBuilder; -import org.apache.http.ssl.SSLContexts; -import org.apache.solr.client.solrj.apache.HttpClientUtil.SocketFactoryRegistryProvider; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.client.solrj.jetty.SSLConfig; import org.eclipse.jetty.util.resource.Resource; @@ -45,9 +45,9 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; /** - * An SSLConfig that provides {@link SSLConfig} and {@link SocketFactoryRegistryProvider} for both - * clients and servers that supports reading key/trust store information directly from resource - * files provided with the Solr test-framework classes + * An SSLConfig that provides {@link SSLConfig} for both clients and servers that supports reading + * key/trust store information directly from resource files provided with the Solr test-framework + * classes */ public class SSLTestConfig { private static final String TEST_KEYSTORE_BOGUSHOST_RESOURCE = @@ -101,7 +101,6 @@ public SSLTestConfig(boolean useSsl, boolean clientAuth) { * Certificate (and which testing Cert should be used) * @see SolrHttpConstants#SYS_PROP_CHECK_PEER_NAME */ - @SuppressWarnings("removal") public SSLTestConfig(boolean useSsl, boolean clientAuth, boolean checkPeerName) { this.useSsl = useSsl; this.clientAuth = clientAuth; @@ -130,23 +129,6 @@ public boolean isClientAuthMode() { return clientAuth; } - /** - * Creates a {@link SocketFactoryRegistryProvider} for HTTP clients to use when - * communicating with servers which have been configured based on the settings of this object. - * When {@link #isSSLMode} is true, this SocketFactoryRegistryProvider will - * only support HTTPS (no HTTP scheme) using the appropriate certs. When {@link #isSSLMode} - * is false, only HTTP (no HTTPS scheme) will be supported. - */ - public SocketFactoryRegistryProvider buildClientSocketFactoryRegistryProvider() { - if (isSSLMode()) { - SSLConnectionSocketFactory sslConnectionFactory = buildClientSSLConnectionSocketFactory(); - assert null != sslConnectionFactory; - return new SSLSocketFactoryRegistryProvider(sslConnectionFactory); - } else { - return HTTP_ONLY_SCHEMA_PROVIDER; - } - } - /** * Builds a new SSLContext for HTTP clients to use when communicating with servers which * have been configured based on the settings of this object. @@ -163,22 +145,25 @@ public SSLContext buildClientSSLContext() assert isSSLMode(); - SSLContextBuilder builder = SSLContexts.custom(); - builder.setSecureRandom(NotSecurePseudoRandom.INSTANCE); - // NOTE: KeyStore & TrustStore are swapped because they are from configured from server // perspective... // we are a client - our keystore contains the keys the server trusts, and vice versa - builder - .loadTrustMaterial(buildKeyStore(keyStore, TEST_PASSWORD), new TrustSelfSignedStrategy()) - .build(); + var tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(buildKeyStore(keyStore, TEST_PASSWORD)); + KeyManager[] keyManagers = null; if (isClientAuthMode()) { - builder.loadKeyMaterial( - buildKeyStore(trustStore, TEST_PASSWORD), TEST_PASSWORD.toCharArray()); + var kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(buildKeyStore(trustStore, TEST_PASSWORD), TEST_PASSWORD.toCharArray()); + keyManagers = kmf.getKeyManagers(); } - return builder.build(); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init( + keyManagers, + trustSelfSignedStrategy(tmf.getTrustManagers()), + NotSecurePseudoRandom.INSTANCE); + return sslContext; } public SSLConfig buildClientSSLConfig() { @@ -222,19 +207,19 @@ public SSLConfig buildServerSSLConfig() { public SslContextFactory.Server createContextFactory() { SslContextFactory.Server factory = new SslContextFactory.Server(); try { - SSLContextBuilder builder = SSLContexts.custom(); - builder.setSecureRandom(NotSecurePseudoRandom.INSTANCE); - - builder.loadKeyMaterial( - buildKeyStore(keyStore, TEST_PASSWORD), TEST_PASSWORD.toCharArray()); + var kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(buildKeyStore(keyStore, TEST_PASSWORD), TEST_PASSWORD.toCharArray()); + TrustManager[] trustManagers = null; if (isClientAuthMode()) { - builder - .loadTrustMaterial( - buildKeyStore(trustStore, TEST_PASSWORD), new TrustSelfSignedStrategy()) - .build(); + var tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(buildKeyStore(trustStore, TEST_PASSWORD)); + trustManagers = trustSelfSignedStrategy(tmf.getTrustManagers()); } - factory.setSslContext(builder.build()); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), trustManagers, NotSecurePseudoRandom.INSTANCE); + factory.setSslContext(sslContext); } catch (Exception e) { throw new RuntimeException("ssl context init failure: " + e.getMessage(), e); } @@ -244,6 +229,51 @@ public SslContextFactory.Server createContextFactory() { }; } + /** + * Returns trust managers that accept self-signed certs, delegating all others to {@code + * delegates}. + */ + private static TrustManager[] trustSelfSignedStrategy(TrustManager[] delegates) { + return new TrustManager[] { + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + if (chain.length == 1) return; + for (TrustManager tm : delegates) { + if (tm instanceof X509TrustManager) { + ((X509TrustManager) tm).checkClientTrusted(chain, authType); + return; + } + } + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + if (chain.length == 1) return; + for (TrustManager tm : delegates) { + if (tm instanceof X509TrustManager) { + ((X509TrustManager) tm).checkServerTrusted(chain, authType); + return; + } + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + List issuers = new ArrayList<>(); + for (TrustManager tm : delegates) { + if (tm instanceof X509TrustManager) { + issuers.addAll(Arrays.asList(((X509TrustManager) tm).getAcceptedIssuers())); + } + } + return issuers.toArray(new X509Certificate[0]); + } + } + }; + } + public KeyStore defaultKeyStore() { if (keyStore == null) { return null; @@ -269,64 +299,6 @@ private static KeyStore buildKeyStore(Resource resource, String password) { } } - /** - * Constructs a new SSLConnectionSocketFactory for HTTP clients to use when communicating - * with servers which have been configured based on the settings of this object. Will return null - * unless {@link #isSSLMode} is true. - */ - public SSLConnectionSocketFactory buildClientSSLConnectionSocketFactory() { - if (!isSSLMode()) { - return null; - } - SSLConnectionSocketFactory sslConnectionFactory; - try { - SSLContext sslContext = buildClientSSLContext(); - if (checkPeerName == false) { - sslConnectionFactory = - new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); - } else { - sslConnectionFactory = new SSLConnectionSocketFactory(sslContext); - } - } catch (KeyManagementException - | UnrecoverableKeyException - | NoSuchAlgorithmException - | KeyStoreException e) { - throw new IllegalStateException( - "Unable to setup https scheme for HTTPClient to test SSL.", e); - } - return sslConnectionFactory; - } - - /** - * A SocketFactoryRegistryProvider that only knows about SSL using a specified - * SSLConnectionSocketFactory - */ - private static class SSLSocketFactoryRegistryProvider extends SocketFactoryRegistryProvider { - private final SSLConnectionSocketFactory sslConnectionFactory; - - public SSLSocketFactoryRegistryProvider(SSLConnectionSocketFactory sslConnectionFactory) { - this.sslConnectionFactory = sslConnectionFactory; - } - - @Override - public Registry getSocketFactoryRegistry() { - return RegistryBuilder.create() - .register("https", sslConnectionFactory) - .build(); - } - } - - /** A SocketFactoryRegistryProvider that only knows about HTTP */ - private static final SocketFactoryRegistryProvider HTTP_ONLY_SCHEMA_PROVIDER = - new SocketFactoryRegistryProvider() { - @Override - public Registry getSocketFactoryRegistry() { - return RegistryBuilder.create() - .register("http", PlainConnectionSocketFactory.getSocketFactory()) - .build(); - } - }; - /** * A mocked up instance of SecureRandom that just uses {@link Random} under the covers. This is to * prevent blocking issues that arise in platform default SecureRandom instances due to too many diff --git a/solr/test-framework/src/java/org/apache/solr/util/SocketProxy.java b/solr/test-framework/src/java/org/apache/solr/util/SocketProxy.java index 2e0c6ea388b4..e64aa5a901f1 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/SocketProxy.java +++ b/solr/test-framework/src/java/org/apache/solr/util/SocketProxy.java @@ -81,6 +81,7 @@ public SocketProxy(int port, boolean useSSL) throws Exception { this.usesSSL = useSSL; serverSocket = createServerSocket(useSSL); serverSocket.setReuseAddress(true); + serverSocket.setSoTimeout(1000); if (receiveBufferSize > 0) { serverSocket.setReceiveBufferSize(receiveBufferSize); } @@ -188,6 +189,7 @@ public void reopen() { } serverSocket = createServerSocket(usesSSL); serverSocket.setReuseAddress(true); + serverSocket.setSoTimeout(1000); if (receiveBufferSize > 0) { serverSocket.setReceiveBufferSize(receiveBufferSize); } diff --git a/solr/test-framework/src/java/org/apache/solr/util/SolrJettyTestRule.java b/solr/test-framework/src/java/org/apache/solr/util/SolrJettyTestRule.java index 467c6bb2b1b7..b1bfc23d45df 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/SolrJettyTestRule.java +++ b/solr/test-framework/src/java/org/apache/solr/util/SolrJettyTestRule.java @@ -21,7 +21,7 @@ import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.apache.HttpSolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.common.util.IOUtils; import org.apache.solr.core.CoreContainer; import org.apache.solr.embedded.JettyConfig; @@ -113,7 +113,8 @@ public SolrClient getSolrClient(String collection) { } protected SolrClient newSolrClient(String collection) { - return new HttpSolrClient.Builder(getBaseUrl()) + return new HttpJettySolrClient.Builder() + .withHttpClient(jetty.getSolrClient()) .withDefaultCollection(collection) // Properly handles when collection is 'null' .build(); }