From 12ad41775a3e3e3096843175d0aecc06ba25be18 Mon Sep 17 00:00:00 2001 From: Dai MIKURUBE Date: Wed, 3 Feb 2021 17:24:23 +0900 Subject: [PATCH] Find toJson method even from DataSourceImpl against Embulk v0.10.2 or earlier, whose DataSource interace does not have "toJson" --- .../java/org/embulk/util/config/Compat.java | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/embulk/util/config/Compat.java b/src/main/java/org/embulk/util/config/Compat.java index 474b12f..8ff4521 100644 --- a/src/main/java/org/embulk/util/config/Compat.java +++ b/src/main/java/org/embulk/util/config/Compat.java @@ -78,11 +78,11 @@ static ObjectNode rebuildObjectNode(final DataSource source) throws IOException final JsonNode jsonNode = SIMPLE_MAPPER.readTree(jsonString.get()); if (jsonNode == null) { - throw new NullPointerException("DataSource#toJson() returned null."); + throw new NullPointerException("DataSource(Impl)#toJson() returned null."); } if (!jsonNode.isObject()) { throw new ClassCastException( - "DataSource#toJson() returned not a JSON object: " + jsonNode.getClass().getCanonicalName()); + "DataSource(Impl)#toJson() returned not a JSON object: " + jsonNode.getClass().getCanonicalName()); } return (ObjectNode) jsonNode; } @@ -95,7 +95,7 @@ static ObjectNode rebuildObjectNode(final DataSource source) throws IOException } private static Optional callToJsonIfAvailable(final DataSource source) { - final Method toJson = getToJsonMethod(); + final Method toJson = getToJsonMethod(source); if (toJson == null) { return Optional.empty(); } @@ -111,19 +111,19 @@ private static Optional callToJsonIfAvailable(final DataSource source) { if (targetException instanceof Error) { throw (Error) targetException; } - throw new IllegalStateException("DataSource#toJson() threw unexpected Exception.", targetException); + throw new IllegalStateException("DataSource(Impl)#toJson() threw unexpected Exception.", targetException); } catch (final IllegalAccessException ex) { - logger.debug("DataSource#toJson is not accessible unexpectedly. DataSource: {}, toJson: {}, ", + logger.debug("DataSource(Impl)#toJson is not accessible unexpectedly. DataSource: {}, toJson: {}, ", source.getClass(), toJson); - throw new IllegalStateException("DataSource#toJson() is not accessible.", ex); + throw new IllegalStateException("DataSource(Impl)#toJson() is not accessible.", ex); } if (jsonStringObject == null) { - throw new NullPointerException("org.embulk.config.DataSource#toJson() returned null."); + throw new NullPointerException("DataSource(Impl)#toJson() returned null."); } if (!(jsonStringObject instanceof String)) { throw new ClassCastException( - "org.embulk.config.DataSource#toJson() returned not a String: " + "DataSource(Impl)#toJson() returned not a String: " + jsonStringObject.getClass().getCanonicalName()); } @@ -163,7 +163,7 @@ private static ObjectNode callGetObjectNodeAndRebuildIfAvailable(final DataSourc return ObjectNodeRebuilder.rebuild(coreObjectNode, mapper); } - private static Method getToJsonMethod() { + private static Method getToJsonMethod(final DataSource source) { try { // Getting the "toJson" method from embulk-api's public interface "org.embulk.config.DataSource", not from an implementation class, // for example "org.embulk.(util.)config.DataSourceImpl", so that invoking the method does not throw IllegalAccessException. @@ -178,7 +178,27 @@ private static Method getToJsonMethod() { // A method instance retrieved from the public interface "org.embulk.config.DataSource" would solve the problem. return DataSource.class.getMethod("toJson"); } catch (final NoSuchMethodException ex) { - // Expected: toJson is not defined in Embulk v0.10.2 or earlier. + // Expected: toJson is not defined in "org.embulk.config.DataSource" when a user is running + // Embulk v0.10.2 or earlier. + // + // Even in the case, the received DataSource instance can still be of embulk-util-config's + // "org.embulk.util.config.DataSourceImpl" from another plugin (ex. input <=> parser), or + // from itself. As "org.embulk.util.config.DataSourceImpl" does not have "getObjectNode", + // it must still be rebuilt with "toJson" retrieved in some way. + // + // Pass-through to the next trial to retrieve the "toJson" method, then. + } + + final Class dataSourceImplClass = source.getClass(); + try { + // Getting the "toJson" method from the implementation class embulk-core's "org.embulk.config.DataSourceImpl", + // or embulk-util-config's "org.embulk.util.config.DataSourceImpl". + return dataSourceImplClass.getMethod("toJson"); + } catch (final NoSuchMethodException ex) { + // Still expected: toJson is not defined in embulk-core's "org.embulk.config.DataSourceImpl" + // in Embulk v0.10.2 or earlier. + // + // Returning null in this case so that it fallbacks to call the "getObjectNode" method instead. return null; } }