Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 44393200CB7 for ; Fri, 16 Jun 2017 06:36:05 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 42E11160BED; Fri, 16 Jun 2017 04:36:05 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 6881F160BDF for ; Fri, 16 Jun 2017 06:36:03 +0200 (CEST) Received: (qmail 27934 invoked by uid 500); 16 Jun 2017 04:36:02 -0000 Mailing-List: contact commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@lucene.apache.org Delivered-To: mailing list commits@lucene.apache.org Received: (qmail 27925 invoked by uid 99); 16 Jun 2017 04:36:02 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 16 Jun 2017 04:36:02 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 67DB7E0230; Fri, 16 Jun 2017 04:36:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: noble@apache.org To: commits@lucene.apache.org Message-Id: <4bfc8a0e81424d288bb4c113f656c478@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: lucene-solr:master: SOLR-10433: CollectionAdmin requests in SolrJ to support V2 calls Date: Fri, 16 Jun 2017 04:36:02 +0000 (UTC) archived-at: Fri, 16 Jun 2017 04:36:05 -0000 Repository: lucene-solr Updated Branches: refs/heads/master a7245d5e7 -> f6f6f1132 SOLR-10433: CollectionAdmin requests in SolrJ to support V2 calls Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f6f6f113 Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f6f6f113 Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f6f6f113 Branch: refs/heads/master Commit: f6f6f113209a5766c837665a818a524d0613757e Parents: a7245d5 Author: Noble Paul Authored: Fri Jun 16 14:05:51 2017 +0930 Committer: Noble Paul Committed: Fri Jun 16 14:05:51 2017 +0930 ---------------------------------------------------------------------- solr/CHANGES.txt | 2 + .../src/java/org/apache/solr/api/ApiBag.java | 9 +- .../solr/request/SolrQueryRequestBase.java | 15 +- .../org/apache/solr/servlet/HttpSolrCall.java | 9 +- .../apache/solr/cloud/TestCollectionAPI.java | 30 +++- .../solr/handler/admin/TestCollectionAPIs.java | 10 +- .../test/org/apache/solr/util/TestUtils.java | 32 ++++- .../apache/solr/client/solrj/SolrRequest.java | 18 +++ .../solr/client/solrj/V2RequestSupport.java | 30 ++++ .../solr/client/solrj/impl/CloudSolrClient.java | 5 + .../solr/client/solrj/impl/HttpSolrClient.java | 7 +- .../solrj/request/CollectionAdminRequest.java | 10 +- .../solrj/request/CollectionApiMapping.java | 15 ++ .../client/solrj/request/V1toV2ApiMapper.java | 144 +++++++++++++++++++ .../solr/client/solrj/request/V2Request.java | 47 ++++-- .../solr/common/util/CommandOperation.java | 48 ++++++- .../solr/common/util/ContentStreamBase.java | 7 +- .../apache/solr/common/util/JavaBinCodec.java | 12 +- .../solr/common/util/JsonSchemaValidator.java | 28 +++- .../org/apache/solr/common/util/Template.java | 66 +++++++++ .../java/org/apache/solr/common/util/Utils.java | 9 ++ .../solrj/request/TestV1toV2ApiMapper.java | 55 +++++++ 22 files changed, 551 insertions(+), 57 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/CHANGES.txt ---------------------------------------------------------------------- diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 3c27672..7c8f013 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -142,6 +142,8 @@ New Features This will correct counts (and other statistics) for those top buckets collected in the first phase. (yonik) +* SOLR-10433: CollectionAdmin requests in SolrJ to support V2 calls (noble) + Bug Fixes ---------------------- http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/core/src/java/org/apache/solr/api/ApiBag.java ---------------------------------------------------------------------- diff --git a/solr/core/src/java/org/apache/solr/api/ApiBag.java b/solr/core/src/java/org/apache/solr/api/ApiBag.java index 805c31e..b1ca9a9 100644 --- a/solr/core/src/java/org/apache/solr/api/ApiBag.java +++ b/solr/core/src/java/org/apache/solr/api/ApiBag.java @@ -35,6 +35,8 @@ import com.google.common.collect.ImmutableSet; import org.apache.solr.common.SolrException; import org.apache.solr.common.SpecProvider; import org.apache.solr.common.util.CommandOperation; +import org.apache.solr.common.util.ContentStream; +import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.Utils; import org.apache.solr.common.util.ValidatingJsonMap; import org.apache.solr.core.PluginBag; @@ -282,13 +284,14 @@ public class ApiBag { } } - public static List getCommandOperations(Reader reader, Map validators, boolean validate) { + public static List getCommandOperations(ContentStream stream, Map validators, boolean validate) { List parsedCommands = null; try { - parsedCommands = CommandOperation.parse(reader); + parsedCommands = CommandOperation.readCommands(Collections.singleton(stream), new NamedList()); } catch (IOException e) { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e); + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Unable to parse commands"); } + if (validators == null || !validate) { // no validation possible because we do not have a spec return parsedCommands; } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java ---------------------------------------------------------------------- diff --git a/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java b/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java index 83e44dd..31b8605 100644 --- a/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java +++ b/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java @@ -203,8 +203,7 @@ public abstract class SolrQueryRequestBase implements SolrQueryRequest, Closeabl Iterable contentStreams = getContentStreams(); if (contentStreams == null) throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No content stream"); for (ContentStream contentStream : contentStreams) { - parsedCommands = ApiBag.getCommandOperations(getInputStream(contentStream), - getValidators(), validateInput); + parsedCommands = ApiBag.getCommandOperations(contentStream, getValidators(), validateInput); } } @@ -212,18 +211,6 @@ public abstract class SolrQueryRequestBase implements SolrQueryRequest, Closeabl } - private InputStreamReader getInputStream(ContentStream contentStream) { - if(contentStream instanceof InputStream) { - return new InputStreamReader((InputStream)contentStream, UTF_8); - } else { - try { - return new InputStreamReader(contentStream.getStream(), UTF_8); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - protected ValidatingJsonMap getSpec() { return null; } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java ---------------------------------------------------------------------- diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java index 11b483a..bf6c553 100644 --- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java +++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java @@ -1108,14 +1108,7 @@ public class HttpSolrCall { Iterable contentStreams = solrReq.getContentStreams(); if (contentStreams == null) parsedCommands = Collections.EMPTY_LIST; else { - for (ContentStream contentStream : contentStreams) { - try { - parsedCommands = ApiBag.getCommandOperations(contentStream.getReader(), getValidators(), validateInput); - } catch (IOException e) { - throw new SolrException(ErrorCode.BAD_REQUEST, "Error reading commands"); - } - break; - } + parsedCommands = ApiBag.getCommandOperations(contentStreams.iterator().next(), getValidators(), validateInput); } } return CommandOperation.clone(parsedCommands); http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java ---------------------------------------------------------------------- diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java b/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java index 43b018e..9f81110 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestCollectionAPI.java @@ -22,15 +22,18 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; import com.google.common.collect.Lists; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; +import org.apache.solr.client.solrj.request.V2Request; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrInputDocument; @@ -67,7 +70,9 @@ public class TestCollectionAPI extends ReplicaPropertiesBase { req = CollectionAdminRequest.createCollection(COLLECTION_NAME, "conf1",2, 1, 0, 1); } req.setMaxShardsPerNode(2); + setV2(req); client.request(req); + assertV2CallsCount(); createCollection(null, COLLECTION_NAME1, 1, 1, 1, client, null, "conf1"); } @@ -184,9 +189,8 @@ public class TestCollectionAPI extends ReplicaPropertiesBase { private void clusterStatusZNodeVersion() throws Exception { String cname = "clusterStatusZNodeVersion"; try (CloudSolrClient client = createCloudClient(null)) { - - CollectionAdminRequest.createCollection(cname,"conf1",1,1).setMaxShardsPerNode(1).process(client); - + setV2(CollectionAdminRequest.createCollection(cname, "conf1", 1, 1).setMaxShardsPerNode(1)).process(client); + assertV2CallsCount(); waitForRecoveriesToFinish(cname, true); ModifiableSolrParams params = new ModifiableSolrParams(); @@ -208,8 +212,9 @@ public class TestCollectionAPI extends ReplicaPropertiesBase { assertNotNull(znodeVersion); CollectionAdminRequest.AddReplica addReplica = CollectionAdminRequest.addReplicaToShard(cname, "shard1"); + setV2(addReplica); addReplica.process(client); - + assertV2CallsCount(); waitForRecoveriesToFinish(cname, true); rsp = client.request(request); @@ -222,6 +227,23 @@ public class TestCollectionAPI extends ReplicaPropertiesBase { } } + private static long totalexpectedV2Calls; + + public static SolrRequest setV2(SolrRequest req) { + if (V2Request.v2Calls.get() == null) V2Request.v2Calls.set(new AtomicLong()); + totalexpectedV2Calls = V2Request.v2Calls.get().get(); + if (random().nextBoolean()) { + req.setUseV2(true); + req.setUseBinaryV2(random().nextBoolean()); + totalexpectedV2Calls++; + } + return req; + } + + public static void assertV2CallsCount() { + assertEquals(totalexpectedV2Calls, V2Request.v2Calls.get().get()); + } + private void clusterStatusWithRouteKey() throws IOException, SolrServerException { try (CloudSolrClient client = createCloudClient(DEFAULT_COLLECTION)) { SolrInputDocument doc = new SolrInputDocument(); http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java ---------------------------------------------------------------------- diff --git a/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java b/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java index e7dbf3e..f72bea1 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java @@ -17,7 +17,6 @@ package org.apache.solr.handler.admin; -import java.io.StringReader; import java.lang.invoke.MethodHandles; import java.util.Arrays; import java.util.Collection; @@ -27,11 +26,15 @@ import java.util.List; import java.util.Map; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.api.Api; +import org.apache.solr.api.ApiBag; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.common.cloud.ZkNodeProps; import org.apache.solr.common.params.CollectionParams; import org.apache.solr.common.params.MultiMapSolrParams; import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.CommandOperation; +import org.apache.solr.common.util.ContentStreamBase; import org.apache.solr.common.util.Pair; import org.apache.solr.common.util.Utils; import org.apache.solr.core.CoreContainer; @@ -39,9 +42,6 @@ import org.apache.solr.request.LocalSolrQueryRequest; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.servlet.SolrRequestParsers; -import org.apache.solr.common.util.CommandOperation; -import org.apache.solr.api.Api; -import org.apache.solr.api.ApiBag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -202,7 +202,7 @@ public class TestCollectionAPIs extends SolrTestCaseJ4 { @Override public List getCommands(boolean validateInput) { if (payload == null) return Collections.emptyList(); - return ApiBag.getCommandOperations(new StringReader(payload), api.getCommandSchema(), true); + return ApiBag.getCommandOperations(new ContentStreamBase.StringStream(payload), api.getCommandSchema(), true); } @Override http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/core/src/test/org/apache/solr/util/TestUtils.java ---------------------------------------------------------------------- diff --git a/solr/core/src/test/org/apache/solr/util/TestUtils.java b/solr/core/src/test/org/apache/solr/util/TestUtils.java index 4cf6f6b..5ec88d7 100644 --- a/solr/core/src/test/org/apache/solr/util/TestUtils.java +++ b/solr/core/src/test/org/apache/solr/util/TestUtils.java @@ -16,22 +16,35 @@ */ package org.apache.solr.util; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; import java.io.StringReader; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.solrj.impl.BinaryRequestWriter; +import org.apache.solr.client.solrj.impl.BinaryRequestWriter.BAOS; +import org.apache.solr.common.MapWriter; import org.apache.solr.common.util.CommandOperation; +import org.apache.solr.common.util.ContentStream; +import org.apache.solr.common.util.ContentStreamBase; +import org.apache.solr.common.util.JavaBinCodec; +import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.Utils; import org.junit.Assert; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.solr.common.util.Utils.fromJSONString; /** * @@ -163,7 +176,7 @@ public class TestUtils extends SolrTestCaseJ4 { public void testNoggitFlags() throws IOException { String s = "a{b:c, d [{k1:v1}{k2:v2}]}"; assertNoggitJsonValues((Map) Utils.fromJSON(s.getBytes(UTF_8))); - assertNoggitJsonValues((Map) Utils.fromJSONString(s)); + assertNoggitJsonValues((Map) fromJSONString(s)); List commands = CommandOperation.parse(new StringReader(s + s)); assertEquals(2, commands.size()); for (CommandOperation command : commands) { @@ -173,6 +186,21 @@ public class TestUtils extends SolrTestCaseJ4 { } } + public void testBinaryCommands() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new JavaBinCodec().marshal((MapWriter) ew -> { + ew.put("set-user", fromJSONString("{x:y}")); + ew.put("set-user", fromJSONString("{x:y,x1:y1}")); + ew.put("single", Arrays.asList(fromJSONString("[{x:y,x1:y1},{x2:y2}]"), fromJSONString( "{x2:y2}"))); + ew.put("multi", Arrays.asList(fromJSONString("{x:y,x1:y1}"), fromJSONString( "{x2:y2}"))); + }, baos); + + ContentStream stream = new ContentStreamBase.ByteArrayStream(baos.toByteArray(),null, "application/javabin"); + List commands = CommandOperation.readCommands(Collections.singletonList(stream), new NamedList(), Collections.singleton("single")); + + assertEquals(5, commands.size()); + } + private void assertNoggitJsonValues(Map m) { assertEquals( "c" ,Utils.getObjectByPath(m, true, "/a/b")); assertEquals( "v1" ,Utils.getObjectByPath(m, true, "/a/d[0]/k1")); @@ -196,7 +224,7 @@ public class TestUtils extends SolrTestCaseJ4 { " 'path':'/update/*',\n" + " 'role':'dev'}],\n" + " '':{'v':4}}}"; - Map m = (Map) Utils.fromJSONString(json); + Map m = (Map) fromJSONString(json); assertEquals("x-update", Utils.getObjectByPath(m,false, "authorization/permissions[1]/name")); } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java index 4dbba5b..fe5c4fc 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java @@ -56,6 +56,24 @@ public abstract class SolrRequest implements Serializabl private StreamingResponseCallback callback; private Set queryParams; + protected boolean usev2; + protected boolean useBinaryV2; + + /**If set to true, every request that implements {@link V2RequestSupport} will be converted + * to a V2 API call + */ + public SolrRequest setUseV2(boolean flag){ + this.usev2 = flag; + return this; + } + + /**If set to true use javabin instead of json (default) + */ + public SolrRequest setUseBinaryV2(boolean flag){ + this.useBinaryV2 = flag; + return this; + } + private String basicAuthUser, basicAuthPwd; public SolrRequest setBasicAuthCredentials(String user, String password) { http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/V2RequestSupport.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/V2RequestSupport.java b/solr/solrj/src/java/org/apache/solr/client/solrj/V2RequestSupport.java new file mode 100644 index 0000000..3ff13a6 --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/V2RequestSupport.java @@ -0,0 +1,30 @@ +/* + * 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; + +/**A a request object is able to convert itself to V2 Request + * it should implement this interface + * + */ +public interface V2RequestSupport { + /**If usev2 flag is set to true, return V2Request, if not, + * return V1 request object + * + */ + SolrRequest getV2Request(); +} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java index 10ea590..f0684f8 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java @@ -48,6 +48,7 @@ import org.apache.solr.client.solrj.ResponseParser; 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.V2RequestSupport; import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.IsUpdateRequest; import org.apache.solr.client.solrj.request.RequestWriter; @@ -813,6 +814,7 @@ public class CloudSolrClient extends SolrClient { */ protected NamedList requestWithRetryOnStaleState(SolrRequest request, int retryCount, String collection) throws SolrServerException, IOException { + SolrRequest originalRequest = request; connect(); // important to call this before you start working with the ZkStateReader @@ -823,6 +825,9 @@ public class CloudSolrClient extends SolrClient { String stateVerParam = null; List requestedCollections = null; boolean isCollectionRequestOfV2 = false; + if (request instanceof V2RequestSupport) { + request = ((V2RequestSupport) request).getV2Request(); + } if (request instanceof V2Request) { isCollectionRequestOfV2 = ((V2Request) request).isPerCollectionRequest(); } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java ---------------------------------------------------------------------- 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 1ba08bf..104ab1f 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 @@ -65,6 +65,7 @@ import org.apache.solr.client.solrj.ResponseParser; 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.V2RequestSupport; import org.apache.solr.client.solrj.request.RequestWriter; import org.apache.solr.client.solrj.request.V2Request; import org.apache.solr.common.SolrException; @@ -295,8 +296,10 @@ public class HttpSolrClient extends SolrClient { return queryModParams; } - protected HttpRequestBase createMethod(final SolrRequest request, String collection) throws IOException, SolrServerException { - + protected HttpRequestBase createMethod(SolrRequest request, String collection) throws IOException, SolrServerException { + if (request instanceof V2RequestSupport) { + request = ((V2RequestSupport) request).getV2Request(); + } SolrParams params = request.getParams(); Collection streams = requestWriter.getContentStreams(request); String path = requestWriter.getPath(request); http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java index 9ce6664..ed5b622 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java @@ -28,6 +28,7 @@ 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.V2RequestSupport; import org.apache.solr.client.solrj.response.CollectionAdminResponse; import org.apache.solr.client.solrj.response.RequestStatusState; import org.apache.solr.client.solrj.util.SolrIdentifierValidator; @@ -55,7 +56,7 @@ import static org.apache.solr.common.params.CollectionAdminParams.CREATE_NODE_SE * * @since solr 4.5 */ -public abstract class CollectionAdminRequest extends SolrRequest { +public abstract class CollectionAdminRequest extends SolrRequest implements V2RequestSupport { protected final CollectionAction action; @@ -71,6 +72,13 @@ public abstract class CollectionAdminRequest } @Override + public SolrRequest getV2Request() { + return usev2 ? + V1toV2ApiMapper.convert(this).useBinary(useBinaryV2).build() : + this; + } + + @Override public SolrParams getParams() { ModifiableSolrParams params = new ModifiableSolrParams(); params.set(CoreAdminParams.ACTION, action.toString()); http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionApiMapping.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionApiMapping.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionApiMapping.java index e622c4b..0b77c0e 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionApiMapping.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionApiMapping.java @@ -23,11 +23,13 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.common.params.CollectionParams.CollectionAction; import org.apache.solr.common.params.ConfigSetParams.ConfigSetAction; import org.apache.solr.common.util.CommandOperation; +import org.apache.solr.common.util.Pair; import org.apache.solr.common.util.Utils; import static org.apache.solr.client.solrj.SolrRequest.METHOD.DELETE; @@ -274,6 +276,19 @@ public class CollectionApiMapping { } return s; } + public Object getReverseParamSubstitute(String param) { + String s = paramstoAttr.containsKey(param) ? paramstoAttr.get(param) : param; + + if (prefixSubstitutes != null) { + for (Map.Entry e : prefixSubstitutes.entrySet()) { + if(param.startsWith(e.getValue())){ + return new Pair<>(e.getKey().substring(0, e.getKey().length() - 1), param.substring(e.getValue().length())); + } + } + } + return s; + + } } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/request/V1toV2ApiMapper.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/V1toV2ApiMapper.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/V1toV2ApiMapper.java new file mode 100644 index 0000000..c34f92c --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/V1toV2ApiMapper.java @@ -0,0 +1,144 @@ +/* + * 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.request; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.common.MapWriter; +import org.apache.solr.common.params.CollectionParams.CollectionAction; +import org.apache.solr.common.params.CoreAdminParams; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.JsonSchemaValidator; +import org.apache.solr.common.util.Pair; +import org.apache.solr.common.util.Template; +import org.apache.solr.common.util.Utils; +import org.apache.solr.common.util.ValidatingJsonMap; + +import static org.apache.solr.common.util.ValidatingJsonMap.NOT_NULL; + + +public class V1toV2ApiMapper { + + private static EnumMap mapping = new EnumMap<>(CollectionAction.class); + + static { + for (CollectionApiMapping.Meta meta : CollectionApiMapping.Meta.values()) { + if (meta.action != null) mapping.put(meta.action, new ActionInfo(meta)); + } + } + + private static class ActionInfo { + CollectionApiMapping.Meta meta; + String path; + Template template; + + + JsonSchemaValidator validator; + + ActionInfo(CollectionApiMapping.Meta meta) { + this.meta = meta; + } + + //do this lazily because , it makes no sense if this is not used + synchronized void setPath() { + if (path == null) { + ValidatingJsonMap m = Utils.getSpec(meta.getEndPoint().getSpecName()).getSpec(); + Object o = Utils.getObjectByPath(m, false, "url/paths"); + + String result = null; + if (o instanceof List) {//choose the shortest path + for (Object s : (List) o) { + if (result == null || s.toString().length() < result.length()) result = s.toString(); + } + } else if (o instanceof String) { + result = (String) o; + } + path = result; + template = new Template(path, Template.BRACES_PLACEHOLDER_PATTERN); + + validator = new JsonSchemaValidator(m.getMap("commands", NOT_NULL).getMap(meta.commandName, NOT_NULL)); + } + } + + public V2Request.Builder convert(SolrParams params) { + String[] list = new String[template.variables.size()]; + MapWriter data = serializeToV2Format(params, list); + Map o = data.toMap(new LinkedHashMap<>()); + return new V2Request.Builder(template.apply(s -> { + int idx = template.variables.indexOf(s); + return list[idx]; + })) + .withMethod(meta.getHttpMethod()) + .withPayload(o); + + } + + private MapWriter serializeToV2Format(SolrParams params, String[] list) { + return ew -> ew.put(meta.commandName, (MapWriter) ew1 -> { + Iterator iter = params.getParameterNamesIterator(); + Map> subProperties = null; + while (iter.hasNext()) { + String key = iter.next(); + if (CoreAdminParams.ACTION.equals(key)) continue; + Object substitute = meta.getReverseParamSubstitute(key); + int idx = template.variables.indexOf(substitute); + if (idx > -1) { + String val = params.get(String.valueOf(substitute)); + if (val == null) throw new RuntimeException("null value is not valid for " + key); + list[idx] = val; + continue; + } + if (substitute instanceof Pair) {//this is a nested object + Pair p = (Pair) substitute; + if (subProperties == null) subProperties = new HashMap<>(); + subProperties.computeIfAbsent(p.first(), s -> new HashMap<>()).put(p.second(), params.get(key)); + } else { + Object val = params.get(key); + ew1.put(substitute.toString(), val); + } + } + if (subProperties != null) { + for (Map.Entry> e : subProperties.entrySet()) { + ew1.put(e.getKey(), e.getValue()); + } + } + }); + } + } + + + public static V2Request.Builder convert(CollectionAdminRequest request) { + ActionInfo info = mapping.get(request.action); + if (info == null) throw new RuntimeException("Unsupported action :" + request.action); + + if (info.meta.getHttpMethod() == SolrRequest.METHOD.POST) { + if (info.path == null) info.setPath(); + return info.convert(request.getParams()); + } + + return null; + } + + +} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java index 6cc2314..df186e8 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java @@ -23,23 +23,29 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Collections; +import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Pattern; 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.common.SolrException; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.ContentStream; import org.apache.solr.common.util.ContentStreamBase; +import org.apache.solr.common.util.Utils; public class V2Request extends SolrRequest { + //only for debugging purposes + public static final ThreadLocal v2Calls = new ThreadLocal<>(); static final Pattern COLL_REQ_PATTERN = Pattern.compile("/(c|collections)/[^/]+/(?!shards)"); private InputStream payload; private SolrParams solrParams; + public final boolean useBinary; - private V2Request(METHOD m, String resource, InputStream payload) { + private V2Request(METHOD m, String resource, boolean useBinary) { super(m, resource); - this.payload = payload; + this.useBinary = useBinary; } @Override @@ -49,6 +55,7 @@ public class V2Request extends SolrRequest { @Override public Collection getContentStreams() throws IOException { + if (v2Calls.get() != null) v2Calls.get().incrementAndGet(); if (payload != null) { return Collections.singleton(new ContentStreamBase() { @Override @@ -58,7 +65,7 @@ public class V2Request extends SolrRequest { @Override public String getContentType() { - return "application/json"; + return useBinary ? "application/javabin" : "application/json"; } }); } @@ -77,8 +84,9 @@ public class V2Request extends SolrRequest { public static class Builder { private String resource; private METHOD method = METHOD.GET; - private InputStream payload; + private Object payload; private SolrParams params; + private boolean useBinary = false; /** * Create a Builder object based on the provided resource. @@ -108,7 +116,12 @@ public class V2Request extends SolrRequest { return this; } - public Builder withPayLoad(InputStream payload) { + public Builder withPayload(Object payload) { + this.payload = payload; + return this; + } + + public Builder withPayload(InputStream payload) { this.payload = payload; return this; } @@ -118,10 +131,28 @@ public class V2Request extends SolrRequest { return this; } + public Builder useBinary(boolean flag) { + this.useBinary = flag; + return this; + } + public V2Request build() { - V2Request v2Request = new V2Request(method, resource, payload); - v2Request.solrParams = params; - return v2Request; + try { + V2Request v2Request = new V2Request(method, resource, useBinary); + v2Request.solrParams = params; + InputStream is = null; + if (payload != null) { + if (payload instanceof InputStream) is = (InputStream) payload; + else if (useBinary) is = Utils.toJavabin(payload); + else is = new ByteArrayInputStream(Utils.toJSON(payload)); + } + v2Request.payload = is; + return v2Request; + } catch (IOException e) { + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e); + } + + } } } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java b/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java index c18a8e4..50002f6 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java @@ -17,10 +17,12 @@ package org.apache.solr.common.util; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -221,7 +223,41 @@ public class CommandOperation { } /** - * Parse the command operations into command objects + * Parse the command operations into command objects from javabin payload + * * @param singletonCommands commands that cannot be repeated + */ + public static List parse(InputStream in, Set singletonCommands) throws IOException { + List operations = new ArrayList<>(); + + final HashMap map = new HashMap(0) { + @Override + public Object put(Object key, Object value) { + List vals = null; + if (value instanceof List && !singletonCommands.contains(key)) { + vals = (List) value; + } else { + vals = Collections.singletonList(value); + } + for (Object val : vals) { + operations.add(new CommandOperation(String.valueOf(key), val)); + } + return null; + } + }; + + new JavaBinCodec() { + int level = 0; + @Override + protected Map newMap(int size) { + level++; + return level == 1 ? map : super.newMap(size); + } + }.unmarshal(in); + return operations; + } + + /** + * Parse the command operations into command objects from a json payload * * @param rdr The payload * @param singletonCommands commands that cannot be repeated @@ -304,9 +340,13 @@ public class CommandOperation { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "missing content stream"); } ArrayList ops = new ArrayList<>(); - - for (ContentStream stream : streams) - ops.addAll(parse(stream.getReader(), singletonCommands)); + for (ContentStream stream : streams) { + if ("application/javabin".equals(stream.getContentType())) { + ops.addAll(parse(stream.getStream(), singletonCommands)); + } else { + ops.addAll(parse(stream.getReader(), singletonCommands)); + } + } List errList = CommandOperation.captureErrors(ops); if (!errList.isEmpty()) { resp.add(CommandOperation.ERR_MSGS, errList); http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/common/util/ContentStreamBase.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/common/util/ContentStreamBase.java b/solr/solrj/src/java/org/apache/solr/common/util/ContentStreamBase.java index bd1d63b..f9db69c 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/ContentStreamBase.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/ContentStreamBase.java @@ -258,11 +258,14 @@ public abstract class ContentStreamBase implements ContentStream public static class ByteArrayStream extends ContentStreamBase { private final byte[] bytes; - public ByteArrayStream( byte[] bytes, String source ) { + this(bytes,source, null); + } + + public ByteArrayStream( byte[] bytes, String source, String contentType ) { this.bytes = bytes; - this.contentType = null; + this.contentType = contentType; name = source; size = new Long(bytes.length); sourceInfo = source; http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java index d9843e1..a2400f3 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java @@ -628,7 +628,7 @@ public class JavaBinCodec implements PushWriter { public Map readMapIter(DataInputInputStream dis) throws IOException { - Map m = new LinkedHashMap<>(); + Map m = newMap(-1); for (; ; ) { Object key = readVal(dis); if (key == END_OBJ) break; @@ -638,10 +638,18 @@ public class JavaBinCodec implements PushWriter { return m; } + /** + * create a new Map object + * @param size expected size, -1 means unknown size + */ + protected Map newMap(int size) { + return size < 0 ? new LinkedHashMap<>() : new LinkedHashMap<>(size); + } + public Map readMap(DataInputInputStream dis) throws IOException { int sz = readVInt(dis); - Map m = new LinkedHashMap<>(sz); + Map m = newMap(sz); for (int i = 0; i < sz; i++) { Object key = readVal(dis); Object val = readVal(dis); http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/common/util/JsonSchemaValidator.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/common/util/JsonSchemaValidator.java b/solr/solrj/src/java/org/apache/solr/common/util/JsonSchemaValidator.java index e7b725f..e5a1d44 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/JsonSchemaValidator.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/JsonSchemaValidator.java @@ -94,8 +94,32 @@ enum Type { STRING(String.class), ARRAY(List.class), NUMBER(Number.class), - INTEGER(Long.class), - BOOLEAN(Boolean.class), + INTEGER(Long.class){ + @Override + boolean isValid(Object o) { + if(super.isValid(o)) return true; + try { + Long.parseLong(String.valueOf(o)); + return true; + } catch (NumberFormatException e) { + return false; + + } + } + }, + BOOLEAN(Boolean.class){ + @Override + boolean isValid(Object o) { + if(super.isValid(o)) return true; + try { + Boolean.parseBoolean (String.valueOf(o)); + return true; + } catch (NumberFormatException e) { + return false; + } + + } + }, ENUM(List.class), OBJECT(Map.class), NULL(null), http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/common/util/Template.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/common/util/Template.java b/solr/solrj/src/java/org/apache/solr/common/util/Template.java new file mode 100644 index 0000000..478addc --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/common/util/Template.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.common.util; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Template { + public final String template; + public static final Pattern DOLLAR_BRACES_PLACEHOLDER_PATTERN = Pattern + .compile("[$][{](.*?)[}]"); + public static final Pattern BRACES_PLACEHOLDER_PATTERN = Pattern + .compile("[{](.*?)[}]"); + + + public Template(String template, Pattern pattern) { + this.template = template; + List variables = new ArrayList<>(2); + Matcher m = pattern.matcher(template); + while (m.find()) { + String variable = m.group(1); + startIndexes.add(m.start(0)); + endOffsets.add(m.end(0)); + variables.add(variable); + } + this.variables = Collections.unmodifiableList(variables); + + } + + public String apply(Function valueSupplier) { + if (startIndexes != null) { + StringBuilder sb = new StringBuilder(template); + for (int i = startIndexes.size() - 1; i >= 0; i--) { + String replacement = valueSupplier.apply(variables.get(i)).toString(); + sb.replace(startIndexes.get(i), endOffsets.get(i), replacement); + } + return sb.toString(); + } else { + return template; + } + } + + private List startIndexes = new ArrayList<>(2); + private List endOffsets = new ArrayList<>(2); + public final List variables ; +} http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/java/org/apache/solr/common/util/Utils.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/java/org/apache/solr/common/util/Utils.java b/solr/solrj/src/java/org/apache/solr/common/util/Utils.java index b64f971..66e21c0 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/Utils.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/Utils.java @@ -22,6 +22,7 @@ import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.lang.invoke.MethodHandles; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -39,6 +40,7 @@ import java.util.regex.Pattern; import org.apache.http.HttpEntity; import org.apache.http.util.EntityUtils; +import org.apache.solr.client.solrj.impl.BinaryRequestWriter; import org.apache.solr.common.IteratorWriter; import org.apache.solr.common.MapWriter; import org.apache.solr.common.SolrException; @@ -47,6 +49,7 @@ import org.apache.solr.common.cloud.SolrZkClient; import org.apache.solr.common.cloud.ZkOperation; import org.apache.solr.common.params.CommonParams; import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.server.ByteBufferInputStream; import org.noggit.CharArr; import org.noggit.JSONParser; import org.noggit.JSONWriter; @@ -102,6 +105,12 @@ public class Utils { return v; } + public static InputStream toJavabin(Object o) throws IOException { + BinaryRequestWriter.BAOS baos = new BinaryRequestWriter.BAOS(); + new JavaBinCodec().marshal(o,baos); + return new ByteBufferInputStream(ByteBuffer.wrap(baos.getbuf(),0,baos.size())); + } + public static Collection getDeepCopy(Collection c, int maxDepth, boolean mutable) { return getDeepCopy(c, maxDepth, mutable, false); } http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f6f6f113/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV1toV2ApiMapper.java ---------------------------------------------------------------------- diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV1toV2ApiMapper.java b/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV1toV2ApiMapper.java new file mode 100644 index 0000000..7daefb9 --- /dev/null +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/request/TestV1toV2ApiMapper.java @@ -0,0 +1,55 @@ +/* + * 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.request; + +import java.io.IOException; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import org.apache.lucene.util.LuceneTestCase; +import org.apache.solr.client.solrj.request.CollectionAdminRequest.Create; +import org.apache.solr.common.util.Utils; + +public class TestV1toV2ApiMapper extends LuceneTestCase { + + public void testCommands() throws IOException { + Create cmd = CollectionAdminRequest + .createCollection("mycoll", "conf1", 3, 2) + .setProperties(ImmutableMap.builder() + .put("p1","v1") + .put("p2","v2") + .build()); + V2Request v2r = V1toV2ApiMapper.convert(cmd).build(); + Map m = (Map) Utils.fromJSON(v2r.getContentStreams().iterator().next().getStream()); + assertEquals("/c", v2r.getPath()); + assertEquals("v1", Utils.getObjectByPath(m,true,"/create/properties/p1")); + assertEquals("v2", Utils.getObjectByPath(m,true,"/create/properties/p2")); + assertEquals("3", Utils.getObjectByPath(m,true,"/create/numShards")); + assertEquals("2", Utils.getObjectByPath(m,true,"/create/nrtReplicas")); + + CollectionAdminRequest.AddReplica addReplica = CollectionAdminRequest.addReplicaToShard("mycoll", "shard1"); + v2r = V1toV2ApiMapper.convert(addReplica).build(); + m = (Map) Utils.fromJSON(v2r.getContentStreams().iterator().next().getStream()); + assertEquals("/c/mycoll/shards", v2r.getPath()); + assertEquals("shard1", Utils.getObjectByPath(m,true,"/add-replica/shard")); + assertEquals("NRT", Utils.getObjectByPath(m,true,"/add-replica/type")); + + + + } +}