3232import org .elasticsearch .common .io .stream .StreamInput ;
3333import org .elasticsearch .common .io .stream .StreamOutput ;
3434import org .elasticsearch .common .io .stream .Writeable ;
35+ import org .elasticsearch .common .logging .DeprecationLogger ;
36+ import org .elasticsearch .common .logging .Loggers ;
3537import org .elasticsearch .common .xcontent .LoggingDeprecationHandler ;
3638import org .elasticsearch .common .xcontent .NamedXContentRegistry ;
3739import org .elasticsearch .common .xcontent .ObjectParser ;
5759 */
5860public class StoredScriptSource extends AbstractDiffable <StoredScriptSource > implements Writeable , ToXContentObject {
5961
62+ /**
63+ * Standard deprecation logger for used to deprecate allowance of empty templates.
64+ */
65+ private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger (Loggers .getLogger (StoredScriptSource .class ));
66+
6067 /**
6168 * Standard {@link ParseField} for outer level of stored script source.
6269 */
@@ -109,7 +116,7 @@ private void setLang(String lang) {
109116 private void setSource (XContentParser parser ) {
110117 try {
111118 if (parser .currentToken () == Token .START_OBJECT ) {
112- //this is really for search templates, that need to be converted to json format
119+ // this is really for search templates, that need to be converted to json format
113120 XContentBuilder builder = XContentFactory .jsonBuilder ();
114121 source = Strings .toString (builder .copyCurrentStructure (parser ));
115122 options .put (Script .CONTENT_TYPE_OPTION , XContentType .JSON .mediaType ());
@@ -131,18 +138,38 @@ private void setOptions(Map<String, String> options) {
131138
132139 /**
133140 * Validates the parameters and creates an {@link StoredScriptSource}.
141+ *
142+ * @param ignoreEmpty Specify as {@code true} to ignoreEmpty the empty source check.
143+ * This allow empty templates to be loaded for backwards compatibility.
144+ * This allow empty templates to be loaded for backwards compatibility.
134145 */
135- private StoredScriptSource build () {
146+ private StoredScriptSource build (boolean ignoreEmpty ) {
136147 if (lang == null ) {
137148 throw new IllegalArgumentException ("must specify lang for stored script" );
138149 } else if (lang .isEmpty ()) {
139150 throw new IllegalArgumentException ("lang cannot be empty" );
140151 }
141152
142153 if (source == null ) {
143- throw new IllegalArgumentException ("must specify source for stored script" );
154+ if (ignoreEmpty || Script .DEFAULT_TEMPLATE_LANG .equals (lang )) {
155+ if (Script .DEFAULT_TEMPLATE_LANG .equals (lang )) {
156+ DEPRECATION_LOGGER .deprecated ("empty templates should no longer be used" );
157+ } else {
158+ DEPRECATION_LOGGER .deprecated ("empty scripts should no longer be used" );
159+ }
160+ } else {
161+ throw new IllegalArgumentException ("must specify source for stored script" );
162+ }
144163 } else if (source .isEmpty ()) {
145- throw new IllegalArgumentException ("source cannot be empty" );
164+ if (ignoreEmpty || Script .DEFAULT_TEMPLATE_LANG .equals (lang )) {
165+ if (Script .DEFAULT_TEMPLATE_LANG .equals (lang )) {
166+ DEPRECATION_LOGGER .deprecated ("empty templates should no longer be used" );
167+ } else {
168+ DEPRECATION_LOGGER .deprecated ("empty scripts should no longer be used" );
169+ }
170+ } else {
171+ throw new IllegalArgumentException ("source cannot be empty" );
172+ }
146173 }
147174
148175 if (options .size () > 1 || options .size () == 1 && options .get (Script .CONTENT_TYPE_OPTION ) == null ) {
@@ -257,6 +284,8 @@ public static StoredScriptSource parse(BytesReference content, XContentType xCon
257284 token = parser .nextToken ();
258285
259286 if (token == Token .END_OBJECT ) {
287+ DEPRECATION_LOGGER .deprecated ("empty templates should no longer be used" );
288+
260289 return new StoredScriptSource (Script .DEFAULT_TEMPLATE_LANG , "" , Collections .emptyMap ());
261290 }
262291
@@ -271,7 +300,7 @@ public static StoredScriptSource parse(BytesReference content, XContentType xCon
271300 token = parser .nextToken ();
272301
273302 if (token == Token .START_OBJECT ) {
274- return PARSER .apply (parser , null ).build ();
303+ return PARSER .apply (parser , null ).build (false );
275304 } else {
276305 throw new ParsingException (parser .getTokenLocation (), "unexpected token [" + token + "], expected [{, <source>]" );
277306 }
@@ -280,7 +309,13 @@ public static StoredScriptSource parse(BytesReference content, XContentType xCon
280309 token = parser .nextToken ();
281310
282311 if (token == Token .VALUE_STRING ) {
283- return new StoredScriptSource (Script .DEFAULT_TEMPLATE_LANG , parser .text (), Collections .emptyMap ());
312+ String source = parser .text ();
313+
314+ if (source == null || source .isEmpty ()) {
315+ DEPRECATION_LOGGER .deprecated ("empty templates should no longer be used" );
316+ }
317+
318+ return new StoredScriptSource (Script .DEFAULT_TEMPLATE_LANG , source , Collections .emptyMap ());
284319 }
285320 }
286321
@@ -293,7 +328,13 @@ public static StoredScriptSource parse(BytesReference content, XContentType xCon
293328 builder .copyCurrentStructure (parser );
294329 }
295330
296- return new StoredScriptSource (Script .DEFAULT_TEMPLATE_LANG , Strings .toString (builder ), Collections .emptyMap ());
331+ String source = Strings .toString (builder );
332+
333+ if (source == null || source .isEmpty ()) {
334+ DEPRECATION_LOGGER .deprecated ("empty templates should no longer be used" );
335+ }
336+
337+ return new StoredScriptSource (Script .DEFAULT_TEMPLATE_LANG , source , Collections .emptyMap ());
297338 }
298339 }
299340 } catch (IOException ioe ) {
@@ -320,9 +361,12 @@ public static StoredScriptSource parse(BytesReference content, XContentType xCon
320361 *
321362 * Note that the "source" parameter can also handle template parsing including from
322363 * a complex JSON object.
364+ *
365+ * @param ignoreEmpty Specify as {@code true} to ignoreEmpty the empty source check.
366+ * This allows empty templates to be loaded for backwards compatibility.
323367 */
324- public static StoredScriptSource fromXContent (XContentParser parser ) {
325- return PARSER .apply (parser , null ).build ();
368+ public static StoredScriptSource fromXContent (XContentParser parser , boolean ignoreEmpty ) {
369+ return PARSER .apply (parser , null ).build (ignoreEmpty );
326370 }
327371
328372 /**
0 commit comments