This is an automated email from the ASF dual-hosted git repository.
gerlowskija pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new df88d65 SOLR-15745: Move public v2 "core-admin" APIs to annotation
framework (#565)
df88d65 is described below
commit df88d65a2a83833116db355b722f91771949bef6
Author: Jason Gerlowski <[email protected]>
AuthorDate: Thu Jan 27 06:41:16 2022 -0500
SOLR-15745: Move public v2 "core-admin" APIs to annotation framework (#565)
Solr's been in the slow process of moving its v2 APIs away from the
existing apispec/mapping framework towards one that relies on more
explicit annotations to specify API properties.
This commit converts the 'reload', 'swap', 'rename', 'unload',
'merge-indexes', and 'split' commands of `/v2/cores/<core>` over to the
preferred framework.
(NOTE: the spelling 'indexes' in the 'merge-indexes' command was
retained here for consistency/compatibility. We should consider
changing it going forward.)
---
.../java/org/apache/solr/handler/ClusterAPI.java | 26 +--
.../solr/handler/admin/CoreAdminHandler.java | 12 ++
.../solr/handler/admin/api/MergeIndexesAPI.java | 91 +++++++++
.../solr/handler/admin/api/ReloadCoreAPI.java | 69 +++++++
.../solr/handler/admin/api/RenameCoreAPI.java | 72 ++++++++
.../solr/handler/admin/api/SplitCoreAPI.java | 103 +++++++++++
.../solr/handler/admin/api/SwapCoresAPI.java | 77 ++++++++
.../solr/handler/admin/api/UnloadCoreAPI.java | 78 ++++++++
.../handler/admin/api/V2CoreAPIMappingTest.java | 203 +++++++++++++++++++++
.../solr/client/solrj/request/CoreApiMapping.java | 6 -
.../src/resources/apispec/cores.core.Commands.json | 93 ----------
.../apispec/cores.core.Commands.split.json | 34 ----
.../apache/solr/common/util/JsonValidatorTest.java | 27 +--
13 files changed, 721 insertions(+), 170 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
index a40acc0..42f5082 100644
--- a/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/ClusterAPI.java
@@ -17,9 +17,6 @@
package org.apache.solr.handler;
-import java.io.IOException;
-import java.util.*;
-
import com.google.common.collect.Maps;
import org.apache.solr.api.Command;
import org.apache.solr.api.EndPoint;
@@ -48,18 +45,21 @@ import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.zookeeper.KeeperException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
import static org.apache.solr.client.solrj.SolrRequest.METHOD.DELETE;
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.PUT;
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.*;
import static
org.apache.solr.cloud.api.collections.CollectionHandlingUtils.REQUESTID;
import static org.apache.solr.common.params.CollectionParams.ACTION;
import static
org.apache.solr.common.params.CollectionParams.CollectionAction.*;
import static org.apache.solr.core.RateLimiterConfig.RL_CONFIG_KEY;
-import static
org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
-import static
org.apache.solr.security.PermissionNameProvider.Name.COLL_READ_PERM;
-import static
org.apache.solr.security.PermissionNameProvider.Name.CONFIG_EDIT_PERM;
-import static
org.apache.solr.security.PermissionNameProvider.Name.CONFIG_READ_PERM;
+import static org.apache.solr.security.PermissionNameProvider.Name.*;
/**
* All V2 APIs that have a prefix of /api/cluster/
@@ -293,7 +293,11 @@ public class ClusterAPI {
ModifiableSolrParams solrParams = new ModifiableSolrParams();
m.forEach((k, v) -> {
if (v == null) return;
- solrParams.add(k.toString(), String.valueOf(v));
+ if (v instanceof String[]) {
+ solrParams.add(k, (String[]) v);
+ } else {
+ solrParams.add(k, String.valueOf(v));
+ }
});
DefaultSolrParams dsp = new DefaultSolrParams(req.getParams(), solrParams);
req.setParams(dsp);
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
index 52b2944..27e6116 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
@@ -39,9 +39,15 @@ import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.handler.admin.api.AllCoresStatusAPI;
import org.apache.solr.handler.admin.api.CreateCoreAPI;
import org.apache.solr.handler.admin.api.InvokeClassAPI;
+import org.apache.solr.handler.admin.api.MergeIndexesAPI;
import org.apache.solr.handler.admin.api.OverseerOperationAPI;
import org.apache.solr.handler.admin.api.RejoinLeaderElectionAPI;
+import org.apache.solr.handler.admin.api.ReloadCoreAPI;
+import org.apache.solr.handler.admin.api.RenameCoreAPI;
import org.apache.solr.handler.admin.api.SingleCoreStatusAPI;
+import org.apache.solr.handler.admin.api.SplitCoreAPI;
+import org.apache.solr.handler.admin.api.SwapCoresAPI;
+import org.apache.solr.handler.admin.api.UnloadCoreAPI;
import org.apache.solr.logging.MDCLoggingContext;
import org.apache.solr.metrics.SolrMetricManager;
import org.apache.solr.metrics.SolrMetricsContext;
@@ -429,6 +435,12 @@ public class CoreAdminHandler extends RequestHandlerBase
implements PermissionNa
apis.addAll(AnnotatedApi.getApis(new InvokeClassAPI(this)));
apis.addAll(AnnotatedApi.getApis(new RejoinLeaderElectionAPI(this)));
apis.addAll(AnnotatedApi.getApis(new OverseerOperationAPI(this)));
+ apis.addAll(AnnotatedApi.getApis(new ReloadCoreAPI(this)));
+ apis.addAll(AnnotatedApi.getApis(new SwapCoresAPI(this)));
+ apis.addAll(AnnotatedApi.getApis(new RenameCoreAPI(this)));
+ apis.addAll(AnnotatedApi.getApis(new UnloadCoreAPI(this)));
+ apis.addAll(AnnotatedApi.getApis(new MergeIndexesAPI(this)));
+ apis.addAll(AnnotatedApi.getApis(new SplitCoreAPI(this)));
return apis;
}
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/MergeIndexesAPI.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/MergeIndexesAPI.java
new file mode 100644
index 0000000..21e7787
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/MergeIndexesAPI.java
@@ -0,0 +1,91 @@
+/*
+ * 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.handler.admin.api;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.solr.api.Command;
+import org.apache.solr.api.EndPoint;
+import org.apache.solr.api.PayloadObj;
+import org.apache.solr.common.annotation.JsonProperty;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.params.UpdateParams;
+import org.apache.solr.common.util.ReflectMapWriter;
+import org.apache.solr.handler.admin.CoreAdminHandler;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
+import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static
org.apache.solr.security.PermissionNameProvider.Name.CORE_EDIT_PERM;
+
+/**
+ * V2 API for merging one or more Solr cores into the target core.
+ *
+ * The new API (POST /v2/cores/coreName {'merge-indexes': {...}}) is
equivalent to the v1
+ * /admin/cores?action=mergeindexes command.
+ */
+@EndPoint(
+ path = {"/cores/{core}"},
+ method = POST,
+ permission = CORE_EDIT_PERM)
+public class MergeIndexesAPI {
+ private static final String V2_MERGE_INDEXES_CORE_CMD = "merge-indexes";
+
+ private final CoreAdminHandler coreHandler;
+
+ public MergeIndexesAPI(CoreAdminHandler coreHandler) {
+ this.coreHandler = coreHandler;
+ }
+
+ @Command(name = V2_MERGE_INDEXES_CORE_CMD)
+ public void mergeIndexesIntoCore(PayloadObj<MergeIndexesPayload> obj)
throws Exception {
+ final MergeIndexesPayload v2Body = obj.get();
+ final Map<String, Object> v1Params = v2Body.toMap(new HashMap<>());
+ v1Params.put(CoreAdminParams.ACTION,
CoreAdminParams.CoreAdminAction.MERGEINDEXES.name().toLowerCase(Locale.ROOT));
+ v1Params.put(CoreAdminParams.CORE,
obj.getRequest().getPathTemplateValues().get(CoreAdminParams.CORE));
+ if (! CollectionUtils.isEmpty(v2Body.indexDir)) {
+ v1Params.put("indexDir", v2Body.indexDir.toArray(new
String[v2Body.indexDir.size()]));
+ }
+ if (! CollectionUtils.isEmpty(v2Body.srcCore)) {
+ v1Params.put("srcCore", v2Body.srcCore.toArray(new
String[v2Body.srcCore.size()]));
+ }
+ // V1 API uses 'update.chain' instead of 'updateChain'.
+ if (v2Body.updateChain != null) {
+ v1Params.put(UpdateParams.UPDATE_CHAIN,
v1Params.remove("updateChain"));
+ }
+
+ coreHandler.handleRequestBody(wrapParams(obj.getRequest(), v1Params),
obj.getResponse());
+ }
+
+ public static class MergeIndexesPayload implements ReflectMapWriter {
+ @JsonProperty
+ public List<String> indexDir;
+
+ @JsonProperty
+ public List<String> srcCore;
+
+ @JsonProperty
+ public String updateChain;
+
+ @JsonProperty
+ public String async;
+ }
+}
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCoreAPI.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCoreAPI.java
new file mode 100644
index 0000000..2ee076a
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ReloadCoreAPI.java
@@ -0,0 +1,69 @@
+/*
+ * 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.handler.admin.api;
+
+import org.apache.solr.api.Command;
+import org.apache.solr.api.EndPoint;
+import org.apache.solr.api.PayloadObj;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.util.ReflectMapWriter;
+import org.apache.solr.handler.admin.CoreAdminHandler;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
+import static org.apache.solr.common.params.CommonParams.ACTION;
+import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static
org.apache.solr.security.PermissionNameProvider.Name.CORE_EDIT_PERM;
+
+/**
+ * V2 API for reloading an individual core.
+ *
+ * The new API (POST /v2/cores/coreName {'reload': {...}}) is equivalent to
the v1
+ * /admin/cores?action=reload command.
+ *
+ * @see ReloadCorePayload
+ */
+@EndPoint(
+ path = {"/cores/{core}"},
+ method = POST,
+ permission = CORE_EDIT_PERM)
+public class ReloadCoreAPI {
+ private static final String V2_RELOAD_CORE_CMD = "reload";
+
+ private final CoreAdminHandler coreHandler;
+
+ public ReloadCoreAPI(CoreAdminHandler coreHandler) {
+ this.coreHandler = coreHandler;
+ }
+
+ @Command(name = V2_RELOAD_CORE_CMD)
+ public void reloadCore(PayloadObj<ReloadCorePayload> obj) throws Exception
{
+ final String coreName =
obj.getRequest().getPathTemplateValues().get(CoreAdminParams.CORE);
+
+ final Map<String, Object> v1Params = new HashMap<>();
+ v1Params.put(ACTION,
CoreAdminParams.CoreAdminAction.RELOAD.name().toLowerCase(Locale.ROOT));
+ v1Params.put(CoreAdminParams.CORE, coreName);
+
+ coreHandler.handleRequestBody(wrapParams(obj.getRequest(), v1Params),
obj.getResponse());
+ }
+
+ public static class ReloadCorePayload implements ReflectMapWriter {}
+}
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/RenameCoreAPI.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/RenameCoreAPI.java
new file mode 100644
index 0000000..8782792
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/RenameCoreAPI.java
@@ -0,0 +1,72 @@
+/*
+ * 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.handler.admin.api;
+
+import org.apache.solr.api.Command;
+import org.apache.solr.api.EndPoint;
+import org.apache.solr.api.PayloadObj;
+import org.apache.solr.common.annotation.JsonProperty;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.util.ReflectMapWriter;
+import org.apache.solr.handler.admin.CoreAdminHandler;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
+import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static
org.apache.solr.security.PermissionNameProvider.Name.CORE_EDIT_PERM;
+
+/**
+ * V2 API for renaming an existing Solr core.
+ *
+ * The new API (POST /v2/cores/coreName {'rename': {...}}) is equivalent to
the v1
+ * /admin/cores?action=rename command.
+ */
+@EndPoint(
+ path = {"/cores/{core}"},
+ method = POST,
+ permission = CORE_EDIT_PERM)
+public class RenameCoreAPI {
+ private static final String V2_RENAME_CORE_CMD = "rename";
+
+ private final CoreAdminHandler coreHandler;
+
+ public RenameCoreAPI(CoreAdminHandler coreHandler) {
+ this.coreHandler = coreHandler;
+ }
+
+ @Command(name = V2_RENAME_CORE_CMD)
+ public void renameCore(PayloadObj<RenameCorePayload> obj) throws Exception
{
+ final RenameCorePayload v2Body = obj.get();
+ final Map<String, Object> v1Params = v2Body.toMap(new HashMap<>());
+ v1Params.put(CoreAdminParams.ACTION,
CoreAdminParams.CoreAdminAction.RENAME.name().toLowerCase(Locale.ROOT));
+ v1Params.put(CoreAdminParams.CORE,
obj.getRequest().getPathTemplateValues().get(CoreAdminParams.CORE));
+
+ // V1 API uses 'other' instead of 'to' to represent the new core name.
+ v1Params.put(CoreAdminParams.OTHER, v1Params.remove("to"));
+
+ coreHandler.handleRequestBody(wrapParams(obj.getRequest(), v1Params),
obj.getResponse());
+ }
+
+ public static class RenameCorePayload implements ReflectMapWriter {
+ @JsonProperty(required = true)
+ public String to;
+ }
+}
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/SplitCoreAPI.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/SplitCoreAPI.java
new file mode 100644
index 0000000..6f9404a
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/SplitCoreAPI.java
@@ -0,0 +1,103 @@
+/*
+ * 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.handler.admin.api;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.solr.api.Command;
+import org.apache.solr.api.EndPoint;
+import org.apache.solr.api.PayloadObj;
+import org.apache.solr.common.annotation.JsonProperty;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.util.ReflectMapWriter;
+import org.apache.solr.handler.admin.CoreAdminHandler;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
+import static org.apache.solr.common.params.CommonAdminParams.SPLIT_KEY;
+import static org.apache.solr.common.params.CommonParams.PATH;
+import static org.apache.solr.common.params.CoreAdminParams.TARGET_CORE;
+import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static
org.apache.solr.security.PermissionNameProvider.Name.CORE_EDIT_PERM;
+
+/**
+ * V2 API for splitting a single core into multiple pieces
+ *
+ * The new API (POST /v2/cores/coreName {'split': {...}}) is equivalent to the
v1
+ * /admin/cores?action=split command.
+ */
+@EndPoint(
+ path = {"/cores/{core}"},
+ method = POST,
+ permission = CORE_EDIT_PERM)
+public class SplitCoreAPI {
+ private static final String V2_SPLIT_CORE_CMD = "split";
+
+ private final CoreAdminHandler coreHandler;
+
+ public SplitCoreAPI(CoreAdminHandler coreHandler) {
+ this.coreHandler = coreHandler;
+ }
+
+ @Command(name = V2_SPLIT_CORE_CMD)
+ public void splitCore(PayloadObj<SplitCorePayload> obj) throws Exception {
+ final SplitCorePayload v2Body = obj.get();
+ final Map<String, Object> v1Params = v2Body.toMap(new HashMap<>());
+ v1Params.put(CoreAdminParams.ACTION,
CoreAdminParams.CoreAdminAction.SPLIT.name().toLowerCase(Locale.ROOT));
+ v1Params.put(CoreAdminParams.CORE,
obj.getRequest().getPathTemplateValues().get(CoreAdminParams.CORE));
+
+ if (! CollectionUtils.isEmpty(v2Body.path)) {
+ v1Params.put(PATH, v2Body.path.toArray(new
String[v2Body.path.size()]));
+ }
+ if (! CollectionUtils.isEmpty(v2Body.targetCore)) {
+ v1Params.put(TARGET_CORE, v2Body.targetCore.toArray(new
String[v2Body.targetCore.size()]));
+ }
+
+ if (v2Body.splitKey != null) {
+ v1Params.put(SPLIT_KEY, v1Params.remove("splitKey"));
+ }
+
+ coreHandler.handleRequestBody(wrapParams(obj.getRequest(), v1Params),
obj.getResponse());
+ }
+
+ public static class SplitCorePayload implements ReflectMapWriter {
+ @JsonProperty
+ public List<String> path;
+
+ @JsonProperty
+ public List<String> targetCore;
+
+ @JsonProperty
+ public String splitKey;
+
+ @JsonProperty
+ public String splitMethod;
+
+ @JsonProperty
+ public Boolean getRanges;
+
+ @JsonProperty
+ public String ranges;
+
+ @JsonProperty
+ public String async;
+ }
+}
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/SwapCoresAPI.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/SwapCoresAPI.java
new file mode 100644
index 0000000..77a0a0b
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/SwapCoresAPI.java
@@ -0,0 +1,77 @@
+/*
+ * 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.handler.admin.api;
+
+import org.apache.solr.api.Command;
+import org.apache.solr.api.EndPoint;
+import org.apache.solr.api.PayloadObj;
+import org.apache.solr.common.annotation.JsonProperty;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.util.ReflectMapWriter;
+import org.apache.solr.handler.admin.CoreAdminHandler;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
+import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static
org.apache.solr.security.PermissionNameProvider.Name.CORE_EDIT_PERM;
+
+/**
+ * V2 API for swapping two existing Solr cores.
+ *
+ * Not intended for use in SolrCloud mode.
+ *
+ * The new API (POST /v2/cores/coreName {'swap': {...}}) is equivalent to the
v1
+ * /admin/cores?action=swap command.
+ */
+@EndPoint(
+ path = {"/cores/{core}"},
+ method = POST,
+ permission = CORE_EDIT_PERM)
+public class SwapCoresAPI {
+ private static final String V2_SWAP_CORES_CMD = "swap";
+
+ private final CoreAdminHandler coreHandler;
+
+ public SwapCoresAPI(CoreAdminHandler coreHandler) {
+ this.coreHandler = coreHandler;
+ }
+
+ @Command(name = V2_SWAP_CORES_CMD)
+ public void swapCores(PayloadObj<SwapCoresPayload> obj) throws Exception {
+ final SwapCoresPayload v2Body = obj.get();
+ final Map<String, Object> v1Params = v2Body.toMap(new HashMap<>());
+ v1Params.put(CoreAdminParams.ACTION,
CoreAdminParams.CoreAdminAction.SWAP.name().toLowerCase(Locale.ROOT));
+ v1Params.put(CoreAdminParams.CORE,
obj.getRequest().getPathTemplateValues().get(CoreAdminParams.CORE));
+
+ // V1 API uses 'other' instead of 'with' to represent the
second/replacement core.
+ v1Params.put(CoreAdminParams.OTHER, v1Params.remove("with"));
+
+ coreHandler.handleRequestBody(wrapParams(obj.getRequest(), v1Params),
obj.getResponse());
+ }
+
+ public static class SwapCoresPayload implements ReflectMapWriter {
+ @JsonProperty(required = true)
+ public String with;
+
+ @JsonProperty
+ public String async;
+ }
+}
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/UnloadCoreAPI.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/UnloadCoreAPI.java
new file mode 100644
index 0000000..91f6e06
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/UnloadCoreAPI.java
@@ -0,0 +1,78 @@
+/*
+ * 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.handler.admin.api;
+
+import org.apache.solr.api.Command;
+import org.apache.solr.api.EndPoint;
+import org.apache.solr.api.PayloadObj;
+import org.apache.solr.common.annotation.JsonProperty;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.common.util.ReflectMapWriter;
+import org.apache.solr.handler.admin.CoreAdminHandler;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
+import static org.apache.solr.handler.ClusterAPI.wrapParams;
+import static
org.apache.solr.security.PermissionNameProvider.Name.CORE_EDIT_PERM;
+
+/**
+ * V2 API for renaming an existing Solr core.
+ *
+ * The new API (POST /v2/cores/coreName {'unload': {...}}) is equivalent to
the v1
+ * /admin/cores?action=unload command.
+ */
+@EndPoint(
+ path = {"/cores/{core}"},
+ method = POST,
+ permission = CORE_EDIT_PERM)
+public class UnloadCoreAPI {
+ private static final String V2_UNLOAD_CORE_CMD = "unload";
+
+ private final CoreAdminHandler coreHandler;
+
+ public UnloadCoreAPI(CoreAdminHandler coreHandler) {
+ this.coreHandler = coreHandler;
+ }
+
+ @Command(name = V2_UNLOAD_CORE_CMD)
+ public void unloadCore(PayloadObj<UnloadCorePayload> obj) throws Exception
{
+ final UnloadCorePayload v2Body = obj.get();
+ final Map<String, Object> v1Params = v2Body.toMap(new HashMap<>());
+ v1Params.put(CoreAdminParams.ACTION,
CoreAdminParams.CoreAdminAction.UNLOAD.name().toLowerCase(Locale.ROOT));
+ v1Params.put(CoreAdminParams.CORE,
obj.getRequest().getPathTemplateValues().get(CoreAdminParams.CORE));
+
+ coreHandler.handleRequestBody(wrapParams(obj.getRequest(), v1Params),
obj.getResponse());
+ }
+
+ public static class UnloadCorePayload implements ReflectMapWriter {
+ @JsonProperty
+ public Boolean deleteIndex;
+
+ @JsonProperty
+ public Boolean deleteDataDir;
+
+ @JsonProperty
+ public Boolean deleteInstanceDir;
+
+ @JsonProperty
+ public String async;
+ }
+}
diff --git
a/solr/core/src/test/org/apache/solr/handler/admin/api/V2CoreAPIMappingTest.java
b/solr/core/src/test/org/apache/solr/handler/admin/api/V2CoreAPIMappingTest.java
new file mode 100644
index 0000000..7dbd3f7
--- /dev/null
+++
b/solr/core/src/test/org/apache/solr/handler/admin/api/V2CoreAPIMappingTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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.handler.admin.api;
+
+import com.google.common.collect.Maps;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.api.Api;
+import org.apache.solr.api.ApiBag;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.params.UpdateParams;
+import org.apache.solr.common.util.CommandOperation;
+import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.handler.admin.CoreAdminHandler;
+import org.apache.solr.request.LocalSolrQueryRequest;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.solr.common.params.CommonAdminParams.ASYNC;
+import static org.apache.solr.common.params.CommonAdminParams.SPLIT_KEY;
+import static org.apache.solr.common.params.CommonParams.ACTION;
+import static org.apache.solr.common.params.CommonParams.PATH;
+import static org.apache.solr.common.params.CoreAdminParams.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Unit tests for the V2 APIs found in {@link
org.apache.solr.handler.admin.api} that use the /cores/{core} path.
+ *
+ * Note that the V2 requests made by these tests are not necessarily
semantically valid. They shouldn't be taken as
+ * examples. In several instances, mutually exclusive JSON parameters are
provided. This is done to exercise conversion
+ * of all parameters, even if particular combinations are never expected in
the same request.
+ */
+public class V2CoreAPIMappingTest extends SolrTestCaseJ4 {
+ private ApiBag apiBag;
+
+ private ArgumentCaptor<SolrQueryRequest> queryRequestCaptor;
+
+ private CoreAdminHandler mockCoreHandler;
+
+ @BeforeClass
+ public static void ensureWorkingMockito() {
+ assumeWorkingMockito();
+ }
+
+ @Before
+ public void setupApiBag() throws Exception {
+ mockCoreHandler = mock(CoreAdminHandler.class);
+ queryRequestCaptor = ArgumentCaptor.forClass(SolrQueryRequest.class);
+
+ apiBag = new ApiBag(false);
+ apiBag.registerObject(new ReloadCoreAPI(mockCoreHandler));
+ apiBag.registerObject(new SwapCoresAPI(mockCoreHandler));
+ apiBag.registerObject(new RenameCoreAPI(mockCoreHandler));
+ apiBag.registerObject(new UnloadCoreAPI(mockCoreHandler));
+ apiBag.registerObject(new MergeIndexesAPI(mockCoreHandler));
+ apiBag.registerObject(new SplitCoreAPI(mockCoreHandler));
+ }
+
+ @Test
+ public void testReloadCoreAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cores/coreName", "POST", "{\"reload\": {}}");
+
+ assertEquals("reload", v1Params.get(ACTION));
+ assertEquals("coreName", v1Params.get(CORE));
+ }
+
+ @Test
+ public void testSwapCoresAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cores/coreName", "POST", "{\"swap\": {\"with\":
\"otherCore\"}}");
+
+ assertEquals("swap", v1Params.get(ACTION));
+ assertEquals("coreName", v1Params.get(CORE));
+ assertEquals("otherCore", v1Params.get(OTHER));
+ }
+
+ @Test
+ public void testRenameCoreAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cores/coreName", "POST", "{\"rename\": {\"to\":
\"otherCore\"}}");
+
+ assertEquals("rename", v1Params.get(ACTION));
+ assertEquals("coreName", v1Params.get(CORE));
+ assertEquals("otherCore", v1Params.get(OTHER));
+ }
+
+ @Test
+ public void testUnloadCoreAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cores/coreName", "POST",
+ "{" +
+ "\"unload\": {" +
+ "\"deleteIndex\": true, " +
+ "\"deleteDataDir\": true, " +
+ "\"deleteInstanceDir\": true, " +
+ "\"async\": \"someRequestId\"}}");
+
+ assertEquals("unload", v1Params.get(ACTION));
+ assertEquals("coreName", v1Params.get(CORE));
+ assertEquals(true, v1Params.getBool(DELETE_INDEX));
+ assertEquals(true, v1Params.getBool(DELETE_DATA_DIR));
+ assertEquals(true, v1Params.getBool(DELETE_INSTANCE_DIR));
+ assertEquals("someRequestId", v1Params.get(ASYNC));
+ }
+
+ @Test
+ public void testMergeIndexesAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cores/coreName", "POST",
+ "{" +
+ "\"merge-indexes\": {" +
+ "\"indexDir\": [\"dir1\", \"dir2\"], " +
+ "\"srcCore\": [\"core1\", \"core2\"], " +
+ "\"updateChain\": \"someUpdateChain\", " +
+ "\"async\": \"someRequestId\"}}");
+
+ assertEquals("mergeindexes", v1Params.get(ACTION));
+ assertEquals("coreName", v1Params.get(CORE));
+ assertEquals("someUpdateChain",
v1Params.get(UpdateParams.UPDATE_CHAIN));
+ assertEquals("someRequestId", v1Params.get(ASYNC));
+ final List<String> indexDirs =
Arrays.asList(v1Params.getParams("indexDir"));
+ assertEquals(2, indexDirs.size());
+ assertTrue(indexDirs.containsAll(List.of("dir1", "dir2")));
+ final List<String> srcCores =
Arrays.asList(v1Params.getParams("srcCore"));
+ assertEquals(2, srcCores.size());
+ assertTrue(srcCores.containsAll(List.of("core1", "core2")));
+ }
+
+ @Test
+ public void testSplitCoreAllParams() throws Exception {
+ final SolrParams v1Params =
captureConvertedV1Params("/cores/coreName", "POST",
+ "{" +
+ "\"split\": {" +
+ "\"path\": [\"path1\", \"path2\"], " +
+ "\"targetCore\": [\"core1\", \"core2\"], " +
+ "\"splitKey\": \"someSplitKey\", " +
+ "\"getRanges\": true, " +
+ "\"ranges\": \"range1,range2\", " +
+ "\"async\": \"someRequestId\"}}");
+
+ assertEquals("split", v1Params.get(ACTION));
+ assertEquals("coreName", v1Params.get(CORE));
+ assertEquals("someSplitKey", v1Params.get(SPLIT_KEY));
+ assertEquals("range1,range2", v1Params.get(RANGES));
+ assertEquals("someRequestId", v1Params.get(ASYNC));
+ final List<String> pathEntries =
Arrays.asList(v1Params.getParams(PATH));
+ assertEquals(2, pathEntries.size());
+ assertTrue(pathEntries.containsAll(List.of("path1", "path2")));
+ final List<String> targetCoreEntries =
Arrays.asList(v1Params.getParams(TARGET_CORE));
+ assertEquals(2, targetCoreEntries.size());
+ assertTrue(targetCoreEntries.containsAll(List.of("core1", "core2")));
+ }
+
+ private SolrParams captureConvertedV1Params(String path, String method,
String v2RequestBody) throws Exception {
+ final HashMap<String, String> parts = new HashMap<>();
+ final Api api = apiBag.lookup(path, method, parts);
+ final SolrQueryResponse rsp = new SolrQueryResponse();
+ final LocalSolrQueryRequest req = new LocalSolrQueryRequest(null,
Maps.newHashMap()) {
+ @Override
+ public List<CommandOperation> getCommands(boolean validateInput) {
+ if (v2RequestBody == null) return Collections.emptyList();
+ return ApiBag.getCommandOperations(new
ContentStreamBase.StringStream(v2RequestBody), api.getCommandSchema(), true);
+ }
+
+ @Override
+ public Map<String, String> getPathTemplateValues() {
+ return parts;
+ }
+
+ @Override
+ public String getHttpMethod() {
+ return method;
+ }
+ };
+
+
+ api.call(req, rsp);
+
verify(mockCoreHandler).handleRequestBody(queryRequestCaptor.capture(), any());
+ return queryRequestCaptor.getValue().getParams();
+ }
+}
diff --git
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreApiMapping.java
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreApiMapping.java
index 52e78a6..fbd8444 100644
---
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreApiMapping.java
+++
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreApiMapping.java
@@ -35,12 +35,6 @@ import static
org.apache.solr.client.solrj.request.CoreApiMapping.EndPoint.*;
*/
public class CoreApiMapping {
public enum Meta implements CommandMeta {
- UNLOAD(PER_CORE_COMMANDS, POST, CoreAdminAction.UNLOAD, "unload", null),
- RELOAD(PER_CORE_COMMANDS, POST, CoreAdminAction.RELOAD, "reload", null),
- SWAP(PER_CORE_COMMANDS, POST, CoreAdminAction.SWAP, "swap",
Collections.singletonMap("other", "with")),
- RENAME(PER_CORE_COMMANDS, POST, CoreAdminAction.RENAME, "rename",
Collections.singletonMap("other", "to")),
- MERGEINDEXES(PER_CORE_COMMANDS, POST, CoreAdminAction.MERGEINDEXES,
"merge-indexes", null),
- SPLIT(PER_CORE_COMMANDS, POST, CoreAdminAction.SPLIT, "split",
Collections.singletonMap("split.key", "splitKey")),
PREPRECOVERY(PER_CORE_COMMANDS, POST, CoreAdminAction.PREPRECOVERY,
"prep-recovery", null),
REQUESTRECOVERY(PER_CORE_COMMANDS, POST, CoreAdminAction.REQUESTRECOVERY,
"request-recovery", null),
REQUESTSYNCSHARD(PER_CORE_COMMANDS, POST,
CoreAdminAction.REQUESTSYNCSHARD, "request-sync-shard", null),
diff --git a/solr/solrj/src/resources/apispec/cores.core.Commands.json
b/solr/solrj/src/resources/apispec/cores.core.Commands.json
index 34a70d6..0afe981 100644
--- a/solr/solrj/src/resources/apispec/cores.core.Commands.json
+++ b/solr/solrj/src/resources/apispec/cores.core.Commands.json
@@ -10,99 +10,6 @@
]
},
"commands": {
- "reload": {
- "type":"object",
- "documentation":
"https://solr.apache.org/guide/coreadmin-api.html#coreadmin-reload",
- "description": "Reloads a core. This is useful when you have made
changes on disk such as editing the schema or solrconfig.xml files. Most APIs
reload cores automatically, so this should not be necessary if changes were
made with those APIs."
- },
- "swap": {
- "type":"object",
- "documentation":
"https://solr.apache.org/guide/coreadmin-api.html#coreadmin-swap",
- "description": "Swaps the names of two existing Solr cores. This can be
used to swap new content into production. The former core can be swapped back
if necessary. Using this API is not supported in SolrCloud mode.",
- "properties": {
- "with": {
- "type": "string",
- "description": "The name of the other core to be swapped (the first
core name is included in the request)."
- },
- "async": {
- "type": "string",
- "description": "Defines a request ID that can be used to track this
action after it's submitted. The action will be processed asynchronously when
this is defined."
- }
- },
- "required": [
- "with"
- ]
- },
- "rename": {
- "type": "object",
- "documentation":
"https://solr.apache.org/guide/coreadmin-api.html#coreadmin-rename",
- "description": "Change the name of a core.",
- "properties": {
- "to": {
- "type": "string",
- "description": "The new name for the core."
- },
- "async": {
- "type": "string",
- "description": "Defines a request ID that can be used to track this
action after it's submitted. The action will be processed asynchronously when
this is defined."
- }
- },
- "required": [
- "to"
- ]
- },
- "unload": {
- "type": "object",
- "documentation":
"https://solr.apache.org/guide/coreadmin-api.html#coreadmin-unload",
- "description": "Removes a core. Active requests would continue to be
processed, but new requests will not be sent to the new core. If a core is
registered under more than one name, only the name given in the request is
removed.",
- "properties": {
- "deleteIndex": {
- "type": "boolean",
- "description": "If true, the index will be removed while unloading
the core.",
- "default": "false"
- },
- "deleteDataDir": {
- "type": "boolean",
- "description": "If true, the data directory and all sub-directories
will be removed while unloading the core.",
- "default": "false"
- },
- "deleteInstanceDir": {
- "type": "boolean",
- "description": "If true, everything related to the core, including
the index, data, and conf directories, will be removed while unloading the
core.",
- "default": "false"
- },
- "async": {
- "type": "string",
- "description": "Defines a request ID that can be used to track this
action after it's submitted. The action will be processed asynchronously when
this is defined."
- }
- }
- },
- "merge-indexes": {
- "type":"object",
- "documentation":
"https://solr.apache.org/guide/coreadmin-api.html#coreadmin-mergeindexes",
- "description":"Merges one or more indexes to another index. The indexes
must have completed commits, and should be locked against writes until the
merge is complete to avoid index corruption. The target core (which is the core
that should be used as the endpoint for this command) must exist before using
this command. A commit should also be performed on this core after the merge is
complete.",
- "properties": {
- "indexDir": {
- "type": "array",
- "description": "A comma-separated list index directories for each
source core that will be merged with the target core.",
- "items": {
- "type": "string"
- }
- },
- "srcCore": {
- "type": "array",
- "description": "A comma-separated list of the names of each source
core to be merged with the target core.",
- "items": {
- "type": "string"
- }
- },
- "async": {
- "type": "string",
- "description": "Defines a request ID that can be used to track this
action after it's submitted. The action will be processed asynchronously when
this is defined."
- }
- }
- },
- "split": { "#include": "cores.core.Commands.split"},
"request-recovery": {
"type":"object",
"documentation":
"https://solr.apache.org/guide/coreadmin-api.html#coreadmin-requestrecovery",
diff --git a/solr/solrj/src/resources/apispec/cores.core.Commands.split.json
b/solr/solrj/src/resources/apispec/cores.core.Commands.split.json
deleted file mode 100644
index e20a0e5..0000000
--- a/solr/solrj/src/resources/apispec/cores.core.Commands.split.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "documentation":
"https://solr.apache.org/guide/coreadmin-api.html#coreadmin-split",
- "description": "Allows splitting an index into two or more new indexes.",
- "type": "object",
- "properties": {
- "path": {
- "type": "array",
- "description": "Directory path(s) in which a piece of the index will be
written. This allows splitting the index before creating the cores to contain
them. Note if using this approach that the indexes will not be able to receive
updates until a new core has been created to handle the incoming updates. If
you have already created the new cores, you should define the targetCore
property instead.",
- "items": {
- "type": "string"
- }
- },
- "targetCore": {
- "type": "array",
- "description": "The target Solr core(s) to which a piece of the index
will be merged (if the target core already contains data). This requires that
the cores have already been created. If the cores have not yet been created,
use the path property instead.",
- "items": {
- "type": "string"
- }
- },
- "splitKey": {
- "type":"string",
- "description": "A route key to use for splitting the index. This
parameter is optional, but should not be defined if the ranges parameter is
also defined."
- },
- "ranges": {
- "type": "string",
- "description": "A comma-separated list of hexadecimal hash ranges that
will be used to split the core. This parameter is optional, but should not be
defined if the splitKey parameter is also defined."
- },
- "async": {
- "type": "string",
- "description": "Defines a request ID that can be used to track this
action after it's submitted. The action will be processed asynchronously when
this is defined. This command can be long-running, so running it asynchronously
is recommended."
- }
- }
-
-}
diff --git
a/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java
b/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java
index 10cc866..e4c280e 100644
--- a/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java
+++ b/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java
@@ -22,9 +22,6 @@ import org.apache.solr.SolrTestCaseJ4;
import java.util.List;
import java.util.Map;
-import static org.apache.solr.common.util.Utils.toJSONString;
-import static org.apache.solr.common.util.ValidatingJsonMap.NOT_NULL;
-
public class JsonValidatorTest extends SolrTestCaseJ4 {
public void testSchema() {
@@ -37,35 +34,13 @@ public class JsonValidatorTest extends SolrTestCaseJ4 {
public void testSchemaValidation() {
- // merge-indexes chosen to exercise string and array/list props.
- ValidatingJsonMap spec = Utils.getSpec("cores.core.Commands").getSpec();
- final Map<String, Object> mergeIndexesSchema = spec.getMap("commands",
NOT_NULL).getMap("merge-indexes", NOT_NULL);
- final JsonSchemaValidator mergeIndexesSchemaValidator = new
JsonSchemaValidator(mergeIndexesSchema);
-
- List<String> errs =
mergeIndexesSchemaValidator.validateJson(Utils.fromJSONString("{async : x,
indexDir: [ c1 , c2]}"));
- assertNull(toJSONString(errs), errs);
- errs =
mergeIndexesSchemaValidator.validateJson(Utils.fromJSONString("{async : x,
indexDir: [c1] }"));
- assertNull(toJSONString(errs), errs);
- errs =
mergeIndexesSchemaValidator.validateJson(Utils.fromJSONString("{async : x, x:y,
indexDir: [ c1 , c2]}"));
- assertNotNull(toJSONString(errs), errs);
- assertTrue(toJSONString(errs), errs.get(0).contains("Unknown"));
- errs =
mergeIndexesSchemaValidator.validateJson(Utils.fromJSONString("{async : 123,
indexDir: c1 }"));
- assertNotNull(toJSONString(errs), errs);
- assertTrue(toJSONString(errs), errs.get(0).contains("expected"));
- errs =
mergeIndexesSchemaValidator.validateJson(Utils.fromJSONString("{x:y, indexDir:
[ c1 , c2]}"));
- assertTrue(toJSONString(errs), StrUtils.join(errs,
'|').contains("Unknown"));
- errs =
mergeIndexesSchemaValidator.validateJson(Utils.fromJSONString("{async : x,
indexDir: [ 1 , 2]}"));
- assertFalse(toJSONString(errs), errs.isEmpty());
- assertTrue(toJSONString(errs), errs.get(0).contains("expected"));
-
-
final JsonSchemaValidator personSchemaValidator = new
JsonSchemaValidator("{" +
" type:object," +
" properties: {" +
" age : {type: number}," +
" adult : {type: boolean}," +
" name: {type: string}}}");
- errs = personSchemaValidator.validateJson(Utils.fromJSONString("{name:x,
age:21, adult:true}"));
+ List<String> errs =
personSchemaValidator.validateJson(Utils.fromJSONString("{name:x, age:21,
adult:true}"));
assertNull(errs);
errs = personSchemaValidator.validateJson(Utils.fromJSONString("{name:x,
age:'21', adult:'true'}"));
assertNotNull(errs);