mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-24 17:09:48 +00:00
Add a Painless Context REST API (#39382)
This PR adds an internal REST API for querying context information about Painless whitelists. Commands include the following: GET /_scripts/painless/_context -- retrieves a list of contexts GET /_scripts/painless/_context?context=%name% retrieves all available information about the API for this specific context
This commit is contained in:
parent
ae0ff05c90
commit
b57af6c401
@ -713,6 +713,7 @@ public class RestHighLevelClientTests extends ESTestCase {
|
||||
"nodes.hot_threads",
|
||||
"nodes.usage",
|
||||
"nodes.reload_secure_settings",
|
||||
"scripts_painless_context",
|
||||
"search_shards",
|
||||
};
|
||||
List<String> booleanReturnMethods = Arrays.asList(
|
||||
|
@ -20,15 +20,18 @@
|
||||
package org.elasticsearch.painless;
|
||||
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.IndexScopedSettings;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsFilter;
|
||||
import org.elasticsearch.painless.action.PainlessContextAction;
|
||||
import org.elasticsearch.painless.spi.PainlessExtension;
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
import org.elasticsearch.painless.spi.WhitelistLoader;
|
||||
@ -81,6 +84,8 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens
|
||||
whitelists = map;
|
||||
}
|
||||
|
||||
private final SetOnce<PainlessScriptEngine> painlessScriptEngine = new SetOnce<>();
|
||||
|
||||
@Override
|
||||
public ScriptEngine getScriptEngine(Settings settings, Collection<ScriptContext<?>> contexts) {
|
||||
Map<ScriptContext<?>, List<Whitelist>> contextsWithWhitelists = new HashMap<>();
|
||||
@ -92,7 +97,13 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens
|
||||
}
|
||||
contextsWithWhitelists.put(context, contextWhitelists);
|
||||
}
|
||||
return new PainlessScriptEngine(settings, contextsWithWhitelists);
|
||||
painlessScriptEngine.set(new PainlessScriptEngine(settings, contextsWithWhitelists));
|
||||
return painlessScriptEngine.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.singleton(b -> b.bind(PainlessScriptEngine.class).toInstance(painlessScriptEngine.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,9 +129,10 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens
|
||||
|
||||
@Override
|
||||
public List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions() {
|
||||
return Collections.singletonList(
|
||||
new ActionHandler<>(PainlessExecuteAction.INSTANCE, PainlessExecuteAction.TransportAction.class)
|
||||
);
|
||||
List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> actions = new ArrayList<>();
|
||||
actions.add(new ActionHandler<>(PainlessExecuteAction.INSTANCE, PainlessExecuteAction.TransportAction.class));
|
||||
actions.add(new ActionHandler<>(PainlessContextAction.INSTANCE, PainlessContextAction.TransportAction.class));
|
||||
return actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -128,6 +140,9 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens
|
||||
IndexScopedSettings indexScopedSettings, SettingsFilter settingsFilter,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
Supplier<DiscoveryNodes> nodesInCluster) {
|
||||
return Collections.singletonList(new PainlessExecuteAction.RestAction(settings, restController));
|
||||
List<RestHandler> handlers = new ArrayList<>();
|
||||
handlers.add(new PainlessExecuteAction.RestAction(settings, restController));
|
||||
handlers.add(new PainlessContextAction.RestAction(settings, restController));
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ package org.elasticsearch.painless;
|
||||
import org.elasticsearch.SpecialPermission;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.painless.Compiler.Loader;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupBuilder;
|
||||
import org.elasticsearch.painless.spi.Whitelist;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
@ -82,6 +83,7 @@ public final class PainlessScriptEngine implements ScriptEngine {
|
||||
private final CompilerSettings defaultCompilerSettings = new CompilerSettings();
|
||||
|
||||
private final Map<ScriptContext<?>, Compiler> contextsToCompilers;
|
||||
private final Map<ScriptContext<?>, PainlessLookup> contextsToLookups;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -91,14 +93,22 @@ public final class PainlessScriptEngine implements ScriptEngine {
|
||||
defaultCompilerSettings.setRegexesEnabled(CompilerSettings.REGEX_ENABLED.get(settings));
|
||||
|
||||
Map<ScriptContext<?>, Compiler> contextsToCompilers = new HashMap<>();
|
||||
Map<ScriptContext<?>, PainlessLookup> contextsToLookups = new HashMap<>();
|
||||
|
||||
for (Map.Entry<ScriptContext<?>, List<Whitelist>> entry : contexts.entrySet()) {
|
||||
ScriptContext<?> context = entry.getKey();
|
||||
contextsToCompilers.put(context, new Compiler(context.instanceClazz, context.factoryClazz, context.statefulFactoryClazz,
|
||||
PainlessLookupBuilder.buildFromWhitelists(entry.getValue())));
|
||||
PainlessLookup lookup = PainlessLookupBuilder.buildFromWhitelists(entry.getValue());
|
||||
contextsToCompilers.put(context,
|
||||
new Compiler(context.instanceClazz, context.factoryClazz, context.statefulFactoryClazz, lookup));
|
||||
contextsToLookups.put(context, lookup);
|
||||
}
|
||||
|
||||
this.contextsToCompilers = Collections.unmodifiableMap(contextsToCompilers);
|
||||
this.contextsToLookups = Collections.unmodifiableMap(contextsToLookups);
|
||||
}
|
||||
|
||||
public Map<ScriptContext<?>, PainlessLookup> getContextsToLookups() {
|
||||
return contextsToLookups;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.HandledTransportAction;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.painless.PainlessScriptEngine;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.action.RestToXContentListener;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.tasks.Task;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||
|
||||
/**
|
||||
* Internal REST API for querying context information about Painless whitelists.
|
||||
* Commands include the following:
|
||||
* <ul>
|
||||
* <li> GET /_scripts/painless/_context -- retrieves a list of contexts </li>
|
||||
* <li> GET /_scripts/painless/_context?context=%name% --
|
||||
* retrieves all available information about the API for this specific context</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class PainlessContextAction extends Action<PainlessContextAction.Response> {
|
||||
|
||||
public static final PainlessContextAction INSTANCE = new PainlessContextAction();
|
||||
private static final String NAME = "cluster:admin/scripts/painless/context";
|
||||
|
||||
private static final String SCRIPT_CONTEXT_NAME_PARAM = "context";
|
||||
|
||||
private PainlessContextAction() {
|
||||
super(NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response newResponse() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writeable.Reader<Response> getResponseReader() {
|
||||
return Response::new;
|
||||
}
|
||||
|
||||
public static class Request extends ActionRequest {
|
||||
|
||||
private String scriptContextName;
|
||||
|
||||
public Request() {
|
||||
scriptContextName = null;
|
||||
}
|
||||
|
||||
public Request(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
scriptContextName = in.readString();
|
||||
}
|
||||
|
||||
public void setScriptContextName(String scriptContextName) {
|
||||
this.scriptContextName = scriptContextName;
|
||||
}
|
||||
|
||||
public String getScriptContextName() {
|
||||
return scriptContextName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionRequestValidationException validate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeString(scriptContextName);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends ActionResponse implements ToXContentObject {
|
||||
|
||||
public static final ParseField CONTEXTS = new ParseField("contexts");
|
||||
|
||||
private final List<String> scriptContextNames;
|
||||
private final PainlessContextInfo painlessContextInfo;
|
||||
|
||||
public Response(List<String> scriptContextNames, PainlessContextInfo painlessContextInfo) {
|
||||
Objects.requireNonNull(scriptContextNames);
|
||||
scriptContextNames = new ArrayList<>(scriptContextNames);
|
||||
scriptContextNames.sort(String::compareTo);
|
||||
this.scriptContextNames = Collections.unmodifiableList(scriptContextNames);
|
||||
this.painlessContextInfo = painlessContextInfo;
|
||||
}
|
||||
|
||||
public Response(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
scriptContextNames = in.readStringList();
|
||||
painlessContextInfo = in.readOptionalWriteable(PainlessContextInfo::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeStringCollection(scriptContextNames);
|
||||
out.writeOptionalWriteable(painlessContextInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (painlessContextInfo == null) {
|
||||
builder.startObject();
|
||||
builder.field(CONTEXTS.getPreferredName(), scriptContextNames);
|
||||
builder.endObject();
|
||||
} else {
|
||||
painlessContextInfo.toXContent(builder, params);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TransportAction extends HandledTransportAction<Request, Response> {
|
||||
|
||||
private final PainlessScriptEngine painlessScriptEngine;
|
||||
|
||||
@Inject
|
||||
public TransportAction(TransportService transportService, ActionFilters actionFilters, PainlessScriptEngine painlessScriptEngine) {
|
||||
super(NAME, transportService, actionFilters, (Writeable.Reader<Request>)Request::new);
|
||||
this.painlessScriptEngine = painlessScriptEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doExecute(Task task, Request request, ActionListener<Response> listener) {
|
||||
List<String> scriptContextNames;
|
||||
PainlessContextInfo painlessContextInfo;
|
||||
|
||||
if (request.scriptContextName == null) {
|
||||
scriptContextNames =
|
||||
painlessScriptEngine.getContextsToLookups().keySet().stream().map(v -> v.name).collect(Collectors.toList());
|
||||
painlessContextInfo = null;
|
||||
} else {
|
||||
ScriptContext<?> scriptContext = null;
|
||||
PainlessLookup painlessLookup = null;
|
||||
|
||||
for (Map.Entry<ScriptContext<?>, PainlessLookup> contextLookupEntry :
|
||||
painlessScriptEngine.getContextsToLookups().entrySet()) {
|
||||
if (contextLookupEntry.getKey().name.equals(request.getScriptContextName())) {
|
||||
scriptContext = contextLookupEntry.getKey();
|
||||
painlessLookup = contextLookupEntry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (scriptContext == null || painlessLookup == null) {
|
||||
throw new IllegalArgumentException("script context [" + request.getScriptContextName() + "] not found");
|
||||
}
|
||||
|
||||
scriptContextNames = Collections.emptyList();
|
||||
painlessContextInfo = new PainlessContextInfo(scriptContext, painlessLookup);
|
||||
}
|
||||
|
||||
listener.onResponse(new Response(scriptContextNames, painlessContextInfo));
|
||||
}
|
||||
}
|
||||
|
||||
public static class RestAction extends BaseRestHandler {
|
||||
|
||||
public RestAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(GET, "/_scripts/painless/_context", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "_scripts_painless_context";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {
|
||||
Request request = new Request();
|
||||
request.setScriptContextName(restRequest.param(SCRIPT_CONTEXT_NAME_PARAM));
|
||||
return channel -> client.executeLocally(INSTANCE, request, new RestToXContentListener<>(channel));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.painless.lookup.PainlessClassBinding;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PainlessContextClassBindingInfo implements Writeable, ToXContentObject {
|
||||
|
||||
public static final ParseField DECLARING = new ParseField("declaring");
|
||||
public static final ParseField NAME = new ParseField("name");
|
||||
public static final ParseField RTN = new ParseField("return");
|
||||
public static final ParseField READ_ONLY = new ParseField("read_only");
|
||||
public static final ParseField PARAMETERS = new ParseField("parameters");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<PainlessContextClassBindingInfo, Void> PARSER = new ConstructingObjectParser<>(
|
||||
PainlessContextClassBindingInfo.class.getCanonicalName(),
|
||||
(v) ->
|
||||
new PainlessContextClassBindingInfo(
|
||||
(String)v[0],
|
||||
(String)v[1],
|
||||
(String)v[2],
|
||||
(int)v[3],
|
||||
(List<String>)v[4]
|
||||
)
|
||||
);
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), DECLARING);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), RTN);
|
||||
PARSER.declareInt(ConstructingObjectParser.constructorArg(), READ_ONLY);
|
||||
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), PARAMETERS);
|
||||
}
|
||||
|
||||
private final String declaring;
|
||||
private final String name;
|
||||
private final String rtn;
|
||||
private final int readOnly;
|
||||
private final List<String> parameters;
|
||||
|
||||
public PainlessContextClassBindingInfo(PainlessClassBinding painlessClassBinding) {
|
||||
this(
|
||||
painlessClassBinding.javaMethod.getDeclaringClass().getName(),
|
||||
painlessClassBinding.javaMethod.getName(),
|
||||
painlessClassBinding.returnType.getName(),
|
||||
painlessClassBinding.javaConstructor.getParameterCount(),
|
||||
painlessClassBinding.typeParameters.stream().map(Class::getName).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public PainlessContextClassBindingInfo(String declaring, String name, String rtn, int readOnly, List<String> parameters) {
|
||||
this.declaring = Objects.requireNonNull(declaring);
|
||||
this.name = Objects.requireNonNull(name);
|
||||
this.rtn = Objects.requireNonNull(rtn);
|
||||
this.readOnly = readOnly;
|
||||
this.parameters = Collections.unmodifiableList(Objects.requireNonNull(parameters));
|
||||
}
|
||||
|
||||
public PainlessContextClassBindingInfo(StreamInput in) throws IOException {
|
||||
declaring = in.readString();
|
||||
name = in.readString();
|
||||
rtn = in.readString();
|
||||
readOnly = in.readInt();
|
||||
parameters = Collections.unmodifiableList(in.readStringList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(declaring);
|
||||
out.writeString(name);
|
||||
out.writeString(rtn);
|
||||
out.writeInt(readOnly);
|
||||
out.writeStringCollection(parameters);
|
||||
}
|
||||
|
||||
public static PainlessContextClassBindingInfo fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(DECLARING.getPreferredName(), declaring);
|
||||
builder.field(NAME.getPreferredName(), name);
|
||||
builder.field(RTN.getPreferredName(), rtn);
|
||||
builder.field(READ_ONLY.getPreferredName(), readOnly);
|
||||
builder.field(PARAMETERS.getPreferredName(), parameters);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String getSortValue() {
|
||||
return PainlessLookupUtility.buildPainlessMethodKey(name, parameters.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PainlessContextClassBindingInfo that = (PainlessContextClassBindingInfo) o;
|
||||
return readOnly == that.readOnly &&
|
||||
Objects.equals(declaring, that.declaring) &&
|
||||
Objects.equals(name, that.name) &&
|
||||
Objects.equals(rtn, that.rtn) &&
|
||||
Objects.equals(parameters, that.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(declaring, name, rtn, readOnly, parameters);
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.painless.lookup.PainlessClass;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PainlessContextClassInfo implements Writeable, ToXContentObject {
|
||||
|
||||
public static final ParseField NAME = new ParseField("name");
|
||||
public static final ParseField IMPORTED = new ParseField("imported");
|
||||
public static final ParseField CONSTRUCTORS = new ParseField("constructors");
|
||||
public static final ParseField STATIC_METHODS = new ParseField("static_methods");
|
||||
public static final ParseField METHODS = new ParseField("methods");
|
||||
public static final ParseField STATIC_FIELDS = new ParseField("static_fields");
|
||||
public static final ParseField FIELDS = new ParseField("fields");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<PainlessContextClassInfo, Void> PARSER = new ConstructingObjectParser<>(
|
||||
PainlessContextClassInfo.class.getCanonicalName(),
|
||||
(v) ->
|
||||
new PainlessContextClassInfo(
|
||||
(String)v[0],
|
||||
(boolean)v[1],
|
||||
(List<PainlessContextConstructorInfo>)v[2],
|
||||
(List<PainlessContextMethodInfo>)v[3],
|
||||
(List<PainlessContextMethodInfo>)v[4],
|
||||
(List<PainlessContextFieldInfo>)v[5],
|
||||
(List<PainlessContextFieldInfo>)v[6]
|
||||
)
|
||||
);
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
|
||||
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), IMPORTED);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextConstructorInfo.fromXContent(p), CONSTRUCTORS);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextMethodInfo.fromXContent(p), STATIC_METHODS);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextMethodInfo.fromXContent(p), METHODS);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextFieldInfo.fromXContent(p), STATIC_FIELDS);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextFieldInfo.fromXContent(p), FIELDS);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final boolean imported;
|
||||
private final List<PainlessContextConstructorInfo> constructors;
|
||||
private final List<PainlessContextMethodInfo> staticMethods;
|
||||
private final List<PainlessContextMethodInfo> methods;
|
||||
private final List<PainlessContextFieldInfo> staticFields;
|
||||
private final List<PainlessContextFieldInfo> fields;
|
||||
|
||||
public PainlessContextClassInfo(Class<?> javaClass, boolean imported, PainlessClass painlessClass) {
|
||||
this(
|
||||
javaClass.getName(),
|
||||
imported,
|
||||
painlessClass.constructors.values().stream().map(PainlessContextConstructorInfo::new).collect(Collectors.toList()),
|
||||
painlessClass.staticMethods.values().stream().map(PainlessContextMethodInfo::new).collect(Collectors.toList()),
|
||||
painlessClass.methods.values().stream().map(PainlessContextMethodInfo::new).collect(Collectors.toList()),
|
||||
painlessClass.staticFields.values().stream().map(PainlessContextFieldInfo::new).collect(Collectors.toList()),
|
||||
painlessClass.fields.values().stream().map(PainlessContextFieldInfo::new).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public PainlessContextClassInfo(String name, boolean imported,
|
||||
List<PainlessContextConstructorInfo> constructors,
|
||||
List<PainlessContextMethodInfo> staticMethods, List<PainlessContextMethodInfo> methods,
|
||||
List<PainlessContextFieldInfo> staticFields, List<PainlessContextFieldInfo> fields) {
|
||||
|
||||
this.name = Objects.requireNonNull(name);
|
||||
this.imported = imported;
|
||||
constructors = new ArrayList<>(Objects.requireNonNull(constructors));
|
||||
constructors.sort(Comparator.comparing(PainlessContextConstructorInfo::getSortValue));
|
||||
this.constructors = Collections.unmodifiableList(constructors);
|
||||
staticMethods = new ArrayList<>(Objects.requireNonNull(staticMethods));
|
||||
staticMethods.sort(Comparator.comparing(PainlessContextMethodInfo::getSortValue));
|
||||
this.staticMethods = Collections.unmodifiableList(staticMethods);
|
||||
methods = new ArrayList<>(Objects.requireNonNull(methods));
|
||||
methods.sort(Comparator.comparing(PainlessContextMethodInfo::getSortValue));
|
||||
this.methods = Collections.unmodifiableList(methods);
|
||||
staticFields = new ArrayList<>(Objects.requireNonNull(staticFields));
|
||||
staticFields.sort(Comparator.comparing(PainlessContextFieldInfo::getSortValue));
|
||||
this.staticFields = Collections.unmodifiableList(staticFields);
|
||||
fields = new ArrayList<>(Objects.requireNonNull(fields));
|
||||
fields.sort(Comparator.comparing(PainlessContextFieldInfo::getSortValue));
|
||||
this.fields = Collections.unmodifiableList(fields);
|
||||
}
|
||||
|
||||
public PainlessContextClassInfo(StreamInput in) throws IOException {
|
||||
name = in.readString();
|
||||
imported = in.readBoolean();
|
||||
constructors = Collections.unmodifiableList(in.readList(PainlessContextConstructorInfo::new));
|
||||
staticMethods = Collections.unmodifiableList(in.readList(PainlessContextMethodInfo::new));
|
||||
methods = Collections.unmodifiableList(in.readList(PainlessContextMethodInfo::new));
|
||||
staticFields = Collections.unmodifiableList(in.readList(PainlessContextFieldInfo::new));
|
||||
fields = Collections.unmodifiableList(in.readList(PainlessContextFieldInfo::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(name);
|
||||
out.writeBoolean(imported);
|
||||
out.writeList(constructors);
|
||||
out.writeList(staticMethods);
|
||||
out.writeList(methods);
|
||||
out.writeList(staticFields);
|
||||
out.writeList(fields);
|
||||
}
|
||||
|
||||
public static PainlessContextClassInfo fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(NAME.getPreferredName(), name);
|
||||
builder.field(IMPORTED.getPreferredName(), imported);
|
||||
builder.field(CONSTRUCTORS.getPreferredName(), constructors);
|
||||
builder.field(STATIC_METHODS.getPreferredName(), staticMethods);
|
||||
builder.field(METHODS.getPreferredName(), methods);
|
||||
builder.field(STATIC_FIELDS.getPreferredName(), staticFields);
|
||||
builder.field(FIELDS.getPreferredName(), fields);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String getSortValue() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PainlessContextClassInfo that = (PainlessContextClassInfo) o;
|
||||
return imported == that.imported &&
|
||||
Objects.equals(name, that.name) &&
|
||||
Objects.equals(constructors, that.constructors) &&
|
||||
Objects.equals(staticMethods, that.staticMethods) &&
|
||||
Objects.equals(methods, that.methods) &&
|
||||
Objects.equals(staticFields, that.staticFields) &&
|
||||
Objects.equals(fields, that.fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, imported, constructors, staticMethods, methods, staticFields, fields);
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.painless.lookup.PainlessConstructor;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PainlessContextConstructorInfo implements Writeable, ToXContentObject {
|
||||
|
||||
public static final ParseField DECLARING = new ParseField("declaring");
|
||||
public static final ParseField PARAMETERS = new ParseField("parameters");
|
||||
|
||||
private final String declaring;
|
||||
private final List<String> parameters;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<PainlessContextConstructorInfo, Void> PARSER = new ConstructingObjectParser<>(
|
||||
PainlessContextConstructorInfo.class.getCanonicalName(),
|
||||
(v) ->
|
||||
new PainlessContextConstructorInfo(
|
||||
(String)v[0],
|
||||
(List<String>)v[1]
|
||||
)
|
||||
);
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), DECLARING);
|
||||
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), PARAMETERS);
|
||||
}
|
||||
|
||||
public PainlessContextConstructorInfo(PainlessConstructor painlessConstructor) {
|
||||
this (
|
||||
painlessConstructor.javaConstructor.getDeclaringClass().getName(),
|
||||
painlessConstructor.typeParameters.stream().map(Class::getName).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public PainlessContextConstructorInfo(String declaring, List<String> parameters) {
|
||||
this.declaring = Objects.requireNonNull(declaring);
|
||||
this.parameters = Collections.unmodifiableList(Objects.requireNonNull(parameters));
|
||||
}
|
||||
|
||||
public PainlessContextConstructorInfo(StreamInput in) throws IOException {
|
||||
declaring = in.readString();
|
||||
parameters = Collections.unmodifiableList(in.readStringList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(declaring);
|
||||
out.writeStringCollection(parameters);
|
||||
}
|
||||
|
||||
public static PainlessContextConstructorInfo fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(DECLARING.getPreferredName(), declaring);
|
||||
builder.field(PARAMETERS.getPreferredName(), parameters);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String getSortValue() {
|
||||
return PainlessLookupUtility.buildPainlessConstructorKey(parameters.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PainlessContextConstructorInfo that = (PainlessContextConstructorInfo) o;
|
||||
return Objects.equals(declaring, that.declaring) &&
|
||||
Objects.equals(parameters, that.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(declaring, parameters);
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.painless.lookup.PainlessField;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PainlessContextFieldInfo implements Writeable, ToXContentObject {
|
||||
|
||||
public static final ParseField DECLARING = new ParseField("declaring");
|
||||
public static final ParseField NAME = new ParseField("name");
|
||||
public static final ParseField TYPE = new ParseField("type");
|
||||
|
||||
private static final ConstructingObjectParser<PainlessContextFieldInfo, Void> PARSER = new ConstructingObjectParser<>(
|
||||
PainlessContextFieldInfo.class.getCanonicalName(),
|
||||
(v) ->
|
||||
new PainlessContextFieldInfo(
|
||||
(String)v[0],
|
||||
(String)v[1],
|
||||
(String)v[2]
|
||||
)
|
||||
);
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), DECLARING);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), TYPE);
|
||||
}
|
||||
|
||||
private final String declaring;
|
||||
private final String name;
|
||||
private final String type;
|
||||
|
||||
public PainlessContextFieldInfo(PainlessField painlessField) {
|
||||
this(
|
||||
painlessField.javaField.getDeclaringClass().getName(),
|
||||
painlessField.javaField.getName(),
|
||||
painlessField.typeParameter.getName()
|
||||
);
|
||||
}
|
||||
|
||||
public PainlessContextFieldInfo(String declaring, String name, String type) {
|
||||
this.declaring = Objects.requireNonNull(declaring);
|
||||
this.name = Objects.requireNonNull(name);
|
||||
this.type = Objects.requireNonNull(type);
|
||||
}
|
||||
|
||||
public PainlessContextFieldInfo(StreamInput in) throws IOException {
|
||||
declaring = in.readString();
|
||||
name = in.readString();
|
||||
type = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(declaring);
|
||||
out.writeString(name);
|
||||
out.writeString(type);
|
||||
}
|
||||
|
||||
public static PainlessContextFieldInfo fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(DECLARING.getPreferredName(), declaring);
|
||||
builder.field(NAME.getPreferredName(), name);
|
||||
builder.field(TYPE.getPreferredName(), type);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String getSortValue() {
|
||||
return PainlessLookupUtility.buildPainlessFieldKey(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PainlessContextFieldInfo that = (PainlessContextFieldInfo) o;
|
||||
return Objects.equals(declaring, that.declaring) &&
|
||||
Objects.equals(name, that.name) &&
|
||||
Objects.equals(type, that.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(declaring, name, type);
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.painless.lookup.PainlessClassBinding;
|
||||
import org.elasticsearch.painless.lookup.PainlessInstanceBinding;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookup;
|
||||
import org.elasticsearch.painless.lookup.PainlessMethod;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PainlessContextInfo implements Writeable, ToXContentObject {
|
||||
|
||||
public static final ParseField NAME = new ParseField("name");
|
||||
public static final ParseField CLASSES = new ParseField("classes");
|
||||
public static final ParseField IMPORTED_METHODS = new ParseField("imported_methods");
|
||||
public static final ParseField CLASS_BINDINGS = new ParseField("class_bindings");
|
||||
public static final ParseField INSTANCE_BINDINGS = new ParseField("instance_bindings");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<PainlessContextInfo, Void> PARSER = new ConstructingObjectParser<>(
|
||||
PainlessContextInfo.class.getCanonicalName(),
|
||||
(v) ->
|
||||
new PainlessContextInfo(
|
||||
(String)v[0],
|
||||
(List<PainlessContextClassInfo>)v[1],
|
||||
(List<PainlessContextMethodInfo>)v[2],
|
||||
(List<PainlessContextClassBindingInfo>)v[3],
|
||||
(List<PainlessContextInstanceBindingInfo>)v[4]
|
||||
)
|
||||
);
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextClassInfo.fromXContent(p), CLASSES);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextMethodInfo.fromXContent(p), IMPORTED_METHODS);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextClassBindingInfo.fromXContent(p), CLASS_BINDINGS);
|
||||
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(),
|
||||
(p, c) -> PainlessContextInstanceBindingInfo.fromXContent(p), INSTANCE_BINDINGS);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final List<PainlessContextClassInfo> classes;
|
||||
private final List<PainlessContextMethodInfo> importedMethods;
|
||||
private final List<PainlessContextClassBindingInfo> classBindings;
|
||||
private final List<PainlessContextInstanceBindingInfo> instanceBindings;
|
||||
|
||||
public PainlessContextInfo(ScriptContext<?> scriptContext, PainlessLookup painlessLookup) {
|
||||
this(
|
||||
scriptContext.name,
|
||||
painlessLookup.getClasses().stream().map(
|
||||
javaClass -> new PainlessContextClassInfo(
|
||||
javaClass,
|
||||
javaClass == painlessLookup.canonicalTypeNameToType(
|
||||
javaClass.getName().substring(javaClass.getName().lastIndexOf('.') + 1).replace('$', '.')),
|
||||
painlessLookup.lookupPainlessClass(javaClass))
|
||||
).collect(Collectors.toList()),
|
||||
painlessLookup.getImportedPainlessMethodsKeys().stream().map(importedPainlessMethodKey -> {
|
||||
String[] split = importedPainlessMethodKey.split("/");
|
||||
String importedPainlessMethodName = split[0];
|
||||
int importedPainlessMethodArity = Integer.parseInt(split[1]);
|
||||
PainlessMethod importedPainlessMethod =
|
||||
painlessLookup.lookupImportedPainlessMethod(importedPainlessMethodName, importedPainlessMethodArity);
|
||||
return new PainlessContextMethodInfo(importedPainlessMethod);
|
||||
}).collect(Collectors.toList()),
|
||||
painlessLookup.getPainlessClassBindingsKeys().stream().map(painlessClassBindingKey -> {
|
||||
String[] split = painlessClassBindingKey.split("/");
|
||||
String painlessClassBindingName = split[0];
|
||||
int painlessClassBindingArity = Integer.parseInt(split[1]);
|
||||
PainlessClassBinding painlessClassBinding =
|
||||
painlessLookup.lookupPainlessClassBinding(painlessClassBindingName, painlessClassBindingArity);
|
||||
return new PainlessContextClassBindingInfo(painlessClassBinding);
|
||||
}).collect(Collectors.toList()),
|
||||
painlessLookup.getPainlessInstanceBindingsKeys().stream().map(painlessInstanceBindingKey -> {
|
||||
String[] split = painlessInstanceBindingKey.split("/");
|
||||
String painlessInstanceBindingName = split[0];
|
||||
int painlessInstanceBindingArity = Integer.parseInt(split[1]);
|
||||
PainlessInstanceBinding painlessInstanceBinding =
|
||||
painlessLookup.lookupPainlessInstanceBinding(painlessInstanceBindingName, painlessInstanceBindingArity);
|
||||
return new PainlessContextInstanceBindingInfo(painlessInstanceBinding);
|
||||
}).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public PainlessContextInfo(String name, List<PainlessContextClassInfo> classes, List<PainlessContextMethodInfo> importedMethods,
|
||||
List<PainlessContextClassBindingInfo> classBindings, List<PainlessContextInstanceBindingInfo> instanceBindings) {
|
||||
this.name = Objects.requireNonNull(name);
|
||||
classes = new ArrayList<>(Objects.requireNonNull(classes));
|
||||
classes.sort(Comparator.comparing(PainlessContextClassInfo::getSortValue));
|
||||
this.classes = Collections.unmodifiableList(classes);
|
||||
importedMethods = new ArrayList<>(Objects.requireNonNull(importedMethods));
|
||||
importedMethods.sort(Comparator.comparing(PainlessContextMethodInfo::getSortValue));
|
||||
this.importedMethods = Collections.unmodifiableList(importedMethods);
|
||||
classBindings = new ArrayList<>(Objects.requireNonNull(classBindings));
|
||||
classBindings.sort(Comparator.comparing(PainlessContextClassBindingInfo::getSortValue));
|
||||
this.classBindings = Collections.unmodifiableList(classBindings);
|
||||
instanceBindings = new ArrayList<>(Objects.requireNonNull(instanceBindings));
|
||||
instanceBindings.sort(Comparator.comparing(PainlessContextInstanceBindingInfo::getSortValue));
|
||||
this.instanceBindings = Collections.unmodifiableList(instanceBindings);
|
||||
}
|
||||
|
||||
public PainlessContextInfo(StreamInput in) throws IOException {
|
||||
name = in.readString();
|
||||
classes = Collections.unmodifiableList(in.readList(PainlessContextClassInfo::new));
|
||||
importedMethods = Collections.unmodifiableList(in.readList(PainlessContextMethodInfo::new));
|
||||
classBindings = Collections.unmodifiableList(in.readList(PainlessContextClassBindingInfo::new));
|
||||
instanceBindings = Collections.unmodifiableList(in.readList(PainlessContextInstanceBindingInfo::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(name);
|
||||
out.writeList(classes);
|
||||
out.writeList(importedMethods);
|
||||
out.writeList(classBindings);
|
||||
out.writeList(instanceBindings);
|
||||
}
|
||||
|
||||
public static PainlessContextInfo fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(NAME.getPreferredName(), name);
|
||||
builder.field(CLASSES.getPreferredName(), classes);
|
||||
builder.field(IMPORTED_METHODS.getPreferredName(), importedMethods);
|
||||
builder.field(CLASS_BINDINGS.getPreferredName(), classBindings);
|
||||
builder.field(INSTANCE_BINDINGS.getPreferredName(), instanceBindings);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PainlessContextInfo that = (PainlessContextInfo) o;
|
||||
return Objects.equals(name, that.name) &&
|
||||
Objects.equals(classes, that.classes) &&
|
||||
Objects.equals(importedMethods, that.importedMethods) &&
|
||||
Objects.equals(classBindings, that.classBindings) &&
|
||||
Objects.equals(instanceBindings, that.instanceBindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, classes, importedMethods, classBindings, instanceBindings);
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.painless.lookup.PainlessInstanceBinding;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PainlessContextInstanceBindingInfo implements Writeable, ToXContentObject {
|
||||
|
||||
public static final ParseField DECLARING = new ParseField("declaring");
|
||||
public static final ParseField NAME = new ParseField("name");
|
||||
public static final ParseField RTN = new ParseField("return");
|
||||
public static final ParseField PARAMETERS = new ParseField("parameters");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<PainlessContextInstanceBindingInfo, Void> PARSER = new ConstructingObjectParser<>(
|
||||
PainlessContextInstanceBindingInfo.class.getCanonicalName(),
|
||||
(v) ->
|
||||
new PainlessContextInstanceBindingInfo(
|
||||
(String)v[0],
|
||||
(String)v[1],
|
||||
(String)v[2],
|
||||
(List<String>)v[3]
|
||||
)
|
||||
);
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), DECLARING);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), RTN);
|
||||
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), PARAMETERS);
|
||||
}
|
||||
|
||||
private final String declaring;
|
||||
private final String name;
|
||||
private final String rtn;
|
||||
private final List<String> parameters;
|
||||
|
||||
public PainlessContextInstanceBindingInfo(PainlessInstanceBinding painlessInstanceBinding) {
|
||||
this(
|
||||
painlessInstanceBinding.javaMethod.getDeclaringClass().getName(),
|
||||
painlessInstanceBinding.javaMethod.getName(),
|
||||
painlessInstanceBinding.returnType.getName(),
|
||||
painlessInstanceBinding.typeParameters.stream().map(Class::getName).collect(Collectors.toList())
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
public PainlessContextInstanceBindingInfo(String declaring, String name, String rtn, List<String> parameters) {
|
||||
this.declaring = Objects.requireNonNull(declaring);
|
||||
this.name = Objects.requireNonNull(name);
|
||||
this.rtn = Objects.requireNonNull(rtn);
|
||||
this.parameters = Collections.unmodifiableList(Objects.requireNonNull(parameters));
|
||||
}
|
||||
|
||||
public PainlessContextInstanceBindingInfo(StreamInput in) throws IOException {
|
||||
declaring = in.readString();
|
||||
name = in.readString();
|
||||
rtn = in.readString();
|
||||
parameters = Collections.unmodifiableList(in.readStringList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(declaring);
|
||||
out.writeString(name);
|
||||
out.writeString(rtn);
|
||||
out.writeStringCollection(parameters);
|
||||
}
|
||||
|
||||
public static PainlessContextInstanceBindingInfo fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(DECLARING.getPreferredName(), declaring);
|
||||
builder.field(NAME.getPreferredName(), name);
|
||||
builder.field(RTN.getPreferredName(), rtn);
|
||||
builder.field(PARAMETERS.getPreferredName(), parameters);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String getSortValue() {
|
||||
return PainlessLookupUtility.buildPainlessMethodKey(name, parameters.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PainlessContextInstanceBindingInfo that = (PainlessContextInstanceBindingInfo) o;
|
||||
return Objects.equals(declaring, that.declaring) &&
|
||||
Objects.equals(name, that.name) &&
|
||||
Objects.equals(rtn, that.rtn) &&
|
||||
Objects.equals(parameters, that.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(declaring, name, rtn, parameters);
|
||||
}
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.painless.lookup.PainlessLookupUtility;
|
||||
import org.elasticsearch.painless.lookup.PainlessMethod;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PainlessContextMethodInfo implements Writeable, ToXContentObject {
|
||||
|
||||
public static final ParseField DECLARING = new ParseField("declaring");
|
||||
public static final ParseField NAME = new ParseField("name");
|
||||
public static final ParseField RTN = new ParseField("return");
|
||||
public static final ParseField PARAMETERS = new ParseField("parameters");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<PainlessContextMethodInfo, Void> PARSER = new ConstructingObjectParser<>(
|
||||
PainlessContextMethodInfo.class.getCanonicalName(),
|
||||
(v) ->
|
||||
new PainlessContextMethodInfo(
|
||||
(String)v[0],
|
||||
(String)v[1],
|
||||
(String)v[2],
|
||||
(List<String>)v[3]
|
||||
)
|
||||
);
|
||||
|
||||
static {
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), DECLARING);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
|
||||
PARSER.declareString(ConstructingObjectParser.constructorArg(), RTN);
|
||||
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), PARAMETERS);
|
||||
}
|
||||
|
||||
private final String declaring;
|
||||
private final String name;
|
||||
private final String rtn;
|
||||
private final List<String> parameters;
|
||||
|
||||
public PainlessContextMethodInfo(PainlessMethod painlessMethod) {
|
||||
this(
|
||||
painlessMethod.javaMethod.getDeclaringClass().getName(),
|
||||
painlessMethod.javaMethod.getName(),
|
||||
painlessMethod.returnType.getName(),
|
||||
painlessMethod.typeParameters.stream().map(Class::getName).collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public PainlessContextMethodInfo(String declaring, String name, String rtn, List<String> parameters) {
|
||||
this.declaring = Objects.requireNonNull(declaring);
|
||||
this.name = Objects.requireNonNull(name);
|
||||
this.rtn = Objects.requireNonNull(rtn);
|
||||
this.parameters = Collections.unmodifiableList(Objects.requireNonNull(parameters));
|
||||
}
|
||||
|
||||
public PainlessContextMethodInfo(StreamInput in) throws IOException {
|
||||
declaring = in.readString();
|
||||
name = in.readString();
|
||||
rtn = in.readString();
|
||||
parameters = Collections.unmodifiableList(in.readStringList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeString(declaring);
|
||||
out.writeString(name);
|
||||
out.writeString(rtn);
|
||||
out.writeStringCollection(parameters);
|
||||
}
|
||||
|
||||
public static PainlessContextMethodInfo fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(DECLARING.getPreferredName(), declaring);
|
||||
builder.field(NAME.getPreferredName(), name);
|
||||
builder.field(RTN.getPreferredName(), rtn);
|
||||
builder.field(PARAMETERS.getPreferredName(), parameters);
|
||||
builder.endObject();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String getSortValue() {
|
||||
return PainlessLookupUtility.buildPainlessMethodKey(name, parameters.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PainlessContextMethodInfo that = (PainlessContextMethodInfo) o;
|
||||
return Objects.equals(declaring, that.declaring) &&
|
||||
Objects.equals(name, that.name) &&
|
||||
Objects.equals(rtn, that.rtn) &&
|
||||
Objects.equals(parameters, that.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(declaring, name, rtn, parameters);
|
||||
}
|
||||
}
|
@ -87,6 +87,18 @@ public final class PainlessLookup {
|
||||
return classesToPainlessClasses.keySet();
|
||||
}
|
||||
|
||||
public Set<String> getImportedPainlessMethodsKeys() {
|
||||
return painlessMethodKeysToImportedPainlessMethods.keySet();
|
||||
}
|
||||
|
||||
public Set<String> getPainlessClassBindingsKeys() {
|
||||
return painlessMethodKeysToPainlessClassBindings.keySet();
|
||||
}
|
||||
|
||||
public Set<String> getPainlessInstanceBindingsKeys() {
|
||||
return painlessMethodKeysToPainlessInstanceBindings.keySet();
|
||||
}
|
||||
|
||||
public PainlessClass lookupPainlessClass(Class<?> targetClass) {
|
||||
return classesToPainlessClasses.get(targetClass);
|
||||
}
|
||||
|
@ -202,6 +202,7 @@ public final class PainlessLookupUtility {
|
||||
|
||||
return typesStringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a java type to a type based on the terminology specified as part of {@link PainlessLookupUtility} where if a type is an
|
||||
* object class or object array, the returned type will be the equivalent def class or def array. Otherwise, this behaves as an
|
||||
|
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.painless.action;
|
||||
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ContextInfoTests extends AbstractSerializingTestCase<PainlessContextInfo> {
|
||||
|
||||
@Override
|
||||
protected PainlessContextInfo doParseInstance(XContentParser parser) {
|
||||
return PainlessContextInfo.fromXContent(parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PainlessContextInfo createTestInstance() {
|
||||
int classesSize = randomIntBetween(20, 100);
|
||||
List<PainlessContextClassInfo> classes = new ArrayList<>();
|
||||
|
||||
for (int clazz = 0; clazz < classesSize; ++clazz) {
|
||||
int constructorsSize = randomInt(4);
|
||||
List<PainlessContextConstructorInfo> constructors = new ArrayList<>(constructorsSize);
|
||||
for (int constructor = 0; constructor < constructorsSize; ++constructor) {
|
||||
int parameterSize = randomInt(12);
|
||||
List<String> parameters = new ArrayList<>(parameterSize);
|
||||
for (int parameter = 0; parameter < parameterSize; ++parameter) {
|
||||
parameters.add(randomAlphaOfLengthBetween(1, 20));
|
||||
}
|
||||
constructors.add(new PainlessContextConstructorInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
parameters));
|
||||
}
|
||||
;
|
||||
|
||||
int staticMethodsSize = randomInt(4);
|
||||
List<PainlessContextMethodInfo> staticMethods = new ArrayList<>(staticMethodsSize);
|
||||
for (int staticMethod = 0; staticMethod < staticMethodsSize; ++staticMethod) {
|
||||
int parameterSize = randomInt(12);
|
||||
List<String> parameters = new ArrayList<>(parameterSize);
|
||||
for (int parameter = 0; parameter < parameterSize; ++parameter) {
|
||||
parameters.add(randomAlphaOfLengthBetween(1, 20));
|
||||
}
|
||||
staticMethods.add(new PainlessContextMethodInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
parameters));
|
||||
}
|
||||
|
||||
int methodsSize = randomInt(10);
|
||||
List<PainlessContextMethodInfo> methods = new ArrayList<>(methodsSize);
|
||||
for (int method = 0; method < methodsSize; ++method) {
|
||||
int parameterSize = randomInt(12);
|
||||
List<String> parameters = new ArrayList<>(parameterSize);
|
||||
for (int parameter = 0; parameter < parameterSize; ++parameter) {
|
||||
parameters.add(randomAlphaOfLengthBetween(1, 20));
|
||||
}
|
||||
methods.add(new PainlessContextMethodInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
parameters));
|
||||
}
|
||||
|
||||
int staticFieldsSize = randomInt(10);
|
||||
List<PainlessContextFieldInfo> staticFields = new ArrayList<>();
|
||||
for (int staticField = 0; staticField < staticFieldsSize; ++staticField) {
|
||||
staticFields.add(new PainlessContextFieldInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10))));
|
||||
}
|
||||
|
||||
int fieldsSize = randomInt(4);
|
||||
List<PainlessContextFieldInfo> fields = new ArrayList<>();
|
||||
for (int field = 0; field < fieldsSize; ++field) {
|
||||
fields.add(new PainlessContextFieldInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10))));
|
||||
}
|
||||
|
||||
classes.add(new PainlessContextClassInfo(
|
||||
randomAlphaOfLength(randomIntBetween(3, 200)), randomBoolean(),
|
||||
constructors, staticMethods, methods, fields, staticFields));
|
||||
}
|
||||
|
||||
int importedMethodsSize = randomInt(4);
|
||||
List<PainlessContextMethodInfo> importedMethods = new ArrayList<>(importedMethodsSize);
|
||||
for (int importedMethod = 0; importedMethod < importedMethodsSize; ++importedMethod) {
|
||||
int parameterSize = randomInt(12);
|
||||
List<String> parameters = new ArrayList<>(parameterSize);
|
||||
for (int parameter = 0; parameter < parameterSize; ++parameter) {
|
||||
parameters.add(randomAlphaOfLengthBetween(1, 20));
|
||||
}
|
||||
importedMethods.add(new PainlessContextMethodInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
parameters));
|
||||
}
|
||||
|
||||
int classBindingsSize = randomInt(3);
|
||||
List<PainlessContextClassBindingInfo> classBindings = new ArrayList<>(classBindingsSize);
|
||||
for (int classBinding = 0; classBinding < classBindingsSize; ++classBinding) {
|
||||
int parameterSize = randomIntBetween(2, 5);
|
||||
int readOnly = randomIntBetween(1, parameterSize - 1);
|
||||
List<String> parameters = new ArrayList<>(parameterSize);
|
||||
for (int parameter = 0; parameter < parameterSize; ++parameter) {
|
||||
parameters.add(randomAlphaOfLengthBetween(1, 20));
|
||||
}
|
||||
classBindings.add(new PainlessContextClassBindingInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
readOnly,
|
||||
parameters));
|
||||
}
|
||||
|
||||
int instanceBindingsSize = randomInt(3);
|
||||
List<PainlessContextInstanceBindingInfo> instanceBindings = new ArrayList<>(classBindingsSize);
|
||||
for (int instanceBinding = 0; instanceBinding < instanceBindingsSize; ++instanceBinding) {
|
||||
int parameterSize = randomInt(12);
|
||||
List<String> parameters = new ArrayList<>(parameterSize);
|
||||
for (int parameter = 0; parameter < parameterSize; ++parameter) {
|
||||
parameters.add(randomAlphaOfLengthBetween(1, 20));
|
||||
}
|
||||
instanceBindings.add(new PainlessContextInstanceBindingInfo(
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
randomAlphaOfLength(randomIntBetween(4, 10)),
|
||||
parameters));
|
||||
}
|
||||
|
||||
return new PainlessContextInfo(randomAlphaOfLength(20),
|
||||
classes, importedMethods, classBindings, instanceBindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Writeable.Reader<PainlessContextInfo> instanceReader() {
|
||||
return PainlessContextInfo::new;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
"Action to list contexts":
|
||||
- do:
|
||||
scripts_painless_context: {}
|
||||
- match: { contexts.0: aggregation_selector}
|
||||
- match: { contexts.22: update}
|
||||
---
|
||||
|
||||
"Action to get all API values for score context":
|
||||
- do:
|
||||
scripts_painless_context:
|
||||
context: score
|
||||
- match: { name: score }
|
||||
- match: { classes.6.name: java.lang.Appendable }
|
||||
- match: { classes.6.imported: true }
|
||||
- match: { classes.6.methods.0.name : append }
|
||||
- match: { classes.6.methods.0.return : java.lang.Appendable }
|
||||
- match: { classes.6.methods.0.parameters.0 : java.lang.CharSequence }
|
||||
- match: { classes.6.methods.0.parameters.1 : int }
|
||||
- match: { classes.6.methods.0.parameters.2 : int }
|
||||
- match: { imported_methods.0.name: dotProduct }
|
||||
- match: { class_bindings.0.name: cosineSimilarity }
|
||||
- match: { instance_bindings: [] }
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"scripts_painless_context": {
|
||||
"methods": ["GET"],
|
||||
"url": {
|
||||
"path": "/_scripts/painless/_context",
|
||||
"paths": ["/_scripts/painless/_context"],
|
||||
"parts": {
|
||||
},
|
||||
"params": {
|
||||
"context" : {
|
||||
"type" : "string",
|
||||
"description" : "Select a specific context to retrieve API information about"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user