@@ -78,11 +78,11 @@ static ObjectNode rebuildObjectNode(final DataSource source) throws IOException
7878 final JsonNode jsonNode = SIMPLE_MAPPER .readTree (jsonString .get ());
7979
8080 if (jsonNode == null ) {
81- throw new NullPointerException ("DataSource#toJson() returned null." );
81+ throw new NullPointerException ("DataSource(Impl) #toJson() returned null." );
8282 }
8383 if (!jsonNode .isObject ()) {
8484 throw new ClassCastException (
85- "DataSource#toJson() returned not a JSON object: " + jsonNode .getClass ().getCanonicalName ());
85+ "DataSource(Impl) #toJson() returned not a JSON object: " + jsonNode .getClass ().getCanonicalName ());
8686 }
8787 return (ObjectNode ) jsonNode ;
8888 }
@@ -95,7 +95,7 @@ static ObjectNode rebuildObjectNode(final DataSource source) throws IOException
9595 }
9696
9797 private static Optional <String > callToJsonIfAvailable (final DataSource source ) {
98- final Method toJson = getToJsonMethod ();
98+ final Method toJson = getToJsonMethod (source );
9999 if (toJson == null ) {
100100 return Optional .empty ();
101101 }
@@ -111,19 +111,19 @@ private static Optional<String> callToJsonIfAvailable(final DataSource source) {
111111 if (targetException instanceof Error ) {
112112 throw (Error ) targetException ;
113113 }
114- throw new IllegalStateException ("DataSource#toJson() threw unexpected Exception." , targetException );
114+ throw new IllegalStateException ("DataSource(Impl) #toJson() threw unexpected Exception." , targetException );
115115 } catch (final IllegalAccessException ex ) {
116- logger .debug ("DataSource#toJson is not accessible unexpectedly. DataSource: {}, toJson: {}, " ,
116+ logger .debug ("DataSource(Impl) #toJson is not accessible unexpectedly. DataSource: {}, toJson: {}, " ,
117117 source .getClass (), toJson );
118- throw new IllegalStateException ("DataSource#toJson() is not accessible." , ex );
118+ throw new IllegalStateException ("DataSource(Impl) #toJson() is not accessible." , ex );
119119 }
120120
121121 if (jsonStringObject == null ) {
122- throw new NullPointerException ("org.embulk.config. DataSource#toJson() returned null." );
122+ throw new NullPointerException ("DataSource(Impl) #toJson() returned null." );
123123 }
124124 if (!(jsonStringObject instanceof String )) {
125125 throw new ClassCastException (
126- "org.embulk.config. DataSource#toJson() returned not a String: "
126+ "DataSource(Impl) #toJson() returned not a String: "
127127 + jsonStringObject .getClass ().getCanonicalName ());
128128 }
129129
@@ -163,7 +163,7 @@ private static ObjectNode callGetObjectNodeAndRebuildIfAvailable(final DataSourc
163163 return ObjectNodeRebuilder .rebuild (coreObjectNode , mapper );
164164 }
165165
166- private static Method getToJsonMethod () {
166+ private static Method getToJsonMethod (final DataSource source ) {
167167 try {
168168 // Getting the "toJson" method from embulk-api's public interface "org.embulk.config.DataSource", not from an implementation class,
169169 // for example "org.embulk.(util.)config.DataSourceImpl", so that invoking the method does not throw IllegalAccessException.
@@ -178,7 +178,27 @@ private static Method getToJsonMethod() {
178178 // A method instance retrieved from the public interface "org.embulk.config.DataSource" would solve the problem.
179179 return DataSource .class .getMethod ("toJson" );
180180 } catch (final NoSuchMethodException ex ) {
181- // Expected: toJson is not defined in Embulk v0.10.2 or earlier.
181+ // Expected: toJson is not defined in "org.embulk.config.DataSource" when a user is running
182+ // Embulk v0.10.2 or earlier.
183+ //
184+ // Even in the case, the received DataSource instance can still be of embulk-util-config's
185+ // "org.embulk.util.config.DataSourceImpl" from another plugin (ex. input <=> parser), or
186+ // from itself. As "org.embulk.util.config.DataSourceImpl" does not have "getObjectNode",
187+ // it must still be rebuilt with "toJson" retrieved in some way.
188+ //
189+ // Pass-through to the next trial to retrieve the "toJson" method, then.
190+ }
191+
192+ final Class <? extends DataSource > dataSourceImplClass = source .getClass ();
193+ try {
194+ // Getting the "toJson" method from the implementation class embulk-core's "org.embulk.config.DataSourceImpl",
195+ // or embulk-util-config's "org.embulk.util.config.DataSourceImpl".
196+ return dataSourceImplClass .getMethod ("toJson" );
197+ } catch (final NoSuchMethodException ex ) {
198+ // Still expected: toJson is not defined in embulk-core's "org.embulk.config.DataSourceImpl"
199+ // in Embulk v0.10.2 or earlier.
200+ //
201+ // Returning null in this case so that it fallbacks to call the "getObjectNode" method instead.
182202 return null ;
183203 }
184204 }
0 commit comments