You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2019/10/11 13:38:27 UTC
[lucene-solr] 02/02: SOLR-13787: Support for Payload as 3rd param
This is an automated email from the ASF dual-hosted git repository.
noble pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
commit 71e9564e0d520449b6eeb52a6f67ede91ff091a7
Author: noble <no...@apache.org>
AuthorDate: Sat Oct 12 00:38:06 2019 +1100
SOLR-13787: Support for Payload<T> as 3rd param
---
.../src/java/org/apache/solr/api/AnnotatedApi.java | 59 +++++++++++++++++-----
.../core/src/java/org/apache/solr/api/Command.java | 2 -
.../solr/api/{Command.java => PayloadObj.java} | 26 +++++-----
.../org/apache/solr/util/ReflectMapWriter.java | 58 +++++++++++++++++++++
.../solr/handler/admin/TestApiFramework.java | 4 +-
5 files changed, 116 insertions(+), 33 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java b/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java
index b1be461..964af85 100644
--- a/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java
+++ b/solr/core/src/java/org/apache/solr/api/AnnotatedApi.java
@@ -45,14 +45,14 @@ import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.security.AuthorizationContext;
import org.apache.solr.security.PermissionNameProvider;
-/**This class implements an Api just from an annotated java class
+/**
+ * This class implements an Api just from an annotated java class
* The class must have an annotation {@link EndPoint}
* Each method must have an annotation {@link Command}
* The methods that implement a command should have the first 2 parameters
* {@link SolrQueryRequest} and {@link SolrQueryResponse} or it may optionally
* have a third parameter which could be a java class annotated with jackson annotations.
* The third parameter is only valid if it is using a json command payload
- *
*/
public class AnnotatedApi extends Api implements PermissionNameProvider {
@@ -62,7 +62,6 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
public AnnotatedApi(Object obj) {
this(obj, null);
-
}
public AnnotatedApi(Object obj, Api fallback) {
@@ -94,21 +93,21 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
private static SpecProvider readSpec(Class klas) {
EndPoint endPoint = (EndPoint) klas.getAnnotation(EndPoint.class);
- if (endPoint == null) throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Invalid class : "+ klas.getName());
- EndPoint endPoint1 = (EndPoint) klas.getAnnotation(EndPoint.class);
+ if (endPoint == null)
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Invalid class : " + klas.getName());
return () -> {
Map map = new LinkedHashMap();
List<String> methods = new ArrayList<>();
- for (SolrRequest.METHOD method : endPoint1.method()) {
+ for (SolrRequest.METHOD method : endPoint.method()) {
methods.add(method.name());
}
map.put("methods", methods);
- map.put("url", new ValidatingJsonMap(Collections.singletonMap("paths", Arrays.asList(endPoint1.path()))));
+ map.put("url", new ValidatingJsonMap(Collections.singletonMap("paths", Arrays.asList(endPoint.path()))));
Map<String, Object> cmds = new HashMap<>();
for (Method method : klas.getMethods()) {
Command command = method.getAnnotation(Command.class);
- if (command != null && !command.name().isBlank()) {
+ if (command != null && !command.name().isEmpty()) {
cmds.put(command.name(), AnnotatedApi.createSchema(method));
}
}
@@ -132,7 +131,7 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
}
}
- List<CommandOperation> cmds = req.getCommands(true);
+ List<CommandOperation> cmds = req.getCommands(false);
boolean allExists = true;
for (CommandOperation cmd : cmds) {
if (!commands.containsKey(cmd.name)) {
@@ -168,6 +167,7 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
ObjectMapper mapper = new ObjectMapper();
int paramsCount;
Class c;
+ boolean isWrappedInPayloadObj = false;
Cmd(Command command, Object obj, Method method) {
@@ -181,7 +181,23 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
throw new RuntimeException("Invalid params for method " + method);
}
if (parameterTypes.length == 3) {
- c = parameterTypes[2];
+ Type t = method.getGenericParameterTypes()[2];
+ if (t instanceof ParameterizedType) {
+ ParameterizedType typ = (ParameterizedType) t;
+ if (typ.getRawType() == PayloadObj.class) {
+ isWrappedInPayloadObj = true;
+ Type t1 = typ.getActualTypeArguments()[0];
+ if (t1 instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) t1;
+ c = (Class) parameterizedType.getRawType();
+ } else {
+ c = (Class) typ.getActualTypeArguments()[0];
+ }
+ }
+ } else {
+ c = (Class) t;
+ }
+
}
if (parameterTypes.length > 3) {
throw new RuntimeException("Invalid params count for method " + method);
@@ -195,7 +211,6 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
void invoke(SolrQueryRequest req, SolrQueryResponse rsp, CommandOperation cmd) {
try {
-
if (paramsCount == 2) {
method.invoke(obj, req, rsp);
} else {
@@ -203,14 +218,26 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
if (o instanceof Map && c != null) {
o = mapper.readValue(Utils.toJSONString(o), c);
}
- method.invoke(obj, req, rsp, o);
+ if (isWrappedInPayloadObj) {
+ PayloadObj<Object> payloadObj = new PayloadObj<>(cmd.name, cmd.getCommandData(), o);
+ cmd = payloadObj;
+ method.invoke(obj, req, rsp, payloadObj);
+ } else {
+ method.invoke(obj, req, rsp, o);
+ }
+ if (cmd.hasError()) {
+ throw new ApiBag.ExceptionWithErrObject(SolrException.ErrorCode.BAD_REQUEST, "Error executing command",
+ CommandOperation.captureErrors(Collections.singletonList(cmd)));
+ }
}
+
} catch (SolrException se) {
throw se;
} catch (InvocationTargetException ite) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, ite.getCause());
} catch (Exception e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
}
}
@@ -243,11 +270,15 @@ public class AnnotatedApi extends Api implements PermissionNameProvider {
private static Map<String, Object> createSchemaFromType(Type t) {
Map<String, Object> map = new LinkedHashMap<>();
+ if (t instanceof ParameterizedType) {
+ ParameterizedType typ = (ParameterizedType) t;
+ if (typ.getRawType() == PayloadObj.class) {
+ t = typ.getActualTypeArguments()[0];
+ }
+ }
if (primitives.containsKey(t)) {
map.put("type", primitives.get(t));
- } else if (t == List.class) {
-
} else if (t instanceof ParameterizedType && ((ParameterizedType) t).getRawType() == List.class) {
Type typ = ((ParameterizedType) t).getActualTypeArguments()[0];
map.put("type", "array");
diff --git a/solr/core/src/java/org/apache/solr/api/Command.java b/solr/core/src/java/org/apache/solr/api/Command.java
index d18d064..25de077 100644
--- a/solr/core/src/java/org/apache/solr/api/Command.java
+++ b/solr/core/src/java/org/apache/solr/api/Command.java
@@ -32,6 +32,4 @@ public @interface Command {
*/
String name() default "";
- String jsonSchema() default "";
-
}
diff --git a/solr/core/src/java/org/apache/solr/api/Command.java b/solr/core/src/java/org/apache/solr/api/PayloadObj.java
similarity index 64%
copy from solr/core/src/java/org/apache/solr/api/Command.java
copy to solr/core/src/java/org/apache/solr/api/PayloadObj.java
index d18d064..c09c442 100644
--- a/solr/core/src/java/org/apache/solr/api/Command.java
+++ b/solr/core/src/java/org/apache/solr/api/PayloadObj.java
@@ -17,21 +17,19 @@
package org.apache.solr.api;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import org.apache.solr.common.util.CommandOperation;
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface Command {
- /**if this is not a json command , leave it empty.
- * Keep in mind that you cannot have duplicates.
- * Only one method per name
- *
- */
- String name() default "";
+public class PayloadObj<T> extends CommandOperation {
- String jsonSchema() default "";
+ private T obj;
+
+ public PayloadObj(String operationName, Object metaData, T obj) {
+ super(operationName, metaData);
+ this.obj = obj;
+ }
+
+ public T get(){
+ return obj;
+ }
}
diff --git a/solr/core/src/java/org/apache/solr/util/ReflectMapWriter.java b/solr/core/src/java/org/apache/solr/util/ReflectMapWriter.java
new file mode 100644
index 0000000..9555740
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/ReflectMapWriter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.solr.common.MapWriter;
+
+public interface ReflectMapWriter extends MapWriter {
+
+ @Override
+ default void writeMap(EntryWriter ew) throws IOException {
+ for (Field field : this.getClass().getDeclaredFields()) {
+ JsonProperty prop = field.getAnnotation(JsonProperty.class);
+ if (prop == null) continue;
+ int modifiers = field.getModifiers();
+ if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
+ String fname = prop.value().isEmpty() ? field.getName() : prop.value();
+ try {
+ if (field.getType() == int.class) {
+ ew.put(fname, field.getInt(this));
+ } else if (field.getType() == float.class) {
+ ew.put(fname, field.getFloat(this));
+ } else if (field.getType() == double.class) {
+ ew.put(fname, field.getDouble(this));
+ } else if (field.getType() == boolean.class) {
+ ew.put(fname, field.getBoolean(this));
+ } else if (field.getType() == long.class) {
+ ew.put(fname, field.getLong(this));
+ } else {
+ ew.putIfNotNull(fname, field.get(this));
+ }
+ } catch (IllegalAccessException e) {
+ //it should not happen
+ }
+ }
+ }
+ }
+
+}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java b/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java
index 933b862..fde0335 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/TestApiFramework.java
@@ -168,7 +168,7 @@ public class TestApiFramework extends SolrTestCaseJ4 {
}
- public void testPayload() throws IOException {
+ public void testPayload() {
String json = "{package:pkg1, version: '0.1', files :[a.jar, b.jar]}";
Utils.fromJSONString(json);
@@ -213,8 +213,6 @@ public class TestApiFramework extends SolrTestCaseJ4 {
}
-
-
}
public static class AddVersion {