This is an automated email from the ASF dual-hosted git repository. zjffdu pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push: new 8d86e65 [ZEPPELIN-5115]. Unable to register repository with authentication info 8d86e65 is described below commit 8d86e65f67c535363531e71cc273fbfac1d88f38 Author: Jeff Zhang <zjf...@apache.org> AuthorDate: Thu Oct 29 17:13:56 2020 +0800 [ZEPPELIN-5115]. Unable to register repository with authentication info ### What is this PR for? The root cause is `Authentication` in `RemoteRepository` is interface. This PR fix the issue by creating `InterfaceAdapter` which works all interface types. ### What type of PR is it? [Bug Fix] ### Todos * [ ] - Task ### What is the Jira issue? * https://issues.apache.org/jira/browse/ZEPPELIN-5115 ### How should this be tested? * Manually tested https://travis-ci.org/github/zjffdu/zeppelin/builds/739862453 ### Screenshots (if appropriate) ### Questions: * Does the licenses files need update? No * Is there breaking changes for older versions? No * Does this needs documentation? No Author: Jeff Zhang <zjf...@apache.org> Closes #3959 from zjffdu/ZEPPELIN-5115 and squashes the following commits: 7ee6b1245 [Jeff Zhang] [ZEPPELIN-5115]. Unable to register repository with authentication info --- .../interpreter/InterpreterInfoSaving.java | 53 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java index 04da876..80051d0 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java @@ -19,10 +19,17 @@ package org.apache.zeppelin.interpreter; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.JsonParser; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; import org.apache.commons.io.IOUtils; import org.apache.zeppelin.common.JsonSerializable; +import org.eclipse.aether.repository.Authentication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.eclipse.aether.repository.RemoteRepository; @@ -30,6 +37,7 @@ import org.eclipse.aether.repository.RemoteRepository; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -45,7 +53,11 @@ import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; public class InterpreterInfoSaving implements JsonSerializable { private static final Logger LOGGER = LoggerFactory.getLogger(InterpreterInfoSaving.class); - private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + // Authentication is an interface so that we need to create an InterfaceAdapter for that. + private static final Gson GSON = new GsonBuilder().setPrettyPrinting() + .registerTypeAdapter(Authentication.class, new InterfaceAdapter<Authentication>()) + .create(); public Map<String, InterpreterSetting> interpreterSettings = new HashMap<>(); public List<RemoteRepository> interpreterRepositories = new ArrayList<>(); @@ -61,8 +73,8 @@ public class InterpreterInfoSaving implements JsonSerializable { if (infoSaving != null && infoSaving.interpreterSettings != null) { for (InterpreterSetting interpreterSetting : infoSaving.interpreterSettings.values()) { interpreterSetting.convertPermissionsFromUsersToOwners( - jsonObject.getAsJsonObject("interpreterSettings") - .getAsJsonObject(interpreterSetting.getId())); + jsonObject.getAsJsonObject("interpreterSettings") + .getAsJsonObject(interpreterSetting.getId())); } } } @@ -92,4 +104,39 @@ public class InterpreterInfoSaving implements JsonSerializable { public static InterpreterInfoSaving fromJson(String json) { return GSON.fromJson(json, InterpreterInfoSaving.class); } + + static class InterfaceAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> { + public JsonElement serialize(T object, Type interfaceType, JsonSerializationContext context) { + final JsonObject wrapper = new JsonObject(); + wrapper.addProperty("type", object.getClass().getName()); + wrapper.add("data", context.serialize(object)); + return wrapper; + } + + public T deserialize(JsonElement elem, + Type interfaceType, + JsonDeserializationContext context) throws JsonParseException { + final JsonObject wrapper = (JsonObject) elem; + final JsonElement typeName = get(wrapper, "type"); + final JsonElement data = get(wrapper, "data"); + final Type actualType = typeForName(typeName); + return context.deserialize(data, actualType); + } + + private Type typeForName(final JsonElement typeElem) { + try { + return Class.forName(typeElem.getAsString()); + } catch (ClassNotFoundException e) { + throw new JsonParseException(e); + } + } + + private JsonElement get(final JsonObject wrapper, String memberName) { + final JsonElement elem = wrapper.get(memberName); + if (elem == null) + throw new JsonParseException("no '" + memberName + + "' member found in what was expected to be an interface wrapper"); + return elem; + } + } }