Merge branch 'master' into index-lifecycle

This commit is contained in:
Colin Goodheart-Smithe 2018-07-20 07:56:57 +01:00
commit 573a9e6443
No known key found for this signature in database
GPG Key ID: F975E7BDD739B3C7
46 changed files with 619 additions and 765 deletions

View File

@ -25,8 +25,8 @@ plugins {
group = 'org.elasticsearch.gradle' group = 'org.elasticsearch.gradle'
if (GradleVersion.current() < GradleVersion.version('3.3')) { if (GradleVersion.current() < GradleVersion.version('4.9')) {
throw new GradleException('Gradle 3.3+ is required to build elasticsearch') throw new GradleException('Gradle 4.9+ is required to build elasticsearch')
} }
if (JavaVersion.current() < JavaVersion.VERSION_1_8) { if (JavaVersion.current() < JavaVersion.VERSION_1_8) {

View File

@ -67,6 +67,9 @@ class BuildPlugin implements Plugin<Project> {
+ 'elasticearch.standalone-rest-test, and elasticsearch.build ' + 'elasticearch.standalone-rest-test, and elasticsearch.build '
+ 'are mutually exclusive') + 'are mutually exclusive')
} }
if (GradleVersion.current() < GradleVersion.version('4.9')) {
throw new GradleException('Gradle 4.9+ is required to use elasticsearch.build plugin')
}
project.pluginManager.apply('java') project.pluginManager.apply('java')
project.pluginManager.apply('carrotsearch.randomized-testing') project.pluginManager.apply('carrotsearch.randomized-testing')
// these plugins add lots of info to our jars // these plugins add lots of info to our jars
@ -750,7 +753,6 @@ class BuildPlugin implements Plugin<Project> {
systemProperty 'tests.task', path systemProperty 'tests.task', path
systemProperty 'tests.security.manager', 'true' systemProperty 'tests.security.manager', 'true'
systemProperty 'jna.nosys', 'true' systemProperty 'jna.nosys', 'true'
systemProperty 'es.scripting.exception_for_missing_value', 'true'
// TODO: remove setting logging level via system property // TODO: remove setting logging level via system property
systemProperty 'tests.logger.level', 'WARN' systemProperty 'tests.logger.level', 'WARN'
for (Map.Entry<String, String> property : System.properties.entrySet()) { for (Map.Entry<String, String> property : System.properties.entrySet()) {

View File

@ -123,21 +123,8 @@ GET hockey/_search
[float] [float]
===== Missing values ===== Missing values
If you request the value from a field `field` that isnt in `doc['field'].value` throws an exception if
the document, `doc['field'].value` for this document returns: the field is missing in a document.
- `0` if a `field` has a numeric datatype (long, double etc.)
- `false` is a `field` has a boolean datatype
- epoch date if a `field` has a date datatype
- `null` if a `field` has a string datatype
- `null` if a `field` has a geo datatype
- `""` if a `field` has a binary datatype
IMPORTANT: Starting in 7.0, `doc['field'].value` throws an exception if
the field is missing in a document. To enable this behavior now,
set a {ref}/jvm-options.html[`jvm.option`]
`-Des.scripting.exception_for_missing_value=true` on a node. If you do not enable
this behavior, a deprecation warning is logged on start up.
To check if a document is missing a value, you can call To check if a document is missing a value, you can call
`doc['field'].size() == 0`. `doc['field'].size() == 0`.

View File

@ -466,8 +466,8 @@ public final class AnalyzerCaster {
return PainlessCast.standard(actual, expected, explicit); return PainlessCast.standard(actual, expected, explicit);
} else { } else {
throw location.createError(new ClassCastException("Cannot cast from " + throw location.createError(new ClassCastException("Cannot cast from " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(actual) + "] to " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(actual) + "] to " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(expected) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "]."));
} }
} }

View File

@ -302,7 +302,7 @@ public final class Def {
nestedType, nestedType,
0, 0,
DefBootstrap.REFERENCE, DefBootstrap.REFERENCE,
PainlessLookupUtility.anyTypeToPainlessTypeName(interfaceType)); PainlessLookupUtility.typeToCanonicalTypeName(interfaceType));
filter = nested.dynamicInvoker(); filter = nested.dynamicInvoker();
} else { } else {
throw new AssertionError(); throw new AssertionError();
@ -334,7 +334,7 @@ public final class Def {
int arity = interfaceMethod.arguments.size(); int arity = interfaceMethod.arguments.size();
PainlessMethod implMethod = lookupMethodInternal(painlessLookup, receiverClass, name, arity); PainlessMethod implMethod = lookupMethodInternal(painlessLookup, receiverClass, name, arity);
return lookupReferenceInternal(painlessLookup, methodHandlesLookup, interfaceType, return lookupReferenceInternal(painlessLookup, methodHandlesLookup, interfaceType,
PainlessLookupUtility.anyTypeToPainlessTypeName(implMethod.target), implMethod.name, receiverClass); PainlessLookupUtility.typeToCanonicalTypeName(implMethod.target), implMethod.name, receiverClass);
} }
/** Returns a method handle to an implementation of clazz, given method reference signature. */ /** Returns a method handle to an implementation of clazz, given method reference signature. */
@ -347,7 +347,7 @@ public final class Def {
PainlessMethod interfaceMethod = painlessLookup.getPainlessStructFromJavaClass(clazz).functionalMethod; PainlessMethod interfaceMethod = painlessLookup.getPainlessStructFromJavaClass(clazz).functionalMethod;
if (interfaceMethod == null) { if (interfaceMethod == null) {
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " + throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
"to [" + PainlessLookupUtility.anyTypeToPainlessTypeName(clazz) + "], not a functional interface"); "to [" + PainlessLookupUtility.typeToCanonicalTypeName(clazz) + "], not a functional interface");
} }
int arity = interfaceMethod.arguments.size() + captures.length; int arity = interfaceMethod.arguments.size() + captures.length;
final MethodHandle handle; final MethodHandle handle;

View File

@ -168,7 +168,7 @@ public class FunctionRef {
PainlessMethod method = painlessLookup.getPainlessStructFromJavaClass(expected).functionalMethod; PainlessMethod method = painlessLookup.getPainlessStructFromJavaClass(expected).functionalMethod;
if (method == null) { if (method == null) {
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " + throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
"to [" + PainlessLookupUtility.anyTypeToPainlessTypeName(expected) + "], not a functional interface"); "to [" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "], not a functional interface");
} }
// lookup requested method // lookup requested method

View File

@ -292,7 +292,7 @@ public final class Locals {
@Override @Override
public String toString() { public String toString() {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
b.append("Variable[type=").append(PainlessLookupUtility.anyTypeToPainlessTypeName(clazz)); b.append("Variable[type=").append(PainlessLookupUtility.typeToCanonicalTypeName(clazz));
b.append(",name=").append(name); b.append(",name=").append(name);
b.append(",slot=").append(slot); b.append(",slot=").append(slot);
if (readonly) { if (readonly) {

View File

@ -183,7 +183,7 @@ public class ScriptClassInfo {
private static Class<?> definitionTypeForClass(PainlessLookup painlessLookup, Class<?> type, private static Class<?> definitionTypeForClass(PainlessLookup painlessLookup, Class<?> type,
Function<Class<?>, String> unknownErrorMessageSource) { Function<Class<?>, String> unknownErrorMessageSource) {
type = PainlessLookupUtility.javaObjectTypeToPainlessDefType(type); type = PainlessLookupUtility.javaTypeToType(type);
Class<?> componentType = type; Class<?> componentType = type;
while (componentType.isArray()) { while (componentType.isArray()) {

View File

@ -54,6 +54,6 @@ public final class PainlessLookup {
} }
public Class<?> getJavaClassFromPainlessType(String painlessType) { public Class<?> getJavaClassFromPainlessType(String painlessType) {
return PainlessLookupUtility.painlessTypeNameToPainlessType(painlessType, painlessTypesToJavaClasses); return PainlessLookupUtility.canonicalTypeNameToType(painlessType, painlessTypesToJavaClasses);
} }
} }

View File

@ -30,7 +30,6 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -39,22 +38,21 @@ import java.util.Objects;
import java.util.Stack; import java.util.Stack;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.DEF_PAINLESS_CLASS_NAME; import static org.elasticsearch.painless.lookup.PainlessLookupUtility.DEF_TYPE_NAME;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.anyTypeNameToPainlessTypeName;
import static org.elasticsearch.painless.lookup.PainlessLookupUtility.buildPainlessMethodKey; import static org.elasticsearch.painless.lookup.PainlessLookupUtility.buildPainlessMethodKey;
public class PainlessLookupBuilder { public class PainlessLookupBuilder {
private static class PainlessMethodCacheKey { private static class PainlessMethodCacheKey {
private final Class<?> javaClass; private final Class<?> targetType;
private final String methodName; private final String methodName;
private final List<Class<?>> painlessTypeParameters; private final List<Class<?>> typeParameters;
private PainlessMethodCacheKey(Class<?> javaClass, String methodName, List<Class<?>> painlessTypeParameters) { private PainlessMethodCacheKey(Class<?> targetType, String methodName, List<Class<?>> typeParameters) {
this.javaClass = javaClass; this.targetType = targetType;
this.methodName = methodName; this.methodName = methodName;
this.painlessTypeParameters = Collections.unmodifiableList(painlessTypeParameters); this.typeParameters = Collections.unmodifiableList(typeParameters);
} }
@Override @Override
@ -69,27 +67,27 @@ public class PainlessLookupBuilder {
PainlessMethodCacheKey that = (PainlessMethodCacheKey)object; PainlessMethodCacheKey that = (PainlessMethodCacheKey)object;
return Objects.equals(javaClass, that.javaClass) && return Objects.equals(targetType, that.targetType) &&
Objects.equals(methodName, that.methodName) && Objects.equals(methodName, that.methodName) &&
Objects.equals(painlessTypeParameters, that.painlessTypeParameters); Objects.equals(typeParameters, that.typeParameters);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(javaClass, methodName, painlessTypeParameters); return Objects.hash(targetType, methodName, typeParameters);
} }
} }
private static class PainlessFieldCacheKey { private static class PainlessFieldCacheKey {
private final Class<?> javaClass; private final Class<?> targetType;
private final String fieldName; private final String fieldName;
private final Class<?> painlessType; private final Class<?> typeParameter;
private PainlessFieldCacheKey(Class<?> javaClass, String fieldName, Class<?> painlessType) { private PainlessFieldCacheKey(Class<?> targetType, String fieldName, Class<?> typeParameter) {
this.javaClass = javaClass; this.targetType = targetType;
this.fieldName = fieldName; this.fieldName = fieldName;
this.painlessType = painlessType; this.typeParameter = typeParameter;
} }
@Override @Override
@ -104,14 +102,14 @@ public class PainlessLookupBuilder {
PainlessFieldCacheKey that = (PainlessFieldCacheKey) object; PainlessFieldCacheKey that = (PainlessFieldCacheKey) object;
return Objects.equals(javaClass, that.javaClass) && return Objects.equals(targetType, that.targetType) &&
Objects.equals(fieldName, that.fieldName) && Objects.equals(fieldName, that.fieldName) &&
Objects.equals(painlessType, that.painlessType); Objects.equals(typeParameter, that.typeParameter);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(javaClass, fieldName, painlessType); return Objects.hash(targetType, fieldName, typeParameter);
} }
} }
@ -122,157 +120,115 @@ public class PainlessLookupBuilder {
private static final Pattern METHOD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$"); private static final Pattern METHOD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$");
private static final Pattern FIELD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$"); private static final Pattern FIELD_NAME_PATTERN = Pattern.compile("^[_a-zA-Z][_a-zA-Z0-9]*$");
private static String anyTypesArrayToCanonicalString(Class<?>[] anyTypesArray, boolean toPainlessTypes) {
return anyTypesListToCanonicalString(Arrays.asList(anyTypesArray), toPainlessTypes);
}
private static String anyTypesListToCanonicalString(List<Class<?>> anyTypesList, boolean toPainlessTypes) {
StringBuilder anyTypesCanonicalStringBuilder = new StringBuilder("[");
int anyTypesSize = anyTypesList.size();
int anyTypesIndex = 0;
for (Class<?> anyType : anyTypesList) {
String anyTypeCanonicalName = anyType.getCanonicalName();
if (toPainlessTypes) {
anyTypeCanonicalName = anyTypeNameToPainlessTypeName(anyTypeCanonicalName);
}
anyTypesCanonicalStringBuilder.append(anyTypeCanonicalName);
if (++anyTypesIndex < anyTypesSize) {
anyTypesCanonicalStringBuilder.append(",");
}
}
anyTypesCanonicalStringBuilder.append("]");
return anyTypesCanonicalStringBuilder.toString();
}
private final List<Whitelist> whitelists; private final List<Whitelist> whitelists;
private final Map<String, Class<?>> painlessClassNamesToJavaClasses; private final Map<String, Class<?>> canonicalClassNamesToClasses;
private final Map<Class<?>, PainlessClassBuilder> javaClassesToPainlessClassBuilders; private final Map<Class<?>, PainlessClassBuilder> classesToPainlessClasses;
public PainlessLookupBuilder(List<Whitelist> whitelists) { public PainlessLookupBuilder(List<Whitelist> whitelists) {
this.whitelists = whitelists; this.whitelists = whitelists;
painlessClassNamesToJavaClasses = new HashMap<>(); canonicalClassNamesToClasses = new HashMap<>();
javaClassesToPainlessClassBuilders = new HashMap<>(); classesToPainlessClasses = new HashMap<>();
painlessClassNamesToJavaClasses.put(DEF_PAINLESS_CLASS_NAME, def.class); canonicalClassNamesToClasses.put(DEF_TYPE_NAME, def.class);
javaClassesToPainlessClassBuilders.put(def.class, classesToPainlessClasses.put(def.class,
new PainlessClassBuilder(DEF_PAINLESS_CLASS_NAME, Object.class, Type.getType(Object.class))); new PainlessClassBuilder(DEF_TYPE_NAME, Object.class, Type.getType(Object.class)));
} }
private Class<?> painlessTypeNameToPainlessType(String painlessTypeName) { private Class<?> canonicalTypeNameToType(String canonicalTypeName) {
return PainlessLookupUtility.painlessTypeNameToPainlessType(painlessTypeName, painlessClassNamesToJavaClasses); return PainlessLookupUtility.canonicalTypeNameToType(canonicalTypeName, canonicalClassNamesToClasses);
} }
private void validatePainlessType(Class<?> painlessType) { private void validateType(Class<?> type) {
PainlessLookupUtility.validatePainlessType(painlessType, javaClassesToPainlessClassBuilders.keySet()); PainlessLookupUtility.validateType(type, classesToPainlessClasses.keySet());
} }
public void addPainlessClass(ClassLoader classLoader, String javaClassName, boolean importPainlessClassName) { public void addPainlessClass(ClassLoader classLoader, String javaClassName, boolean importClassName) {
Objects.requireNonNull(classLoader); Objects.requireNonNull(classLoader);
Objects.requireNonNull(javaClassName); Objects.requireNonNull(javaClassName);
String painlessClassName = anyTypeNameToPainlessTypeName(javaClassName); Class<?> clazz;
if (CLASS_NAME_PATTERN.matcher(painlessClassName).matches() == false) { if ("void".equals(javaClassName)) clazz = void.class;
throw new IllegalArgumentException("invalid painless class name [" + painlessClassName + "]"); else if ("boolean".equals(javaClassName)) clazz = boolean.class;
} else if ("byte".equals(javaClassName)) clazz = byte.class;
else if ("short".equals(javaClassName)) clazz = short.class;
String importedPainlessClassName = anyTypeNameToPainlessTypeName(javaClassName.substring(javaClassName.lastIndexOf('.') + 1)); else if ("char".equals(javaClassName)) clazz = char.class;
else if ("int".equals(javaClassName)) clazz = int.class;
Class<?> javaClass; else if ("long".equals(javaClassName)) clazz = long.class;
else if ("float".equals(javaClassName)) clazz = float.class;
if ("void".equals(javaClassName)) javaClass = void.class; else if ("double".equals(javaClassName)) clazz = double.class;
else if ("boolean".equals(javaClassName)) javaClass = boolean.class;
else if ("byte".equals(javaClassName)) javaClass = byte.class;
else if ("short".equals(javaClassName)) javaClass = short.class;
else if ("char".equals(javaClassName)) javaClass = char.class;
else if ("int".equals(javaClassName)) javaClass = int.class;
else if ("long".equals(javaClassName)) javaClass = long.class;
else if ("float".equals(javaClassName)) javaClass = float.class;
else if ("double".equals(javaClassName)) javaClass = double.class;
else { else {
try { try {
javaClass = Class.forName(javaClassName, true, classLoader); clazz = Class.forName(javaClassName, true, classLoader);
if (javaClass == def.class) {
throw new IllegalArgumentException("cannot add reserved painless class [" + DEF_PAINLESS_CLASS_NAME + "]");
}
if (javaClass.isArray()) {
throw new IllegalArgumentException("cannot add an array type java class [" + javaClassName + "] as a painless class");
}
} catch (ClassNotFoundException cnfe) { } catch (ClassNotFoundException cnfe) {
throw new IllegalArgumentException("java class [" + javaClassName + "] not found", cnfe); throw new IllegalArgumentException("class [" + javaClassName + "] not found", cnfe);
} }
} }
addPainlessClass(painlessClassName, importedPainlessClassName, javaClass, importPainlessClassName); addPainlessClass(clazz, importClassName);
} }
public void addPainlessClass(Class<?> javaClass, boolean importPainlessClassName) { public void addPainlessClass(Class<?> clazz, boolean importClassName) {
Objects.requireNonNull(javaClass); Objects.requireNonNull(clazz);
if (javaClass == def.class) { if (clazz == def.class) {
throw new IllegalArgumentException("cannot specify reserved painless class [" + DEF_PAINLESS_CLASS_NAME + "]"); throw new IllegalArgumentException("cannot add reserved class [" + DEF_TYPE_NAME + "]");
} }
String javaClassName = javaClass.getCanonicalName(); String canonicalClassName = clazz.getCanonicalName();
String painlessClassName = anyTypeNameToPainlessTypeName(javaClassName);
String importedPainlessClassName = anyTypeNameToPainlessTypeName(javaClassName.substring(javaClassName.lastIndexOf('.') + 1));
addPainlessClass(painlessClassName, importedPainlessClassName, javaClass, importPainlessClassName); if (clazz.isArray()) {
} throw new IllegalArgumentException("cannot add array type [" + canonicalClassName + "] as a class");
}
private void addPainlessClass( if (CLASS_NAME_PATTERN.matcher(canonicalClassName).matches() == false) {
String painlessClassName, String importedPainlessClassName, Class<?> javaClass, boolean importPainlessClassName) { throw new IllegalArgumentException("invalid class name [" + canonicalClassName + "]");
PainlessClassBuilder existingPainlessClassBuilder = javaClassesToPainlessClassBuilders.get(javaClass); }
PainlessClassBuilder existingPainlessClassBuilder = classesToPainlessClasses.get(clazz);
if (existingPainlessClassBuilder == null) { if (existingPainlessClassBuilder == null) {
PainlessClassBuilder painlessClassBuilder = new PainlessClassBuilder(painlessClassName, javaClass, Type.getType(javaClass)); PainlessClassBuilder painlessClassBuilder = new PainlessClassBuilder(canonicalClassName, clazz, Type.getType(clazz));
painlessClassNamesToJavaClasses.put(painlessClassName, javaClass);
javaClassesToPainlessClassBuilders.put(javaClass, painlessClassBuilder); canonicalClassNamesToClasses.put(canonicalClassName, clazz);
} else if (existingPainlessClassBuilder.clazz.equals(javaClass) == false) { classesToPainlessClasses.put(clazz, painlessClassBuilder);
throw new IllegalArgumentException("painless class [" + painlessClassName + "] illegally represents multiple java classes " + } else if (existingPainlessClassBuilder.clazz.equals(clazz) == false) {
"[" + javaClass.getCanonicalName() + "] and [" + existingPainlessClassBuilder.clazz.getCanonicalName() + "]"); throw new IllegalArgumentException("class [" + canonicalClassName + "] " +
"cannot represent multiple java classes with the same name from different class loaders");
} }
if (painlessClassName.equals(importedPainlessClassName)) { String javaClassName = clazz.getName();
if (importPainlessClassName == true) { String importedCanonicalClassName = javaClassName.substring(javaClassName.lastIndexOf('.') + 1).replace('$', '.');
throw new IllegalArgumentException(
"must use only_fqn parameter on painless class [" + painlessClassName + "] with no package"); if (canonicalClassName.equals(importedCanonicalClassName)) {
if (importClassName == true) {
throw new IllegalArgumentException("must use only_fqn parameter on class [" + canonicalClassName + "] with no package");
} }
} else { } else {
Class<?> importedJavaClass = painlessClassNamesToJavaClasses.get(importedPainlessClassName); Class<?> importedPainlessType = canonicalClassNamesToClasses.get(importedCanonicalClassName);
if (importedJavaClass == null) { if (importedPainlessType == null) {
if (importPainlessClassName) { if (importClassName) {
if (existingPainlessClassBuilder != null) { if (existingPainlessClassBuilder != null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"inconsistent only_fqn parameters found for painless class [" + painlessClassName + "]"); "inconsistent only_fqn parameters found for painless type [" + canonicalClassName + "]");
} }
painlessClassNamesToJavaClasses.put(importedPainlessClassName, javaClass); canonicalClassNamesToClasses.put(importedCanonicalClassName, clazz);
} }
} else if (importedJavaClass.equals(javaClass) == false) { } else if (importedPainlessType.equals(clazz) == false) {
throw new IllegalArgumentException("painless class [" + importedPainlessClassName + "] illegally represents multiple " + throw new IllegalArgumentException("painless type [" + importedCanonicalClassName + "] illegally represents multiple " +
"java classes [" + javaClass.getCanonicalName() + "] and [" + importedJavaClass.getCanonicalName() + "]"); "java types [" + clazz.getCanonicalName() + "] and [" + importedPainlessType.getCanonicalName() + "]");
} else if (importPainlessClassName == false) { } else if (importClassName == false) {
throw new IllegalArgumentException( throw new IllegalArgumentException("inconsistent only_fqn parameters found for painless type [" + canonicalClassName + "]");
"inconsistent only_fqn parameters found for painless class [" + painlessClassName + "]");
} }
} }
} }
private void addConstructor(String ownerStructName, WhitelistConstructor whitelistConstructor) { private void addConstructor(String ownerStructName, WhitelistConstructor whitelistConstructor) {
PainlessClassBuilder ownerStruct = javaClassesToPainlessClassBuilders.get(painlessClassNamesToJavaClasses.get(ownerStructName)); PainlessClassBuilder ownerStruct = classesToPainlessClasses.get(canonicalClassNamesToClasses.get(ownerStructName));
if (ownerStruct == null) { if (ownerStruct == null) {
throw new IllegalArgumentException("owner struct [" + ownerStructName + "] not defined for constructor with " + throw new IllegalArgumentException("owner struct [" + ownerStructName + "] not defined for constructor with " +
@ -286,10 +242,10 @@ public class PainlessLookupBuilder {
String painlessParameterTypeName = whitelistConstructor.painlessParameterTypeNames.get(parameterCount); String painlessParameterTypeName = whitelistConstructor.painlessParameterTypeNames.get(parameterCount);
try { try {
Class<?> painlessParameterClass = painlessTypeNameToPainlessType(painlessParameterTypeName); Class<?> painlessParameterClass = canonicalTypeNameToType(painlessParameterTypeName);
painlessParametersTypes.add(painlessParameterClass); painlessParametersTypes.add(painlessParameterClass);
javaClassParameters[parameterCount] = PainlessLookupUtility.painlessDefTypeToJavaObjectType(painlessParameterClass); javaClassParameters[parameterCount] = PainlessLookupUtility.typeToJavaType(painlessParameterClass);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
throw new IllegalArgumentException("struct not defined for constructor parameter [" + painlessParameterTypeName + "] " + throw new IllegalArgumentException("struct not defined for constructor parameter [" + painlessParameterTypeName + "] " +
"with owner struct [" + ownerStructName + "] and constructor parameters " + "with owner struct [" + ownerStructName + "] and constructor parameters " +
@ -333,7 +289,7 @@ public class PainlessLookupBuilder {
} }
private void addMethod(ClassLoader whitelistClassLoader, String ownerStructName, WhitelistMethod whitelistMethod) { private void addMethod(ClassLoader whitelistClassLoader, String ownerStructName, WhitelistMethod whitelistMethod) {
PainlessClassBuilder ownerStruct = javaClassesToPainlessClassBuilders.get(painlessClassNamesToJavaClasses.get(ownerStructName)); PainlessClassBuilder ownerStruct = classesToPainlessClasses.get(canonicalClassNamesToClasses.get(ownerStructName));
if (ownerStruct == null) { if (ownerStruct == null) {
throw new IllegalArgumentException("owner struct [" + ownerStructName + "] not defined for method with " + throw new IllegalArgumentException("owner struct [" + ownerStructName + "] not defined for method with " +
@ -372,11 +328,11 @@ public class PainlessLookupBuilder {
String painlessParameterTypeName = whitelistMethod.painlessParameterTypeNames.get(parameterCount); String painlessParameterTypeName = whitelistMethod.painlessParameterTypeNames.get(parameterCount);
try { try {
Class<?> painlessParameterClass = painlessTypeNameToPainlessType(painlessParameterTypeName); Class<?> painlessParameterClass = canonicalTypeNameToType(painlessParameterTypeName);
painlessParametersTypes.add(painlessParameterClass); painlessParametersTypes.add(painlessParameterClass);
javaClassParameters[parameterCount + augmentedOffset] = javaClassParameters[parameterCount + augmentedOffset] =
PainlessLookupUtility.painlessDefTypeToJavaObjectType(painlessParameterClass); PainlessLookupUtility.typeToJavaType(painlessParameterClass);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
throw new IllegalArgumentException("struct not defined for method parameter [" + painlessParameterTypeName + "] " + throw new IllegalArgumentException("struct not defined for method parameter [" + painlessParameterTypeName + "] " +
"with owner struct [" + ownerStructName + "] and method with name [" + whitelistMethod.javaMethodName + "] " + "with owner struct [" + ownerStructName + "] and method with name [" + whitelistMethod.javaMethodName + "] " +
@ -398,14 +354,14 @@ public class PainlessLookupBuilder {
Class<?> painlessReturnClass; Class<?> painlessReturnClass;
try { try {
painlessReturnClass = painlessTypeNameToPainlessType(whitelistMethod.painlessReturnTypeName); painlessReturnClass = canonicalTypeNameToType(whitelistMethod.painlessReturnTypeName);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
throw new IllegalArgumentException("struct not defined for return type [" + whitelistMethod.painlessReturnTypeName + "] " + throw new IllegalArgumentException("struct not defined for return type [" + whitelistMethod.painlessReturnTypeName + "] " +
"with owner struct [" + ownerStructName + "] and method with name [" + whitelistMethod.javaMethodName + "] " + "with owner struct [" + ownerStructName + "] and method with name [" + whitelistMethod.javaMethodName + "] " +
"and parameters " + whitelistMethod.painlessParameterTypeNames, iae); "and parameters " + whitelistMethod.painlessParameterTypeNames, iae);
} }
if (javaMethod.getReturnType() != PainlessLookupUtility.painlessDefTypeToJavaObjectType(painlessReturnClass)) { if (javaMethod.getReturnType() != PainlessLookupUtility.typeToJavaType(painlessReturnClass)) {
throw new IllegalArgumentException("specified return type class [" + painlessReturnClass + "] " + throw new IllegalArgumentException("specified return type class [" + painlessReturnClass + "] " +
"does not match the return type class [" + javaMethod.getReturnType() + "] for the " + "does not match the return type class [" + javaMethod.getReturnType() + "] for the " +
"method with name [" + whitelistMethod.javaMethodName + "] " + "method with name [" + whitelistMethod.javaMethodName + "] " +
@ -471,7 +427,7 @@ public class PainlessLookupBuilder {
} }
private void addField(String ownerStructName, WhitelistField whitelistField) { private void addField(String ownerStructName, WhitelistField whitelistField) {
PainlessClassBuilder ownerStruct = javaClassesToPainlessClassBuilders.get(painlessClassNamesToJavaClasses.get(ownerStructName)); PainlessClassBuilder ownerStruct = classesToPainlessClasses.get(canonicalClassNamesToClasses.get(ownerStructName));
if (ownerStruct == null) { if (ownerStruct == null) {
throw new IllegalArgumentException("owner struct [" + ownerStructName + "] not defined for method with " + throw new IllegalArgumentException("owner struct [" + ownerStructName + "] not defined for method with " +
@ -495,7 +451,7 @@ public class PainlessLookupBuilder {
Class<?> painlessFieldClass; Class<?> painlessFieldClass;
try { try {
painlessFieldClass = painlessTypeNameToPainlessType(whitelistField.painlessFieldTypeName); painlessFieldClass = canonicalTypeNameToType(whitelistField.painlessFieldTypeName);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
throw new IllegalArgumentException("struct not defined for return type [" + whitelistField.painlessFieldTypeName + "] " + throw new IllegalArgumentException("struct not defined for return type [" + whitelistField.painlessFieldTypeName + "] " +
"with owner struct [" + ownerStructName + "] and field with name [" + whitelistField.javaFieldName + "]", iae); "with owner struct [" + ownerStructName + "] and field with name [" + whitelistField.javaFieldName + "]", iae);
@ -552,7 +508,7 @@ public class PainlessLookupBuilder {
} }
private void copyStruct(String struct, List<String> children) { private void copyStruct(String struct, List<String> children) {
final PainlessClassBuilder owner = javaClassesToPainlessClassBuilders.get(painlessClassNamesToJavaClasses.get(struct)); final PainlessClassBuilder owner = classesToPainlessClasses.get(canonicalClassNamesToClasses.get(struct));
if (owner == null) { if (owner == null) {
throw new IllegalArgumentException("Owner struct [" + struct + "] not defined for copy."); throw new IllegalArgumentException("Owner struct [" + struct + "] not defined for copy.");
@ -560,7 +516,7 @@ public class PainlessLookupBuilder {
for (int count = 0; count < children.size(); ++count) { for (int count = 0; count < children.size(); ++count) {
final PainlessClassBuilder child = final PainlessClassBuilder child =
javaClassesToPainlessClassBuilders.get(painlessClassNamesToJavaClasses.get(children.get(count))); classesToPainlessClasses.get(canonicalClassNamesToClasses.get(children.get(count)));
if (child == null) { if (child == null) {
throw new IllegalArgumentException("Child struct [" + children.get(count) + "]" + throw new IllegalArgumentException("Child struct [" + children.get(count) + "]" +
@ -734,7 +690,7 @@ public class PainlessLookupBuilder {
for (WhitelistClass whitelistStruct : whitelist.whitelistStructs) { for (WhitelistClass whitelistStruct : whitelist.whitelistStructs) {
String painlessTypeName = whitelistStruct.javaClassName.replace('$', '.'); String painlessTypeName = whitelistStruct.javaClassName.replace('$', '.');
PainlessClassBuilder painlessStruct = PainlessClassBuilder painlessStruct =
javaClassesToPainlessClassBuilders.get(painlessClassNamesToJavaClasses.get(painlessTypeName)); classesToPainlessClasses.get(canonicalClassNamesToClasses.get(painlessTypeName));
if (painlessStruct != null && painlessStruct.clazz.getName().equals(whitelistStruct.javaClassName) == false) { if (painlessStruct != null && painlessStruct.clazz.getName().equals(whitelistStruct.javaClassName) == false) {
throw new IllegalArgumentException("struct [" + painlessStruct.name + "] cannot represent multiple classes " + throw new IllegalArgumentException("struct [" + painlessStruct.name + "] cannot represent multiple classes " +
@ -745,8 +701,8 @@ public class PainlessLookupBuilder {
addPainlessClass( addPainlessClass(
whitelist.javaClassLoader, whitelistStruct.javaClassName, whitelistStruct.onlyFQNJavaClassName == false); whitelist.javaClassLoader, whitelistStruct.javaClassName, whitelistStruct.onlyFQNJavaClassName == false);
painlessStruct = javaClassesToPainlessClassBuilders.get(painlessClassNamesToJavaClasses.get(painlessTypeName)); painlessStruct = classesToPainlessClasses.get(canonicalClassNamesToClasses.get(painlessTypeName));
javaClassesToPainlessClassBuilders.put(painlessStruct.clazz, painlessStruct); classesToPainlessClasses.put(painlessStruct.clazz, painlessStruct);
} }
} }
@ -779,8 +735,8 @@ public class PainlessLookupBuilder {
// goes through each Painless struct and determines the inheritance list, // goes through each Painless struct and determines the inheritance list,
// and then adds all inherited types to the Painless struct's whitelist // and then adds all inherited types to the Painless struct's whitelist
for (Class<?> javaClass : javaClassesToPainlessClassBuilders.keySet()) { for (Class<?> javaClass : classesToPainlessClasses.keySet()) {
PainlessClassBuilder painlessStruct = javaClassesToPainlessClassBuilders.get(javaClass); PainlessClassBuilder painlessStruct = classesToPainlessClasses.get(javaClass);
List<String> painlessSuperStructs = new ArrayList<>(); List<String> painlessSuperStructs = new ArrayList<>();
Class<?> javaSuperClass = painlessStruct.clazz.getSuperclass(); Class<?> javaSuperClass = painlessStruct.clazz.getSuperclass();
@ -791,7 +747,7 @@ public class PainlessLookupBuilder {
// adds super classes to the inheritance list // adds super classes to the inheritance list
if (javaSuperClass != null && javaSuperClass.isInterface() == false) { if (javaSuperClass != null && javaSuperClass.isInterface() == false) {
while (javaSuperClass != null) { while (javaSuperClass != null) {
PainlessClassBuilder painlessSuperStruct = javaClassesToPainlessClassBuilders.get(javaSuperClass); PainlessClassBuilder painlessSuperStruct = classesToPainlessClasses.get(javaSuperClass);
if (painlessSuperStruct != null) { if (painlessSuperStruct != null) {
painlessSuperStructs.add(painlessSuperStruct.name); painlessSuperStructs.add(painlessSuperStruct.name);
@ -807,7 +763,7 @@ public class PainlessLookupBuilder {
Class<?> javaInterfaceLookup = javaInteraceLookups.pop(); Class<?> javaInterfaceLookup = javaInteraceLookups.pop();
for (Class<?> javaSuperInterface : javaInterfaceLookup.getInterfaces()) { for (Class<?> javaSuperInterface : javaInterfaceLookup.getInterfaces()) {
PainlessClassBuilder painlessInterfaceStruct = javaClassesToPainlessClassBuilders.get(javaSuperInterface); PainlessClassBuilder painlessInterfaceStruct = classesToPainlessClasses.get(javaSuperInterface);
if (painlessInterfaceStruct != null) { if (painlessInterfaceStruct != null) {
String painlessInterfaceStructName = painlessInterfaceStruct.name; String painlessInterfaceStructName = painlessInterfaceStruct.name;
@ -828,7 +784,7 @@ public class PainlessLookupBuilder {
// copies methods and fields from Object into interface types // copies methods and fields from Object into interface types
if (painlessStruct.clazz.isInterface() || (def.class.getSimpleName()).equals(painlessStruct.name)) { if (painlessStruct.clazz.isInterface() || (def.class.getSimpleName()).equals(painlessStruct.name)) {
PainlessClassBuilder painlessObjectStruct = javaClassesToPainlessClassBuilders.get(Object.class); PainlessClassBuilder painlessObjectStruct = classesToPainlessClasses.get(Object.class);
if (painlessObjectStruct != null) { if (painlessObjectStruct != null) {
copyStruct(painlessStruct.name, Collections.singletonList(painlessObjectStruct.name)); copyStruct(painlessStruct.name, Collections.singletonList(painlessObjectStruct.name));
@ -837,18 +793,18 @@ public class PainlessLookupBuilder {
} }
// precompute runtime classes // precompute runtime classes
for (PainlessClassBuilder painlessStruct : javaClassesToPainlessClassBuilders.values()) { for (PainlessClassBuilder painlessStruct : classesToPainlessClasses.values()) {
addRuntimeClass(painlessStruct); addRuntimeClass(painlessStruct);
} }
Map<Class<?>, PainlessClass> javaClassesToPainlessClasses = new HashMap<>(); Map<Class<?>, PainlessClass> javaClassesToPainlessClasses = new HashMap<>();
// copy all structs to make them unmodifiable for outside users: // copy all structs to make them unmodifiable for outside users:
for (Map.Entry<Class<?>,PainlessClassBuilder> entry : javaClassesToPainlessClassBuilders.entrySet()) { for (Map.Entry<Class<?>,PainlessClassBuilder> entry : classesToPainlessClasses.entrySet()) {
entry.getValue().functionalMethod = computeFunctionalInterfaceMethod(entry.getValue()); entry.getValue().functionalMethod = computeFunctionalInterfaceMethod(entry.getValue());
javaClassesToPainlessClasses.put(entry.getKey(), entry.getValue().build()); javaClassesToPainlessClasses.put(entry.getKey(), entry.getValue().build());
} }
return new PainlessLookup(painlessClassNamesToJavaClasses, javaClassesToPainlessClasses); return new PainlessLookup(canonicalClassNamesToClasses, javaClassesToPainlessClasses);
} }
} }

View File

@ -19,35 +19,177 @@
package org.elasticsearch.painless.lookup; package org.elasticsearch.painless.lookup;
import org.objectweb.asm.Type;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* This class contains methods shared by {@link PainlessLookupBuilder}, {@link PainlessLookup}, and other classes within * PainlessLookupUtility contains methods shared by {@link PainlessLookupBuilder}, {@link PainlessLookup}, and other classes within
* Painless for conversion between type names and types along with some other various utility methods. * Painless for conversion between type names and types along with some other various utility methods.
* *
* The following terminology is used for variable names throughout the lookup package: * The following terminology is used for variable names throughout the lookup package:
* *
* - javaClass (Class) - a java class including def and excluding array type java classes * A class is a set of methods and fields under a specific class name. A type is either a class or an array under a specific type name.
* - javaClassName (String) - the fully qualified java class name for a javaClass * Note the distinction between class versus type is class means that no array classes will be be represented whereas type allows array
* - painlessClassName (String) - the fully qualified painless name or imported painless name for a painlessClass * classes to be represented. The set of available classes will always be a subset of the available types.
* - anyClassName (String) - either a javaClassName or a painlessClassName
* - javaType (Class) - a java class excluding def and array type java classes
* - painlessType (Class) - a java class including def and array type java classes
* - javaTypeName (String) - the fully qualified java Type name for a javaType
* - painlessTypeName (String) - the fully qualified painless name or imported painless name for a painlessType
* - anyTypeName (String) - either a javaTypeName or a painlessTypeName
* - painlessClass (PainlessClass) - a painless class object
* *
* Under ambiguous circumstances most variable names are prefixed with asm, java, or painless. * Under ambiguous circumstances most variable names are prefixed with asm, java, or painless. If the variable value is the same for asm,
* If the variable name is the same for asm, java, and painless, no prefix is used. * java, and painless, no prefix is used.
*
* <ul>
* <li> - javaClassName (String) - the fully qualified java class name where '$' tokens represent inner classes excluding
* def and array types </li>
*
* <li> - javaClass (Class) - a java class excluding def and array types </li>
*
* <li> - javaType (Class) - a java class excluding def and including array types </li>
*
* <li> - importedClassName (String) - the imported painless class name where the java canonical class name is used without
* the package qualifier
*
* <li> - canonicalClassName (String) - the fully qualified painless class name equivalent to the fully
* qualified java canonical class name or imported painless class name for a class
* including def and excluding array types where '.' tokens represent inner classes <li>
*
* <li> - canonicalTypeName (String) - the fully qualified painless type name equivalent to the fully
* qualified java canonical type name or imported painless type name for a type
* including def where '.' tokens represent inner classes and each set of '[]' tokens
* at the end of the type name represent a single dimension for an array type <li>
*
* <li> - class/clazz (Class) - a painless class represented by a java class including def and excluding array
* types </li>
*
* <li> - type (Class) - a painless type represented by a java class including def and array types </li>
*
* <li> - painlessClass (PainlessClass) - a painless class object </li>
*
* <li> - painlessMethod (PainlessMethod) - a painless method object </li>
*
* <li> - painlessField (PainlessField) - a painless field object </li>
* </ul>
*/ */
public final class PainlessLookupUtility { public final class PainlessLookupUtility {
public static Class<?> javaObjectTypeToPainlessDefType(Class<?> javaType) { /**
* Converts a canonical type name to a type based on the terminology specified as part of the documentation for
* {@link PainlessLookupUtility}. Since canonical class names are a subset of canonical type names, this method will
* safely convert a canonical class name to a class as well.
*/
public static Class<?> canonicalTypeNameToType(String canonicalTypeName, Map<String, Class<?>> canonicalClassNamesToClasses) {
Objects.requireNonNull(canonicalTypeName);
Objects.requireNonNull(canonicalClassNamesToClasses);
Class<?> type = canonicalClassNamesToClasses.get(canonicalTypeName);
if (type != null) {
return type;
}
int arrayDimensions = 0;
int arrayIndex = canonicalTypeName.indexOf('[');
if (arrayIndex != -1) {
int typeNameLength = canonicalTypeName.length();
while (arrayIndex < typeNameLength) {
if (canonicalTypeName.charAt(arrayIndex) == '[' &&
++arrayIndex < typeNameLength &&
canonicalTypeName.charAt(arrayIndex++) == ']') {
++arrayDimensions;
} else {
throw new IllegalArgumentException("type [" + canonicalTypeName + "] not found");
}
}
canonicalTypeName = canonicalTypeName.substring(0, canonicalTypeName.indexOf('['));
type = canonicalClassNamesToClasses.get(canonicalTypeName);
char arrayBraces[] = new char[arrayDimensions];
Arrays.fill(arrayBraces, '[');
String javaTypeName = new String(arrayBraces);
if (type == boolean.class) {
javaTypeName += "Z";
} else if (type == byte.class) {
javaTypeName += "B";
} else if (type == short.class) {
javaTypeName += "S";
} else if (type == char.class) {
javaTypeName += "C";
} else if (type == int.class) {
javaTypeName += "I";
} else if (type == long.class) {
javaTypeName += "J";
} else if (type == float.class) {
javaTypeName += "F";
} else if (type == double.class) {
javaTypeName += "D";
} else {
javaTypeName += "L" + type.getName() + ";";
}
try {
return Class.forName(javaTypeName);
} catch (ClassNotFoundException cnfe) {
throw new IllegalArgumentException("type [" + canonicalTypeName + "] not found", cnfe);
}
}
throw new IllegalArgumentException("type [" + canonicalTypeName + "] not found");
}
/**
* Converts a type to a canonical type name based on the terminology specified as part of the documentation for
* {@link PainlessLookupUtility}. Since classes are a subset of types, this method will safely convert a class
* to a canonical class name as well.
*/
public static String typeToCanonicalTypeName(Class<?> type) {
Objects.requireNonNull(type);
String canonicalTypeName = type.getCanonicalName();
if (canonicalTypeName.startsWith(def.class.getName())) {
canonicalTypeName = canonicalTypeName.replace(def.class.getName(), DEF_TYPE_NAME);
}
return canonicalTypeName;
}
/**
* Converts a list of types to a list of canonical type names as a string based on the terminology specified as part of the
* documentation for {@link PainlessLookupUtility}. Since classes are a subset of types, this method will safely convert a list
* of classes or a mixed list of classes and types to a list of canonical type names as a string as well.
*/
public static String typesToCanonicalTypeNames(List<Class<?>> types) {
StringBuilder typesStringBuilder = new StringBuilder("[");
int anyTypesSize = types.size();
int anyTypesIndex = 0;
for (Class<?> painlessType : types) {
String canonicalTypeName = typeToCanonicalTypeName(painlessType);
typesStringBuilder.append(canonicalTypeName);
if (++anyTypesIndex < anyTypesSize) {
typesStringBuilder.append(",");
}
}
typesStringBuilder.append("]");
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
* identity function.
*/
public static Class<?> javaTypeToType(Class<?> javaType) {
Objects.requireNonNull(javaType);
if (javaType.isArray()) { if (javaType.isArray()) {
Class<?> javaTypeComponent = javaType.getComponentType(); Class<?> javaTypeComponent = javaType.getComponentType();
int arrayDimensions = 1; int arrayDimensions = 1;
@ -58,14 +200,11 @@ public final class PainlessLookupUtility {
} }
if (javaTypeComponent == Object.class) { if (javaTypeComponent == Object.class) {
char[] asmDescriptorBraces = new char[arrayDimensions]; char[] arrayBraces = new char[arrayDimensions];
Arrays.fill(asmDescriptorBraces, '['); Arrays.fill(arrayBraces, '[');
String asmDescriptor = new String(asmDescriptorBraces) + Type.getType(def.class).getDescriptor();
Type asmType = Type.getType(asmDescriptor);
try { try {
return Class.forName(asmType.getInternalName().replace('/', '.')); return Class.forName(new String(arrayBraces) + "L" + def.class.getName() + ";");
} catch (ClassNotFoundException cnfe) { } catch (ClassNotFoundException cnfe) {
throw new IllegalStateException("internal error", cnfe); throw new IllegalStateException("internal error", cnfe);
} }
@ -77,206 +216,147 @@ public final class PainlessLookupUtility {
return javaType; return javaType;
} }
public static Class<?> painlessDefTypeToJavaObjectType(Class<?> painlessType) { /**
if (painlessType.isArray()) { * Converts a type to a java type based on the terminology specified as part of {@link PainlessLookupUtility} where if a type is a
Class<?> painlessTypeComponent = painlessType.getComponentType(); * def class or def array, the returned type will be the equivalent object class or object array. Otherwise, this behaves as an
* identity function.
*/
public static Class<?> typeToJavaType(Class<?> type) {
Objects.requireNonNull(type);
if (type.isArray()) {
Class<?> typeComponent = type.getComponentType();
int arrayDimensions = 1; int arrayDimensions = 1;
while (painlessTypeComponent.isArray()) { while (typeComponent.isArray()) {
painlessTypeComponent = painlessTypeComponent.getComponentType(); typeComponent = typeComponent.getComponentType();
++arrayDimensions; ++arrayDimensions;
} }
if (painlessTypeComponent == def.class) { if (typeComponent == def.class) {
char[] asmDescriptorBraces = new char[arrayDimensions]; char[] arrayBraces = new char[arrayDimensions];
Arrays.fill(asmDescriptorBraces, '['); Arrays.fill(arrayBraces, '[');
String asmDescriptor = new String(asmDescriptorBraces) + Type.getType(Object.class).getDescriptor();
Type asmType = Type.getType(asmDescriptor);
try { try {
return Class.forName(asmType.getInternalName().replace('/', '.')); return Class.forName(new String(arrayBraces) + "L" + Object.class.getName() + ";");
} catch (ClassNotFoundException exception) { } catch (ClassNotFoundException cnfe) {
throw new IllegalStateException("internal error", exception); throw new IllegalStateException("internal error", cnfe);
} }
} }
} else if (painlessType == def.class) { } else if (type == def.class) {
return Object.class; return Object.class;
} }
return painlessType; return type;
} }
public static String anyTypeNameToPainlessTypeName(String anyTypeName) { /**
return anyTypeName.replace(def.class.getName(), DEF_PAINLESS_CLASS_NAME).replace('$', '.'); * Ensures a type exists based on the terminology specified as part of {@link PainlessLookupUtility}. Throws an
} * {@link IllegalArgumentException} if the type does not exist.
*/
public static void validateType(Class<?> type, Collection<Class<?>> classes) {
String canonicalTypeName = typeToCanonicalTypeName(type);
public static String anyTypeToPainlessTypeName(Class<?> anyType) { while (type.getComponentType() != null) {
if (anyType.isLocalClass() || anyType.isAnonymousClass()) { type = type.getComponentType();
return null;
} else if (anyType.isArray()) {
Class<?> anyTypeComponent = anyType.getComponentType();
int arrayDimensions = 1;
while (anyTypeComponent.isArray()) {
anyTypeComponent = anyTypeComponent.getComponentType();
++arrayDimensions;
}
if (anyTypeComponent == def.class) {
StringBuilder painlessDefTypeNameArrayBuilder = new StringBuilder(DEF_PAINLESS_CLASS_NAME);
for (int dimension = 0; dimension < arrayDimensions; dimension++) {
painlessDefTypeNameArrayBuilder.append("[]");
}
return painlessDefTypeNameArrayBuilder.toString();
}
} else if (anyType == def.class) {
return DEF_PAINLESS_CLASS_NAME;
} }
return anyType.getCanonicalName().replace('$', '.'); if (classes.contains(type) == false) {
} throw new IllegalArgumentException("type [" + canonicalTypeName + "] not found");
public static Class<?> painlessTypeNameToPainlessType(String painlessTypeName, Map<String, Class<?>> painlessClassNamesToJavaClasses) {
Class<?> javaClass = painlessClassNamesToJavaClasses.get(painlessTypeName);
if (javaClass != null) {
return javaClass;
}
int arrayDimensions = 0;
int arrayIndex = painlessTypeName.indexOf('[');
if (arrayIndex != -1) {
int painlessTypeNameLength = painlessTypeName.length();
while (arrayIndex < painlessTypeNameLength) {
if (painlessTypeName.charAt(arrayIndex) == '[' &&
++arrayIndex < painlessTypeNameLength &&
painlessTypeName.charAt(arrayIndex++) == ']') {
++arrayDimensions;
} else {
throw new IllegalArgumentException("painless type [" + painlessTypeName + "] not found");
}
}
painlessTypeName = painlessTypeName.substring(0, painlessTypeName.indexOf('['));
javaClass = painlessClassNamesToJavaClasses.get(painlessTypeName);
char javaDescriptorBraces[] = new char[arrayDimensions];
Arrays.fill(javaDescriptorBraces, '[');
String javaDescriptor = new String(javaDescriptorBraces);
if (javaClass == boolean.class) {
javaDescriptor += "Z";
} else if (javaClass == byte.class) {
javaDescriptor += "B";
} else if (javaClass == short.class) {
javaDescriptor += "S";
} else if (javaClass == char.class) {
javaDescriptor += "C";
} else if (javaClass == int.class) {
javaDescriptor += "I";
} else if (javaClass == long.class) {
javaDescriptor += "J";
} else if (javaClass == float.class) {
javaDescriptor += "F";
} else if (javaClass == double.class) {
javaDescriptor += "D";
} else {
javaDescriptor += "L" + javaClass.getName() + ";";
}
try {
return Class.forName(javaDescriptor);
} catch (ClassNotFoundException cnfe) {
throw new IllegalArgumentException("painless type [" + painlessTypeName + "] not found", cnfe);
}
}
throw new IllegalArgumentException("painless type [" + painlessTypeName + "] not found");
}
public static void validatePainlessType(Class<?> painlessType, Collection<Class<?>> javaClasses) {
String painlessTypeName = anyTypeNameToPainlessTypeName(painlessType.getName());
while (painlessType.getComponentType() != null) {
painlessType = painlessType.getComponentType();
}
if (javaClasses.contains(painlessType) == false) {
throw new IllegalArgumentException("painless type [" + painlessTypeName + "] not found");
} }
} }
/**
* Converts a type to its boxed type equivalent if one exists based on the terminology specified as part of
* {@link PainlessLookupUtility}. Otherwise, this behaves as an identity function.
*/
public static Class<?> typeToBoxedType(Class<?> type) {
if (type == boolean.class) {
return Boolean.class;
} else if (type == byte.class) {
return Byte.class;
} else if (type == short.class) {
return Short.class;
} else if (type == char.class) {
return Character.class;
} else if (type == int.class) {
return Integer.class;
} else if (type == long.class) {
return Long.class;
} else if (type == float.class) {
return Float.class;
} else if (type == double.class) {
return Double.class;
}
return type;
}
/**
* Converts a type to its unboxed type equivalent if one exists based on the terminology specified as part of
* {@link PainlessLookupUtility}. Otherwise, this behaves as an identity function.
*/
public static Class<?> typeToUnboxedType(Class<?> type) {
if (type == Boolean.class) {
return boolean.class;
} else if (type == Byte.class) {
return byte.class;
} else if (type == Short.class) {
return short.class;
} else if (type == Character.class) {
return char.class;
} else if (type == Integer.class) {
return int.class;
} else if (type == Long.class) {
return long.class;
} else if (type == Float.class) {
return float.class;
} else if (type == Double.class) {
return double.class;
}
return type;
}
/**
* Checks if a type based on the terminology specified as part of {@link PainlessLookupUtility} is available as a constant type
* where {@code true} is returned if the type is a constant type and {@code false} otherwise.
*/
public static boolean isConstantType(Class<?> type) {
return type == boolean.class ||
type == byte.class ||
type == short.class ||
type == char.class ||
type == int.class ||
type == long.class ||
type == float.class ||
type == double.class ||
type == String.class;
}
/**
* Constructs a painless method key used to lookup painless methods from a painless class.
*/
public static String buildPainlessMethodKey(String methodName, int methodArity) { public static String buildPainlessMethodKey(String methodName, int methodArity) {
return methodName + "/" + methodArity; return methodName + "/" + methodArity;
} }
/**
* Constructs a painless field key used to lookup painless fields from a painless class.
*/
public static String buildPainlessFieldKey(String fieldName) { public static String buildPainlessFieldKey(String fieldName) {
return fieldName; return fieldName;
} }
public static Class<?> getBoxedAnyType(Class<?> anyType) { /**
if (anyType == boolean.class) { * The def type name as specified in the source for a script.
return Boolean.class; */
} else if (anyType == byte.class) { public static final String DEF_TYPE_NAME = "def";
return Byte.class;
} else if (anyType == short.class) {
return Short.class;
} else if (anyType == char.class) {
return Character.class;
} else if (anyType == int.class) {
return Integer.class;
} else if (anyType == long.class) {
return Long.class;
} else if (anyType == float.class) {
return Float.class;
} else if (anyType == double.class) {
return Double.class;
}
return anyType; /**
} * The method name for all constructors.
*/
public static Class<?> getUnboxedAnyType(Class<?> anyType) { public static final String CONSTRUCTOR_NAME = "<init>";
if (anyType == Boolean.class) {
return boolean.class;
} else if (anyType == Byte.class) {
return byte.class;
} else if (anyType == Short.class) {
return short.class;
} else if (anyType == Character.class) {
return char.class;
} else if (anyType == Integer.class) {
return int.class;
} else if (anyType == Long.class) {
return long.class;
} else if (anyType == Float.class) {
return float.class;
} else if (anyType == Double.class) {
return double.class;
}
return anyType;
}
public static boolean isAnyTypeConstant(Class<?> anyType) {
return anyType == boolean.class ||
anyType == byte.class ||
anyType == short.class ||
anyType == char.class ||
anyType == int.class ||
anyType == long.class ||
anyType == float.class ||
anyType == double.class ||
anyType == String.class;
}
public static final String DEF_PAINLESS_CLASS_NAME = def.class.getSimpleName();
public static final String CONSTRUCTOR_ANY_NAME = "<init>";
private PainlessLookupUtility() { private PainlessLookupUtility() {

View File

@ -70,21 +70,21 @@ public class PainlessMethod {
params = new Class<?>[1 + arguments.size()]; params = new Class<?>[1 + arguments.size()];
params[0] = augmentation; params[0] = augmentation;
for (int i = 0; i < arguments.size(); i++) { for (int i = 0; i < arguments.size(); i++) {
params[i + 1] = PainlessLookupUtility.painlessDefTypeToJavaObjectType(arguments.get(i)); params[i + 1] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
} }
returnValue = PainlessLookupUtility.painlessDefTypeToJavaObjectType(rtn); returnValue = PainlessLookupUtility.typeToJavaType(rtn);
} else if (Modifier.isStatic(modifiers)) { } else if (Modifier.isStatic(modifiers)) {
// static method: straightforward copy // static method: straightforward copy
params = new Class<?>[arguments.size()]; params = new Class<?>[arguments.size()];
for (int i = 0; i < arguments.size(); i++) { for (int i = 0; i < arguments.size(); i++) {
params[i] = PainlessLookupUtility.painlessDefTypeToJavaObjectType(arguments.get(i)); params[i] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
} }
returnValue = PainlessLookupUtility.painlessDefTypeToJavaObjectType(rtn); returnValue = PainlessLookupUtility.typeToJavaType(rtn);
} else if ("<init>".equals(name)) { } else if ("<init>".equals(name)) {
// constructor: returns the owner class // constructor: returns the owner class
params = new Class<?>[arguments.size()]; params = new Class<?>[arguments.size()];
for (int i = 0; i < arguments.size(); i++) { for (int i = 0; i < arguments.size(); i++) {
params[i] = PainlessLookupUtility.painlessDefTypeToJavaObjectType(arguments.get(i)); params[i] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
} }
returnValue = target; returnValue = target;
} else { } else {
@ -92,9 +92,9 @@ public class PainlessMethod {
params = new Class<?>[1 + arguments.size()]; params = new Class<?>[1 + arguments.size()];
params[0] = target; params[0] = target;
for (int i = 0; i < arguments.size(); i++) { for (int i = 0; i < arguments.size(); i++) {
params[i + 1] = PainlessLookupUtility.painlessDefTypeToJavaObjectType(arguments.get(i)); params[i + 1] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
} }
returnValue = PainlessLookupUtility.painlessDefTypeToJavaObjectType(rtn); returnValue = PainlessLookupUtility.typeToJavaType(rtn);
} }
return MethodType.methodType(returnValue, params); return MethodType.methodType(returnValue, params);
} }

View File

@ -157,7 +157,7 @@ public abstract class AExpression extends ANode {
return ecast; return ecast;
} else { } else {
if (PainlessLookupUtility.isAnyTypeConstant(expected)) { if (PainlessLookupUtility.isConstantType(expected)) {
// For the case where a cast is required, a constant is set, // For the case where a cast is required, a constant is set,
// and the constant can be immediately cast to the expected type. // and the constant can be immediately cast to the expected type.
// An EConstant replaces this node with the constant cast appropriately // An EConstant replaces this node with the constant cast appropriately

View File

@ -106,8 +106,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply multiply [*] to types " + throw createError(new ClassCastException("Cannot apply multiply [*] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;
@ -149,8 +149,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply divide [/] to types " + throw createError(new ClassCastException("Cannot apply divide [/] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;
@ -197,8 +197,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply remainder [%] to types " + throw createError(new ClassCastException("Cannot apply remainder [%] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;
@ -245,8 +245,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply add [+] to types " + throw createError(new ClassCastException("Cannot apply add [+] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;
@ -304,8 +304,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply subtract [-] to types " + throw createError(new ClassCastException("Cannot apply subtract [-] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;
@ -363,8 +363,8 @@ public final class EBinary extends AExpression {
if (lhspromote == null || rhspromote == null) { if (lhspromote == null || rhspromote == null) {
throw createError(new ClassCastException("Cannot apply left shift [<<] to types " + throw createError(new ClassCastException("Cannot apply left shift [<<] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote = lhspromote; actual = promote = lhspromote;
@ -411,8 +411,8 @@ public final class EBinary extends AExpression {
if (lhspromote == null || rhspromote == null) { if (lhspromote == null || rhspromote == null) {
throw createError(new ClassCastException("Cannot apply right shift [>>] to types " + throw createError(new ClassCastException("Cannot apply right shift [>>] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote = lhspromote; actual = promote = lhspromote;
@ -462,8 +462,8 @@ public final class EBinary extends AExpression {
if (lhspromote == null || rhspromote == null) { if (lhspromote == null || rhspromote == null) {
throw createError(new ClassCastException("Cannot apply unsigned shift [>>>] to types " + throw createError(new ClassCastException("Cannot apply unsigned shift [>>>] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
if (lhspromote == def.class || rhspromote == def.class) { if (lhspromote == def.class || rhspromote == def.class) {
@ -506,8 +506,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply and [&] to types " + throw createError(new ClassCastException("Cannot apply and [&] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;
@ -546,8 +546,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply xor [^] to types " + throw createError(new ClassCastException("Cannot apply xor [^] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;
@ -587,8 +587,8 @@ public final class EBinary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply or [|] to types " + throw createError(new ClassCastException("Cannot apply or [|] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
actual = promote; actual = promote;

View File

@ -69,7 +69,7 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
defPointer = "D" + variable + "." + call + ",1"; defPointer = "D" + variable + "." + call + ",1";
} else { } else {
// typed implementation // typed implementation
defPointer = "S" + PainlessLookupUtility.anyTypeToPainlessTypeName(captured.clazz) + "." + call + ",1"; defPointer = "S" + PainlessLookupUtility.typeToCanonicalTypeName(captured.clazz) + "." + call + ",1";
} }
actual = String.class; actual = String.class;
} else { } else {
@ -77,8 +77,8 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
// static case // static case
if (captured.clazz != def.class) { if (captured.clazz != def.class) {
try { try {
ref = new FunctionRef( ref = new FunctionRef(locals.getPainlessLookup(), expected,
locals.getPainlessLookup(), expected, PainlessLookupUtility.anyTypeToPainlessTypeName(captured.clazz), call, 1); PainlessLookupUtility.typeToCanonicalTypeName(captured.clazz), call, 1);
// check casts between the interface method and the delegate method are legal // check casts between the interface method and the delegate method are legal
for (int i = 0; i < ref.interfaceMethod.arguments.size(); ++i) { for (int i = 0; i < ref.interfaceMethod.arguments.size(); ++i) {
@ -110,7 +110,7 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
// typed interface, dynamic implementation // typed interface, dynamic implementation
writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot()); writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());
Type methodType = Type.getMethodType(MethodWriter.getType(expected), MethodWriter.getType(captured.clazz)); Type methodType = Type.getMethodType(MethodWriter.getType(expected), MethodWriter.getType(captured.clazz));
writer.invokeDefCall(call, methodType, DefBootstrap.REFERENCE, PainlessLookupUtility.anyTypeToPainlessTypeName(expected)); writer.invokeDefCall(call, methodType, DefBootstrap.REFERENCE, PainlessLookupUtility.typeToCanonicalTypeName(expected));
} else { } else {
// typed interface, typed implementation // typed interface, typed implementation
writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot()); writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());

View File

@ -63,6 +63,6 @@ final class ECast extends AExpression {
@Override @Override
public String toString() { public String toString() {
return singleLineToString(PainlessLookupUtility.anyTypeToPainlessTypeName(cast.to), child); return singleLineToString(PainlessLookupUtility.typeToCanonicalTypeName(cast.to), child);
} }
} }

View File

@ -93,8 +93,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply equals [==] to types " + throw createError(new ClassCastException("Cannot apply equals [==] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
if (promotedType == def.class) { if (promotedType == def.class) {
@ -143,8 +143,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply reference equals [===] to types " + throw createError(new ClassCastException("Cannot apply reference equals [===] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
left.expected = promotedType; left.expected = promotedType;
@ -184,8 +184,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply not equals [!=] to types " + throw createError(new ClassCastException("Cannot apply not equals [!=] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
if (promotedType == def.class) { if (promotedType == def.class) {
@ -234,8 +234,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply reference not equals [!==] to types " + throw createError(new ClassCastException("Cannot apply reference not equals [!==] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
left.expected = promotedType; left.expected = promotedType;
@ -275,8 +275,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply greater than or equals [>=] to types " + throw createError(new ClassCastException("Cannot apply greater than or equals [>=] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
if (promotedType == def.class) { if (promotedType == def.class) {
@ -315,8 +315,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply greater than [>] to types " + throw createError(new ClassCastException("Cannot apply greater than [>] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
if (promotedType == def.class) { if (promotedType == def.class) {
@ -355,8 +355,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply less than or equals [<=] to types " + throw createError(new ClassCastException("Cannot apply less than or equals [<=] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
if (promotedType == def.class) { if (promotedType == def.class) {
@ -395,8 +395,8 @@ public final class EComp extends AExpression {
if (promotedType == null) { if (promotedType == null) {
throw createError(new ClassCastException("Cannot apply less than [>=] to types " + throw createError(new ClassCastException("Cannot apply less than [>=] to types " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(left.actual) + "] and " + "[" + PainlessLookupUtility.typeToCanonicalTypeName(left.actual) + "] and " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(right.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(right.actual) + "]."));
} }
if (promotedType == def.class) { if (promotedType == def.class) {

View File

@ -68,13 +68,13 @@ public final class EFunctionRef extends AExpression implements ILambda {
PainlessMethod interfaceMethod = locals.getPainlessLookup().getPainlessStructFromJavaClass(expected).functionalMethod; PainlessMethod interfaceMethod = locals.getPainlessLookup().getPainlessStructFromJavaClass(expected).functionalMethod;
if (interfaceMethod == null) { if (interfaceMethod == null) {
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " + throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
"to [" + PainlessLookupUtility.anyTypeToPainlessTypeName(expected) + "], not a functional interface"); "to [" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "], not a functional interface");
} }
PainlessMethod delegateMethod = PainlessMethod delegateMethod =
locals.getMethod(PainlessLookupUtility.buildPainlessMethodKey(call, interfaceMethod.arguments.size())); locals.getMethod(PainlessLookupUtility.buildPainlessMethodKey(call, interfaceMethod.arguments.size()));
if (delegateMethod == null) { if (delegateMethod == null) {
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " + throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
"to [" + PainlessLookupUtility.anyTypeToPainlessTypeName(expected) + "], function not found"); "to [" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "], function not found");
} }
ref = new FunctionRef(expected, interfaceMethod, delegateMethod, 0); ref = new FunctionRef(expected, interfaceMethod, delegateMethod, 0);

View File

@ -64,8 +64,8 @@ public final class EInstanceof extends AExpression {
} }
// map to wrapped type for primitive types // map to wrapped type for primitive types
resolvedType = clazz.isPrimitive() ? PainlessLookupUtility.getBoxedAnyType(clazz) : resolvedType = clazz.isPrimitive() ? PainlessLookupUtility.typeToBoxedType(clazz) :
PainlessLookupUtility.painlessDefTypeToJavaObjectType(clazz); PainlessLookupUtility.typeToJavaType(clazz);
// analyze and cast the expression // analyze and cast the expression
expression.analyze(locals); expression.analyze(locals);
@ -76,7 +76,7 @@ public final class EInstanceof extends AExpression {
primitiveExpression = expression.actual.isPrimitive(); primitiveExpression = expression.actual.isPrimitive();
// map to wrapped type for primitive types // map to wrapped type for primitive types
expressionType = expression.actual.isPrimitive() ? expressionType = expression.actual.isPrimitive() ?
PainlessLookupUtility.getBoxedAnyType(expression.actual) : PainlessLookupUtility.painlessDefTypeToJavaObjectType(clazz); PainlessLookupUtility.typeToBoxedType(expression.actual) : PainlessLookupUtility.typeToJavaType(clazz);
actual = boolean.class; actual = boolean.class;
} }

View File

@ -123,12 +123,12 @@ public final class ELambda extends AExpression implements ILambda {
interfaceMethod = locals.getPainlessLookup().getPainlessStructFromJavaClass(expected).functionalMethod; interfaceMethod = locals.getPainlessLookup().getPainlessStructFromJavaClass(expected).functionalMethod;
if (interfaceMethod == null) { if (interfaceMethod == null) {
throw createError(new IllegalArgumentException("Cannot pass lambda to " + throw createError(new IllegalArgumentException("Cannot pass lambda to " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(expected) + "], not a functional interface")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "], not a functional interface"));
} }
// check arity before we manipulate parameters // check arity before we manipulate parameters
if (interfaceMethod.arguments.size() != paramTypeStrs.size()) if (interfaceMethod.arguments.size() != paramTypeStrs.size())
throw new IllegalArgumentException("Incorrect number of parameters for [" + interfaceMethod.name + throw new IllegalArgumentException("Incorrect number of parameters for [" + interfaceMethod.name +
"] in [" + PainlessLookupUtility.anyTypeToPainlessTypeName(expected) + "]"); "] in [" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "]");
// for method invocation, its allowed to ignore the return value // for method invocation, its allowed to ignore the return value
if (interfaceMethod.rtn == void.class) { if (interfaceMethod.rtn == void.class) {
returnType = def.class; returnType = def.class;
@ -140,7 +140,7 @@ public final class ELambda extends AExpression implements ILambda {
for (int i = 0; i < paramTypeStrs.size(); i++) { for (int i = 0; i < paramTypeStrs.size(); i++) {
String paramType = paramTypeStrs.get(i); String paramType = paramTypeStrs.get(i);
if (paramType == null) { if (paramType == null) {
actualParamTypeStrs.add(PainlessLookupUtility.anyTypeToPainlessTypeName(interfaceMethod.arguments.get(i))); actualParamTypeStrs.add(PainlessLookupUtility.typeToCanonicalTypeName(interfaceMethod.arguments.get(i)));
} else { } else {
actualParamTypeStrs.add(paramType); actualParamTypeStrs.add(paramType);
} }
@ -162,14 +162,14 @@ public final class ELambda extends AExpression implements ILambda {
List<String> paramTypes = new ArrayList<>(captures.size() + actualParamTypeStrs.size()); List<String> paramTypes = new ArrayList<>(captures.size() + actualParamTypeStrs.size());
List<String> paramNames = new ArrayList<>(captures.size() + paramNameStrs.size()); List<String> paramNames = new ArrayList<>(captures.size() + paramNameStrs.size());
for (Variable var : captures) { for (Variable var : captures) {
paramTypes.add(PainlessLookupUtility.anyTypeToPainlessTypeName(var.clazz)); paramTypes.add(PainlessLookupUtility.typeToCanonicalTypeName(var.clazz));
paramNames.add(var.name); paramNames.add(var.name);
} }
paramTypes.addAll(actualParamTypeStrs); paramTypes.addAll(actualParamTypeStrs);
paramNames.addAll(paramNameStrs); paramNames.addAll(paramNameStrs);
// desugar lambda body into a synthetic method // desugar lambda body into a synthetic method
desugared = new SFunction(reserved, location, PainlessLookupUtility.anyTypeToPainlessTypeName(returnType), name, desugared = new SFunction(reserved, location, PainlessLookupUtility.typeToCanonicalTypeName(returnType), name,
paramTypes, paramNames, statements, true); paramTypes, paramNames, statements, true);
desugared.generateSignature(locals.getPainlessLookup()); desugared.generateSignature(locals.getPainlessLookup());
desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), returnType, desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), returnType,

View File

@ -53,7 +53,7 @@ public final class ENull extends AExpression {
if (expected != null) { if (expected != null) {
if (expected.isPrimitive()) { if (expected.isPrimitive()) {
throw createError(new IllegalArgumentException( throw createError(new IllegalArgumentException(
"Cannot cast null to a primitive type [" + PainlessLookupUtility.anyTypeToPainlessTypeName(expected) + "].")); "Cannot cast null to a primitive type [" + PainlessLookupUtility.typeToCanonicalTypeName(expected) + "]."));
} }
actual = expected; actual = expected;

View File

@ -94,7 +94,7 @@ public final class EUnary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply not [~] to type " + throw createError(new ClassCastException("Cannot apply not [~] to type " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(child.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(child.actual) + "]."));
} }
child.expected = promote; child.expected = promote;
@ -124,7 +124,7 @@ public final class EUnary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply positive [+] to type " + throw createError(new ClassCastException("Cannot apply positive [+] to type " +
"[" + PainlessLookupUtility.painlessDefTypeToJavaObjectType(child.actual) + "].")); "[" + PainlessLookupUtility.typeToJavaType(child.actual) + "]."));
} }
child.expected = promote; child.expected = promote;
@ -158,7 +158,7 @@ public final class EUnary extends AExpression {
if (promote == null) { if (promote == null) {
throw createError(new ClassCastException("Cannot apply negative [-] to type " + throw createError(new ClassCastException("Cannot apply negative [-] to type " +
"[" + PainlessLookupUtility.painlessDefTypeToJavaObjectType(child.actual) + "].")); "[" + PainlessLookupUtility.typeToJavaType(child.actual) + "]."));
} }
child.expected = promote; child.expected = promote;

View File

@ -68,7 +68,7 @@ public final class PBrace extends AStoreable {
sub = new PSubListShortcut(location, locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual), index); sub = new PSubListShortcut(location, locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual), index);
} else { } else {
throw createError(new IllegalArgumentException("Illegal array access on type " + throw createError(new IllegalArgumentException("Illegal array access on type " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(prefix.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual) + "]."));
} }
sub.write = write; sub.write = write;

View File

@ -73,7 +73,7 @@ public final class PCallInvoke extends AExpression {
PainlessClass struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual); PainlessClass struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(prefix.actual);
if (prefix.actual.isPrimitive()) { if (prefix.actual.isPrimitive()) {
struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(PainlessLookupUtility.getBoxedAnyType(prefix.actual)); struct = locals.getPainlessLookup().getPainlessStructFromJavaClass(PainlessLookupUtility.typeToBoxedType(prefix.actual));
} }
String methodKey = PainlessLookupUtility.buildPainlessMethodKey(name, arguments.size()); String methodKey = PainlessLookupUtility.buildPainlessMethodKey(name, arguments.size());

View File

@ -63,7 +63,7 @@ public final class PField extends AStoreable {
prefix = prefix.cast(locals); prefix = prefix.cast(locals);
if (prefix.actual.isArray()) { if (prefix.actual.isArray()) {
sub = new PSubArrayLength(location, PainlessLookupUtility.anyTypeToPainlessTypeName(prefix.actual), value); sub = new PSubArrayLength(location, PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual), value);
} else if (prefix.actual == def.class) { } else if (prefix.actual == def.class) {
sub = new PSubDefField(location, value); sub = new PSubDefField(location, value);
} else { } else {
@ -85,7 +85,8 @@ public final class PField extends AStoreable {
"set" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 1)); "set" + Character.toUpperCase(value.charAt(0)) + value.substring(1), 1));
if (getter != null || setter != null) { if (getter != null || setter != null) {
sub = new PSubShortcut(location, value, PainlessLookupUtility.anyTypeToPainlessTypeName(prefix.actual), getter, setter); sub = new PSubShortcut(
location, value, PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual), getter, setter);
} else { } else {
EConstant index = new EConstant(location, value); EConstant index = new EConstant(location, value);
index.analyze(locals); index.analyze(locals);
@ -103,7 +104,7 @@ public final class PField extends AStoreable {
if (sub == null) { if (sub == null) {
throw createError(new IllegalArgumentException( throw createError(new IllegalArgumentException(
"Unknown field [" + value + "] for type [" + PainlessLookupUtility.anyTypeToPainlessTypeName(prefix.actual) + "].")); "Unknown field [" + value + "] for type [" + PainlessLookupUtility.typeToCanonicalTypeName(prefix.actual) + "]."));
} }
if (nullSafe) { if (nullSafe) {

View File

@ -53,7 +53,7 @@ final class PSubField extends AStoreable {
void analyze(Locals locals) { void analyze(Locals locals) {
if (write && Modifier.isFinal(field.modifiers)) { if (write && Modifier.isFinal(field.modifiers)) {
throw createError(new IllegalArgumentException("Cannot write to read-only field [" + field.name + "] for type " + throw createError(new IllegalArgumentException("Cannot write to read-only field [" + field.name + "] for type " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(field.clazz) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(field.clazz) + "]."));
} }
actual = field.clazz; actual = field.clazz;

View File

@ -85,7 +85,7 @@ public class SEach extends AStatement {
sub = new SSubEachIterable(location, variable, expression, block); sub = new SSubEachIterable(location, variable, expression, block);
} else { } else {
throw createError(new IllegalArgumentException("Illegal for each type " + throw createError(new IllegalArgumentException("Illegal for each type " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(expression.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(expression.actual) + "]."));
} }
sub.analyze(locals); sub.analyze(locals);

View File

@ -136,7 +136,7 @@ public final class SFunction extends AStatement {
try { try {
Class<?> paramType = painlessLookup.getJavaClassFromPainlessType(this.paramTypeStrs.get(param)); Class<?> paramType = painlessLookup.getJavaClassFromPainlessType(this.paramTypeStrs.get(param));
paramClasses[param] = PainlessLookupUtility.painlessDefTypeToJavaObjectType(paramType); paramClasses[param] = PainlessLookupUtility.typeToJavaType(paramType);
paramTypes.add(paramType); paramTypes.add(paramType);
parameters.add(new Parameter(location, paramNameStrs.get(param), paramType)); parameters.add(new Parameter(location, paramNameStrs.get(param), paramType));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
@ -146,7 +146,7 @@ public final class SFunction extends AStatement {
} }
org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(name, MethodType.methodType( org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(name, MethodType.methodType(
PainlessLookupUtility.painlessDefTypeToJavaObjectType(rtnType), paramClasses).toMethodDescriptorString()); PainlessLookupUtility.typeToJavaType(rtnType), paramClasses).toMethodDescriptorString());
this.method = new PainlessMethod(name, null, null, rtnType, paramTypes, method, Modifier.STATIC | Modifier.PRIVATE, null); this.method = new PainlessMethod(name, null, null, rtnType, paramTypes, method, Modifier.STATIC | Modifier.PRIVATE, null);
} }

View File

@ -109,6 +109,6 @@ final class SSubEachArray extends AStatement {
@Override @Override
public String toString() { public String toString() {
return singleLineToString(PainlessLookupUtility.anyTypeToPainlessTypeName(variable.clazz), variable.name, expression, block); return singleLineToString(PainlessLookupUtility.typeToCanonicalTypeName(variable.clazz), variable.name, expression, block);
} }
} }

View File

@ -81,7 +81,7 @@ final class SSubEachIterable extends AStatement {
if (method == null) { if (method == null) {
throw createError(new IllegalArgumentException("Unable to create iterator for the type " + throw createError(new IllegalArgumentException("Unable to create iterator for the type " +
"[" + PainlessLookupUtility.anyTypeToPainlessTypeName(expression.actual) + "].")); "[" + PainlessLookupUtility.typeToCanonicalTypeName(expression.actual) + "]."));
} }
} }
@ -132,6 +132,6 @@ final class SSubEachIterable extends AStatement {
@Override @Override
public String toString() { public String toString() {
return singleLineToString(PainlessLookupUtility.anyTypeToPainlessTypeName(variable.clazz), variable.name, expression, block); return singleLineToString(PainlessLookupUtility.typeToCanonicalTypeName(variable.clazz), variable.name, expression, block);
} }
} }

View File

@ -210,7 +210,7 @@ public class PainlessDocGenerator {
*/ */
private static void emitAnchor(PrintStream stream, Class<?> clazz) { private static void emitAnchor(PrintStream stream, Class<?> clazz) {
stream.print("painless-api-reference-"); stream.print("painless-api-reference-");
stream.print(PainlessLookupUtility.anyTypeToPainlessTypeName(clazz).replace('.', '-')); stream.print(PainlessLookupUtility.typeToCanonicalTypeName(clazz).replace('.', '-'));
} }
/** /**
@ -234,7 +234,7 @@ public class PainlessDocGenerator {
} }
private static String methodName(PainlessMethod method) { private static String methodName(PainlessMethod method) {
return method.name.equals("<init>") ? PainlessLookupUtility.anyTypeToPainlessTypeName(method.target) : method.name; return method.name.equals("<init>") ? PainlessLookupUtility.typeToCanonicalTypeName(method.target) : method.name;
} }
/** /**

View File

@ -156,16 +156,6 @@ if (isEclipse) {
compileJava.options.compilerArgs << "-Xlint:-cast,-deprecation,-rawtypes,-try,-unchecked" compileJava.options.compilerArgs << "-Xlint:-cast,-deprecation,-rawtypes,-try,-unchecked"
compileTestJava.options.compilerArgs << "-Xlint:-cast,-deprecation,-rawtypes,-try,-unchecked" compileTestJava.options.compilerArgs << "-Xlint:-cast,-deprecation,-rawtypes,-try,-unchecked"
// TODO: remove ScriptDocValuesMissingV6BehaviourTests in 7.0
additionalTest('testScriptDocValuesMissingV6Behaviour'){
include '**/ScriptDocValuesMissingV6BehaviourTests.class'
systemProperty 'es.scripting.exception_for_missing_value', 'false'
}
test {
// these are tested explicitly in separate test tasks
exclude '**/*ScriptDocValuesMissingV6BehaviourTests.class'
}
forbiddenPatterns { forbiddenPatterns {
exclude '**/*.json' exclude '**/*.json'
exclude '**/*.jmx' exclude '**/*.jmx'

View File

@ -29,7 +29,6 @@ import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.logging.DeprecationLogger; import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.script.ScriptModule;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import org.joda.time.MutableDateTime; import org.joda.time.MutableDateTime;
@ -126,11 +125,8 @@ public abstract class ScriptDocValues<T> extends AbstractList<T> {
public long getValue() { public long getValue() {
if (count == 0) { if (count == 0) {
if (ScriptModule.EXCEPTION_FOR_MISSING_VALUE) { throw new IllegalStateException("A document doesn't have a value for a field! " +
throw new IllegalStateException("A document doesn't have a value for a field! " + "Use doc[<field>].size()==0 to check if a document is missing a field!");
"Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return 0L;
} }
return values[0]; return values[0];
} }
@ -172,11 +168,8 @@ public abstract class ScriptDocValues<T> extends AbstractList<T> {
*/ */
public ReadableDateTime getValue() { public ReadableDateTime getValue() {
if (count == 0) { if (count == 0) {
if (ScriptModule.EXCEPTION_FOR_MISSING_VALUE) { throw new IllegalStateException("A document doesn't have a value for a field! " +
throw new IllegalStateException("A document doesn't have a value for a field! " + "Use doc[<field>].size()==0 to check if a document is missing a field!");
"Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return EPOCH;
} }
return get(0); return get(0);
} }
@ -277,11 +270,8 @@ public abstract class ScriptDocValues<T> extends AbstractList<T> {
public double getValue() { public double getValue() {
if (count == 0) { if (count == 0) {
if (ScriptModule.EXCEPTION_FOR_MISSING_VALUE) { throw new IllegalStateException("A document doesn't have a value for a field! " +
throw new IllegalStateException("A document doesn't have a value for a field! " + "Use doc[<field>].size()==0 to check if a document is missing a field!");
"Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return 0d;
} }
return values[0]; return values[0];
} }
@ -337,11 +327,8 @@ public abstract class ScriptDocValues<T> extends AbstractList<T> {
public GeoPoint getValue() { public GeoPoint getValue() {
if (count == 0) { if (count == 0) {
if (ScriptModule.EXCEPTION_FOR_MISSING_VALUE) { throw new IllegalStateException("A document doesn't have a value for a field! " +
throw new IllegalStateException("A document doesn't have a value for a field! " +
"Use doc[<field>].size()==0 to check if a document is missing a field!"); "Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return null;
} }
return values[0]; return values[0];
} }
@ -454,11 +441,8 @@ public abstract class ScriptDocValues<T> extends AbstractList<T> {
public boolean getValue() { public boolean getValue() {
if (count == 0) { if (count == 0) {
if (ScriptModule.EXCEPTION_FOR_MISSING_VALUE) { throw new IllegalStateException("A document doesn't have a value for a field! " +
throw new IllegalStateException("A document doesn't have a value for a field! " + "Use doc[<field>].size()==0 to check if a document is missing a field!");
"Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return false;
} }
return values[0]; return values[0];
} }
@ -544,11 +528,8 @@ public abstract class ScriptDocValues<T> extends AbstractList<T> {
public String getValue() { public String getValue() {
if (count == 0) { if (count == 0) {
if (ScriptModule.EXCEPTION_FOR_MISSING_VALUE) { throw new IllegalStateException("A document doesn't have a value for a field! " +
throw new IllegalStateException("A document doesn't have a value for a field! " +
"Use doc[<field>].size()==0 to check if a document is missing a field!"); "Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return null;
} }
return get(0); return get(0);
} }
@ -572,11 +553,8 @@ public abstract class ScriptDocValues<T> extends AbstractList<T> {
public BytesRef getValue() { public BytesRef getValue() {
if (count == 0) { if (count == 0) {
if (ScriptModule.EXCEPTION_FOR_MISSING_VALUE) { throw new IllegalStateException("A document doesn't have a value for a field! " +
throw new IllegalStateException("A document doesn't have a value for a field! " +
"Use doc[<field>].size()==0 to check if a document is missing a field!"); "Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return new BytesRef();
} }
return get(0); return get(0);
} }

View File

@ -31,9 +31,7 @@ import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.ScriptPlugin; import org.elasticsearch.plugins.ScriptPlugin;
import org.elasticsearch.search.aggregations.pipeline.movfn.MovingFunctionScript; import org.elasticsearch.search.aggregations.pipeline.movfn.MovingFunctionScript;
import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.Loggers;
/** /**
* Manages building {@link ScriptService}. * Manages building {@link ScriptService}.
@ -64,11 +62,6 @@ public class ScriptModule {
).collect(Collectors.toMap(c -> c.name, Function.identity())); ).collect(Collectors.toMap(c -> c.name, Function.identity()));
} }
public static final boolean EXCEPTION_FOR_MISSING_VALUE =
Booleans.parseBoolean(System.getProperty("es.scripting.exception_for_missing_value", "false"));
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(Loggers.getLogger(ScriptModule.class));
private final ScriptService scriptService; private final ScriptService scriptService;
public ScriptModule(Settings settings, List<ScriptPlugin> scriptPlugins) { public ScriptModule(Settings settings, List<ScriptPlugin> scriptPlugins) {
@ -92,10 +85,6 @@ public class ScriptModule {
} }
} }
} }
if (EXCEPTION_FOR_MISSING_VALUE == false)
DEPRECATION_LOGGER.deprecated("Script: returning default values for missing document values is deprecated. " +
"Set system property '-Des.scripting.exception_for_missing_value=true' " +
"to make behaviour compatible with future major versions.");
scriptService = new ScriptService(settings, Collections.unmodifiableMap(engines), Collections.unmodifiableMap(contexts)); scriptService = new ScriptService(settings, Collections.unmodifiableMap(engines), Collections.unmodifiableMap(contexts));
} }

View File

@ -1,195 +0,0 @@
/*
* 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.index.fielddata;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.fielddata.ScriptDocValues.Longs;
import org.elasticsearch.index.fielddata.ScriptDocValues.Dates;
import org.elasticsearch.index.fielddata.ScriptDocValues.Booleans;
import org.elasticsearch.plugins.ScriptPlugin;
import org.elasticsearch.script.MockScriptEngine;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptEngine;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.test.ESTestCase;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.ReadableDateTime;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import static java.util.Collections.singletonList;
public class ScriptDocValuesMissingV6BehaviourTests extends ESTestCase {
public void testScriptMissingValuesWarning(){
new ScriptModule(Settings.EMPTY, singletonList(new ScriptPlugin() {
@Override
public ScriptEngine getScriptEngine(Settings settings, Collection<ScriptContext<?>> contexts) {
return new MockScriptEngine(MockScriptEngine.NAME, Collections.singletonMap("1", script -> "1"));
}
}));
assertWarnings("Script: returning default values for missing document values is deprecated. " +
"Set system property '-Des.scripting.exception_for_missing_value=true' " +
"to make behaviour compatible with future major versions.");
}
public void testZeroForMissingValueLong() throws IOException {
long[][] values = new long[between(3, 10)][];
for (int d = 0; d < values.length; d++) {
values[d] = new long[0];
}
Longs longs = wrap(values);
for (int round = 0; round < 10; round++) {
int d = between(0, values.length - 1);
longs.setNextDocId(d);
assertEquals(0, longs.getValue());
}
}
public void testEpochForMissingValueDate() throws IOException {
final ReadableDateTime EPOCH = new DateTime(0, DateTimeZone.UTC);
long[][] values = new long[between(3, 10)][];
for (int d = 0; d < values.length; d++) {
values[d] = new long[0];
}
Dates dates = wrapDates(values);
for (int round = 0; round < 10; round++) {
int d = between(0, values.length - 1);
dates.setNextDocId(d);
assertEquals(EPOCH, dates.getValue());
}
}
public void testFalseForMissingValueBoolean() throws IOException {
long[][] values = new long[between(3, 10)][];
for (int d = 0; d < values.length; d++) {
values[d] = new long[0];
}
Booleans bools = wrapBooleans(values);
for (int round = 0; round < 10; round++) {
int d = between(0, values.length - 1);
bools.setNextDocId(d);
assertEquals(false, bools.getValue());
}
}
public void testNullForMissingValueGeo() throws IOException{
final MultiGeoPointValues values = wrap(new GeoPoint[0]);
final ScriptDocValues.GeoPoints script = new ScriptDocValues.GeoPoints(values);
script.setNextDocId(0);
assertEquals(null, script.getValue());
}
private Longs wrap(long[][] values) {
return new Longs(new AbstractSortedNumericDocValues() {
long[] current;
int i;
@Override
public boolean advanceExact(int doc) {
i = 0;
current = values[doc];
return current.length > 0;
}
@Override
public int docValueCount() {
return current.length;
}
@Override
public long nextValue() {
return current[i++];
}
});
}
private Booleans wrapBooleans(long[][] values) {
return new Booleans(new AbstractSortedNumericDocValues() {
long[] current;
int i;
@Override
public boolean advanceExact(int doc) {
i = 0;
current = values[doc];
return current.length > 0;
}
@Override
public int docValueCount() {
return current.length;
}
@Override
public long nextValue() {
return current[i++];
}
});
}
private Dates wrapDates(long[][] values) {
return new Dates(new AbstractSortedNumericDocValues() {
long[] current;
int i;
@Override
public boolean advanceExact(int doc) {
current = values[doc];
i = 0;
return current.length > 0;
}
@Override
public int docValueCount() {
return current.length;
}
@Override
public long nextValue() {
return current[i++];
}
});
}
private static MultiGeoPointValues wrap(final GeoPoint... points) {
return new MultiGeoPointValues() {
int docID = -1;
int i;
@Override
public GeoPoint nextValue() {
if (docID != 0) {
fail();
}
return points[i++];
}
@Override
public boolean advanceExact(int docId) {
docID = docId;
return points.length > 0;
}
@Override
public int docValueCount() {
if (docID != 0) {
return 0;
}
return points.length;
}
};
}
}

View File

@ -120,7 +120,8 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
this.scheduler = new SchedulerEngine(clock); this.scheduler = new SchedulerEngine(clock);
this.licenseState = licenseState; this.licenseState = licenseState;
this.operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService, this.operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService,
XPackPlugin.resolveConfigFile(env, "license_mode"), logger, () -> updateLicenseState(getLicense())); XPackPlugin.resolveConfigFile(env, "license_mode"), logger,
() -> updateLicenseState(getLicensesMetaData()));
this.scheduler.register(this); this.scheduler.register(this);
populateExpirationCallbacks(); populateExpirationCallbacks();
} }
@ -265,11 +266,11 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
@Override @Override
public void triggered(SchedulerEngine.Event event) { public void triggered(SchedulerEngine.Event event) {
final LicensesMetaData licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); final LicensesMetaData licensesMetaData = getLicensesMetaData();
if (licensesMetaData != null) { if (licensesMetaData != null) {
final License license = licensesMetaData.getLicense(); final License license = licensesMetaData.getLicense();
if (event.getJobName().equals(LICENSE_JOB)) { if (event.getJobName().equals(LICENSE_JOB)) {
updateLicenseState(license); updateLicenseState(license, licensesMetaData.getMostRecentTrialVersion());
} else if (event.getJobName().startsWith(ExpirationCallback.EXPIRATION_JOB_PREFIX)) { } else if (event.getJobName().startsWith(ExpirationCallback.EXPIRATION_JOB_PREFIX)) {
expirationCallbacks.stream() expirationCallbacks.stream()
.filter(expirationCallback -> expirationCallback.getId().equals(event.getJobName())) .filter(expirationCallback -> expirationCallback.getId().equals(event.getJobName()))
@ -311,6 +312,10 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license; return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license;
} }
private LicensesMetaData getLicensesMetaData() {
return this.clusterService.state().metaData().custom(LicensesMetaData.TYPE);
}
void startTrialLicense(PostStartTrialRequest request, final ActionListener<PostStartTrialResponse> listener) { void startTrialLicense(PostStartTrialRequest request, final ActionListener<PostStartTrialResponse> listener) {
if (VALID_TRIAL_TYPES.contains(request.getType()) == false) { if (VALID_TRIAL_TYPES.contains(request.getType()) == false) {
throw new IllegalArgumentException("Cannot start trial of type [" + request.getType() + "]. Valid trial types are " throw new IllegalArgumentException("Cannot start trial of type [" + request.getType() + "]. Valid trial types are "
@ -422,10 +427,16 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
} }
} }
protected void updateLicenseState(final License license) { private void updateLicenseState(LicensesMetaData licensesMetaData) {
if (licensesMetaData != null) {
updateLicenseState(getLicense(licensesMetaData), licensesMetaData.getMostRecentTrialVersion());
}
}
protected void updateLicenseState(final License license, Version mostRecentTrialVersion) {
if (license == LicensesMetaData.LICENSE_TOMBSTONE) { if (license == LicensesMetaData.LICENSE_TOMBSTONE) {
// implies license has been explicitly deleted // implies license has been explicitly deleted
licenseState.update(License.OperationMode.MISSING, false); licenseState.update(License.OperationMode.MISSING, false, mostRecentTrialVersion);
return; return;
} }
if (license != null) { if (license != null) {
@ -438,7 +449,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
// date that is near Long.MAX_VALUE // date that is near Long.MAX_VALUE
active = time >= license.issueDate() && time - GRACE_PERIOD_DURATION.getMillis() < license.expiryDate(); active = time >= license.issueDate() && time - GRACE_PERIOD_DURATION.getMillis() < license.expiryDate();
} }
licenseState.update(license.operationMode(), active); licenseState.update(license.operationMode(), active, mostRecentTrialVersion);
if (active) { if (active) {
if (time < license.expiryDate()) { if (time < license.expiryDate()) {
@ -480,7 +491,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
logger.info("license [{}] mode [{}] - valid", license.uid(), logger.info("license [{}] mode [{}] - valid", license.uid(),
license.operationMode().name().toLowerCase(Locale.ROOT)); license.operationMode().name().toLowerCase(Locale.ROOT));
} }
updateLicenseState(license); updateLicenseState(license, currentLicensesMetaData.getMostRecentTrialVersion());
} }
} }

View File

@ -5,8 +5,11 @@
*/ */
package org.elasticsearch.license; package org.elasticsearch.license;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.LoggerMessageFormat; import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.License.OperationMode; import org.elasticsearch.license.License.OperationMode;
import org.elasticsearch.xpack.core.XPackField; import org.elasticsearch.xpack.core.XPackField;
@ -266,6 +269,7 @@ public class XPackLicenseState {
private final List<Runnable> listeners = new CopyOnWriteArrayList<>(); private final List<Runnable> listeners = new CopyOnWriteArrayList<>();
private final boolean isSecurityEnabled; private final boolean isSecurityEnabled;
private final boolean isSecurityExplicitlyEnabled; private final boolean isSecurityExplicitlyEnabled;
private volatile boolean isSecurityEnabledByTrialVersion;
public XPackLicenseState(Settings settings) { public XPackLicenseState(Settings settings) {
this.isSecurityEnabled = XPackSettings.SECURITY_ENABLED.get(settings); this.isSecurityEnabled = XPackSettings.SECURITY_ENABLED.get(settings);
@ -274,11 +278,30 @@ public class XPackLicenseState {
// setting is not explicitly set // setting is not explicitly set
this.isSecurityExplicitlyEnabled = isSecurityEnabled && this.isSecurityExplicitlyEnabled = isSecurityEnabled &&
(settings.hasValue(XPackSettings.SECURITY_ENABLED.getKey()) || XPackSettings.TRANSPORT_SSL_ENABLED.get(settings)); (settings.hasValue(XPackSettings.SECURITY_ENABLED.getKey()) || XPackSettings.TRANSPORT_SSL_ENABLED.get(settings));
this.isSecurityEnabledByTrialVersion = false;
} }
/** Updates the current state of the license, which will change what features are available. */ /**
void update(OperationMode mode, boolean active) { * Updates the current state of the license, which will change what features are available.
*
* @param mode The mode (type) of the current license.
* @param active True if the current license exists and is within its allowed usage period; false if it is expired or missing.
* @param mostRecentTrialVersion If this cluster has, at some point commenced a trial, the most recent version on which they did that.
* May be {@code null} if they have never generated a trial license on this cluster, or the most recent
* trial was prior to this metadata being tracked (6.1)
*/
void update(OperationMode mode, boolean active, @Nullable Version mostRecentTrialVersion) {
status = new Status(mode, active); status = new Status(mode, active);
if (isSecurityEnabled == true && isSecurityExplicitlyEnabled == false && mode == OperationMode.TRIAL
&& isSecurityEnabledByTrialVersion == false) {
// Before 6.3, Trial licenses would default having security enabled.
// If this license was generated before that version, then treat it as if security is explicitly enabled
if (mostRecentTrialVersion == null || mostRecentTrialVersion.before(Version.V_6_3_0)) {
Loggers.getLogger(getClass()).info("Automatically enabling security for older trial license ({})",
mostRecentTrialVersion == null ? "[pre 6.1.0]" : mostRecentTrialVersion.toString());
isSecurityEnabledByTrialVersion = true;
}
}
listeners.forEach(Runnable::run); listeners.forEach(Runnable::run);
} }
@ -603,6 +626,6 @@ public class XPackLicenseState {
public boolean isSecurityEnabled() { public boolean isSecurityEnabled() {
final OperationMode mode = status.mode; final OperationMode mode = status.mode;
return mode == OperationMode.TRIAL ? isSecurityExplicitlyEnabled : isSecurityEnabled; return mode == OperationMode.TRIAL ? (isSecurityExplicitlyEnabled || isSecurityEnabledByTrialVersion) : isSecurityEnabled;
} }
} }

View File

@ -6,6 +6,7 @@
package org.elasticsearch.license; package org.elasticsearch.license;
import com.carrotsearch.randomizedtesting.RandomizedTest; import com.carrotsearch.randomizedtesting.RandomizedTest;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
@ -353,20 +354,22 @@ public class TestUtils {
public static class AssertingLicenseState extends XPackLicenseState { public static class AssertingLicenseState extends XPackLicenseState {
public final List<License.OperationMode> modeUpdates = new ArrayList<>(); public final List<License.OperationMode> modeUpdates = new ArrayList<>();
public final List<Boolean> activeUpdates = new ArrayList<>(); public final List<Boolean> activeUpdates = new ArrayList<>();
public final List<Version> trialVersionUpdates = new ArrayList<>();
public AssertingLicenseState() { public AssertingLicenseState() {
super(Settings.EMPTY); super(Settings.EMPTY);
} }
@Override @Override
void update(License.OperationMode mode, boolean active) { void update(License.OperationMode mode, boolean active, Version mostRecentTrialVersion) {
modeUpdates.add(mode); modeUpdates.add(mode);
activeUpdates.add(active); activeUpdates.add(active);
trialVersionUpdates.add(mostRecentTrialVersion);
} }
} }
/** /**
* A license state that makes the {@link #update(License.OperationMode, boolean)} * A license state that makes the {@link #update(License.OperationMode, boolean, Version)}
* method public for use in tests. * method public for use in tests.
*/ */
public static class UpdatableLicenseState extends XPackLicenseState { public static class UpdatableLicenseState extends XPackLicenseState {
@ -379,8 +382,8 @@ public class TestUtils {
} }
@Override @Override
public void update(License.OperationMode mode, boolean active) { public void update(License.OperationMode mode, boolean active, Version mostRecentTrialVersion) {
super.update(mode, active); super.update(mode, active, mostRecentTrialVersion);
} }
} }

View File

@ -5,9 +5,11 @@
*/ */
package org.elasticsearch.license; package org.elasticsearch.license;
import org.elasticsearch.Version;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.License.OperationMode; import org.elasticsearch.license.License.OperationMode;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.VersionUtils;
import org.elasticsearch.xpack.core.XPackField; import org.elasticsearch.xpack.core.XPackField;
import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.XPackSettings;
@ -31,7 +33,7 @@ public class XPackLicenseStateTests extends ESTestCase {
/** Creates a license state with the given license type and active state, and checks the given method returns expected. */ /** Creates a license state with the given license type and active state, and checks the given method returns expected. */
void assertAllowed(OperationMode mode, boolean active, Predicate<XPackLicenseState> predicate, boolean expected) { void assertAllowed(OperationMode mode, boolean active, Predicate<XPackLicenseState> predicate, boolean expected) {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(mode, active); licenseState.update(mode, active, null);
assertEquals(expected, predicate.test(licenseState)); assertEquals(expected, predicate.test(licenseState));
} }
@ -102,7 +104,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityBasic() { public void testSecurityBasic() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(BASIC, true); licenseState.update(BASIC, true, null);
assertThat(licenseState.isAuthAllowed(), is(false)); assertThat(licenseState.isAuthAllowed(), is(false));
assertThat(licenseState.isIpFilteringAllowed(), is(false)); assertThat(licenseState.isIpFilteringAllowed(), is(false));
@ -116,7 +118,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityBasicExpired() { public void testSecurityBasicExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(BASIC, false); licenseState.update(BASIC, false, null);
assertThat(licenseState.isAuthAllowed(), is(false)); assertThat(licenseState.isAuthAllowed(), is(false));
assertThat(licenseState.isIpFilteringAllowed(), is(false)); assertThat(licenseState.isIpFilteringAllowed(), is(false));
@ -130,7 +132,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityStandard() { public void testSecurityStandard() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(STANDARD, true); licenseState.update(STANDARD, true, null);
assertThat(licenseState.isAuthAllowed(), is(true)); assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(false)); assertThat(licenseState.isIpFilteringAllowed(), is(false));
@ -144,7 +146,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityStandardExpired() { public void testSecurityStandardExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(STANDARD, false); licenseState.update(STANDARD, false, null);
assertThat(licenseState.isAuthAllowed(), is(true)); assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(false)); assertThat(licenseState.isIpFilteringAllowed(), is(false));
@ -158,7 +160,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityGold() { public void testSecurityGold() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(GOLD, true); licenseState.update(GOLD, true, null);
assertThat(licenseState.isAuthAllowed(), is(true)); assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true)); assertThat(licenseState.isIpFilteringAllowed(), is(true));
@ -172,7 +174,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityGoldExpired() { public void testSecurityGoldExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(GOLD, false); licenseState.update(GOLD, false, null);
assertThat(licenseState.isAuthAllowed(), is(true)); assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true)); assertThat(licenseState.isIpFilteringAllowed(), is(true));
@ -186,7 +188,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityPlatinum() { public void testSecurityPlatinum() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(PLATINUM, true); licenseState.update(PLATINUM, true, null);
assertThat(licenseState.isAuthAllowed(), is(true)); assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true)); assertThat(licenseState.isIpFilteringAllowed(), is(true));
@ -200,7 +202,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSecurityPlatinumExpired() { public void testSecurityPlatinumExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY, XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build())); Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(PLATINUM, false); licenseState.update(PLATINUM, false, null);
assertThat(licenseState.isAuthAllowed(), is(true)); assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true)); assertThat(licenseState.isIpFilteringAllowed(), is(true));
@ -211,6 +213,34 @@ public class XPackLicenseStateTests extends ESTestCase {
assertThat(licenseState.isCustomRoleProvidersAllowed(), is(false)); assertThat(licenseState.isCustomRoleProvidersAllowed(), is(false));
} }
public void testNewTrialDefaultsSecurityOff() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(TRIAL, true, VersionUtils.randomVersionBetween(random(), Version.V_6_3_0, Version.CURRENT));
assertThat(licenseState.isSecurityEnabled(), is(false));
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(true));
assertThat(licenseState.allowedRealmType(), is(XPackLicenseState.AllowedRealmType.ALL));
assertThat(licenseState.isCustomRoleProvidersAllowed(), is(true));
}
public void testOldTrialDefaultsSecurityOn() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(TRIAL, true, rarely() ? null : VersionUtils.randomVersionBetween(random(), Version.V_5_6_0, Version.V_6_2_4));
assertThat(licenseState.isSecurityEnabled(), is(true));
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(true));
assertThat(licenseState.allowedRealmType(), is(XPackLicenseState.AllowedRealmType.ALL));
assertThat(licenseState.isCustomRoleProvidersAllowed(), is(true));
}
public void testSecurityAckBasicToNotGoldOrStandard() { public void testSecurityAckBasicToNotGoldOrStandard() {
OperationMode toMode = randomFrom(OperationMode.values(), mode -> mode != GOLD && mode != STANDARD); OperationMode toMode = randomFrom(OperationMode.values(), mode -> mode != GOLD && mode != STANDARD);
assertAckMesssages(XPackField.SECURITY, BASIC, toMode, 0); assertAckMesssages(XPackField.SECURITY, BASIC, toMode, 0);
@ -354,7 +384,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlBasic() { public void testSqlBasic() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(BASIC, true); licenseState.update(BASIC, true, null);
assertThat(licenseState.isSqlAllowed(), is(true)); assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(false)); assertThat(licenseState.isJdbcAllowed(), is(false));
@ -362,7 +392,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlBasicExpired() { public void testSqlBasicExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(BASIC, false); licenseState.update(BASIC, false, null);
assertThat(licenseState.isSqlAllowed(), is(false)); assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false)); assertThat(licenseState.isJdbcAllowed(), is(false));
@ -370,7 +400,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlStandard() { public void testSqlStandard() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(STANDARD, true); licenseState.update(STANDARD, true, null);
assertThat(licenseState.isSqlAllowed(), is(true)); assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(false)); assertThat(licenseState.isJdbcAllowed(), is(false));
@ -378,7 +408,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlStandardExpired() { public void testSqlStandardExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(STANDARD, false); licenseState.update(STANDARD, false, null);
assertThat(licenseState.isSqlAllowed(), is(false)); assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false)); assertThat(licenseState.isJdbcAllowed(), is(false));
@ -386,7 +416,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlGold() { public void testSqlGold() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(GOLD, true); licenseState.update(GOLD, true, null);
assertThat(licenseState.isSqlAllowed(), is(true)); assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(false)); assertThat(licenseState.isJdbcAllowed(), is(false));
@ -394,7 +424,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlGoldExpired() { public void testSqlGoldExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(GOLD, false); licenseState.update(GOLD, false, null);
assertThat(licenseState.isSqlAllowed(), is(false)); assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false)); assertThat(licenseState.isJdbcAllowed(), is(false));
@ -402,7 +432,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlPlatinum() { public void testSqlPlatinum() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(PLATINUM, true); licenseState.update(PLATINUM, true, null);
assertThat(licenseState.isSqlAllowed(), is(true)); assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(true)); assertThat(licenseState.isJdbcAllowed(), is(true));
@ -410,7 +440,7 @@ public class XPackLicenseStateTests extends ESTestCase {
public void testSqlPlatinumExpired() { public void testSqlPlatinumExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY); XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(PLATINUM, false); licenseState.update(PLATINUM, false, null);
assertThat(licenseState.isSqlAllowed(), is(false)); assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false)); assertThat(licenseState.isJdbcAllowed(), is(false));

View File

@ -551,7 +551,7 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
public static void disableLicensing(License.OperationMode operationMode) { public static void disableLicensing(License.OperationMode operationMode) {
for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) {
licenseState.update(operationMode, false); licenseState.update(operationMode, false, null);
} }
} }
@ -561,7 +561,7 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
public static void enableLicensing(License.OperationMode operationMode) { public static void enableLicensing(License.OperationMode operationMode) {
for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) {
licenseState.update(operationMode, true); licenseState.update(operationMode, true, null);
} }
} }
} }

View File

@ -307,7 +307,7 @@ public class LicensingTests extends SecurityIntegTestCase {
public static void disableLicensing(License.OperationMode operationMode) { public static void disableLicensing(License.OperationMode operationMode) {
for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) {
licenseState.update(operationMode, false); licenseState.update(operationMode, false, null);
} }
} }
@ -317,7 +317,7 @@ public class LicensingTests extends SecurityIntegTestCase {
public static void enableLicensing(License.OperationMode operationMode) { public static void enableLicensing(License.OperationMode operationMode) {
for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) {
licenseState.update(operationMode, true); licenseState.update(operationMode, true, null);
} }
} }
} }

View File

@ -399,7 +399,8 @@ public class SecurityTests extends ESTestCase {
createComponents(Settings.EMPTY); createComponents(Settings.EMPTY);
Function<String, Predicate<String>> fieldFilter = security.getFieldFilter(); Function<String, Predicate<String>> fieldFilter = security.getFieldFilter();
assertNotSame(MapperPlugin.NOOP_FIELD_FILTER, fieldFilter); assertNotSame(MapperPlugin.NOOP_FIELD_FILTER, fieldFilter);
licenseState.update(randomFrom(License.OperationMode.BASIC, License.OperationMode.STANDARD, License.OperationMode.GOLD), true); licenseState.update(
randomFrom(License.OperationMode.BASIC, License.OperationMode.STANDARD, License.OperationMode.GOLD), true, null);
assertNotSame(MapperPlugin.NOOP_FIELD_FILTER, fieldFilter); assertNotSame(MapperPlugin.NOOP_FIELD_FILTER, fieldFilter);
assertSame(MapperPlugin.NOOP_FIELD_PREDICATE, fieldFilter.apply(randomAlphaOfLengthBetween(3, 6))); assertSame(MapperPlugin.NOOP_FIELD_PREDICATE, fieldFilter.apply(randomAlphaOfLengthBetween(3, 6)));
} }

View File

@ -409,7 +409,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
UpdatableLicenseState xPackLicenseState = new UpdatableLicenseState(SECURITY_ENABLED_SETTINGS); UpdatableLicenseState xPackLicenseState = new UpdatableLicenseState(SECURITY_ENABLED_SETTINGS);
// these licenses don't allow custom role providers // these licenses don't allow custom role providers
xPackLicenseState.update(randomFrom(OperationMode.BASIC, OperationMode.GOLD, OperationMode.STANDARD), true); xPackLicenseState.update(randomFrom(OperationMode.BASIC, OperationMode.GOLD, OperationMode.STANDARD), true, null);
CompositeRolesStore compositeRolesStore = new CompositeRolesStore( CompositeRolesStore compositeRolesStore = new CompositeRolesStore(
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore,
Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState); Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState);
@ -427,7 +427,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore,
Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState); Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState);
// these licenses allow custom role providers // these licenses allow custom role providers
xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), true); xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), true, null);
roleNames = Sets.newHashSet("roleA"); roleNames = Sets.newHashSet("roleA");
future = new PlainActionFuture<>(); future = new PlainActionFuture<>();
fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY); fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);
@ -441,7 +441,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
compositeRolesStore = new CompositeRolesStore( compositeRolesStore = new CompositeRolesStore(
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore,
Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState); Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState);
xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), false); xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), false, null);
roleNames = Sets.newHashSet("roleA"); roleNames = Sets.newHashSet("roleA");
future = new PlainActionFuture<>(); future = new PlainActionFuture<>();
fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY); fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);

View File

@ -48,7 +48,7 @@ public class SamlBaseRestHandlerTests extends ESTestCase {
.put(XPackSettings.SECURITY_ENABLED.getKey(), true) .put(XPackSettings.SECURITY_ENABLED.getKey(), true)
.build(); .build();
final TestUtils.UpdatableLicenseState licenseState = new TestUtils.UpdatableLicenseState(settings); final TestUtils.UpdatableLicenseState licenseState = new TestUtils.UpdatableLicenseState(settings);
licenseState.update(licenseMode, true); licenseState.update(licenseMode, true, null);
return new SamlBaseRestHandler(settings, licenseState) { return new SamlBaseRestHandler(settings, licenseState) {

View File

@ -85,7 +85,7 @@ public class ADLdapUserSearchSessionFactoryTests extends AbstractActiveDirectory
Settings.Builder builder = Settings.builder() Settings.Builder builder = Settings.builder()
.put(globalSettings); .put(globalSettings);
settings.keySet().forEach(k -> { settings.keySet().forEach(k -> {
builder.copy("xpack.security.authc.realms.ldap." + k, k, settings); builder.copy("xpack.security.authc.realms.ad-as-ldap-test." + k, k, settings);
}); });
Settings fullSettings = builder.build(); Settings fullSettings = builder.build();

View File

@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException; import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.env.TestEnvironment;
import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.TestThreadPool;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -59,9 +60,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testAdAuth() throws Exception { public void testAdAuth() throws Exception {
RealmConfig config = new RealmConfig("ad-test", RealmConfig config = configureRealm("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false));
buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false),
globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(Settings.EMPTY));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String userName = "ironman"; String userName = "ironman";
@ -82,11 +81,21 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
} }
} }
private RealmConfig configureRealm(String name, Settings settings) {
final Environment env = TestEnvironment.newEnvironment(globalSettings);
final Settings mergedSettings = Settings.builder()
.put(settings)
.normalizePrefix("xpack.security.authc.realms." + name + ".")
.put(globalSettings)
.build();
this.sslService = new SSLService(mergedSettings, env);
return new RealmConfig(name, settings, globalSettings, env, new ThreadContext(globalSettings));
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testNetbiosAuth() throws Exception { public void testNetbiosAuth() throws Exception {
final String adUrl = randomFrom(AD_LDAP_URL, AD_LDAP_GC_URL); final String adUrl = randomFrom(AD_LDAP_URL, AD_LDAP_GC_URL);
RealmConfig config = new RealmConfig("ad-test", buildAdSettings(adUrl, AD_DOMAIN, false), globalSettings, RealmConfig config = configureRealm("ad-test", buildAdSettings(adUrl, AD_DOMAIN, false));
TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String userName = "ades\\ironman"; String userName = "ades\\ironman";
@ -108,8 +117,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
} }
public void testAdAuthAvengers() throws Exception { public void testAdAuthAvengers() throws Exception {
RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false), globalSettings, RealmConfig config = configureRealm("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false));
TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String[] users = new String[]{"cap", "hawkeye", "hulk", "ironman", "thor", "blackwidow"}; String[] users = new String[]{"cap", "hawkeye", "hulk", "ironman", "thor", "blackwidow"};
@ -126,8 +134,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
public void testAuthenticate() throws Exception { public void testAuthenticate() throws Exception {
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com",
LdapSearchScope.ONE_LEVEL, false); LdapSearchScope.ONE_LEVEL, false);
RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-test", settings);
new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String userName = "hulk"; String userName = "hulk";
@ -151,8 +158,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
public void testAuthenticateBaseUserSearch() throws Exception { public void testAuthenticateBaseUserSearch() throws Exception {
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Bruce Banner, CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Bruce Banner, CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com",
LdapSearchScope.BASE, false); LdapSearchScope.BASE, false);
RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-test", settings);
new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String userName = "hulk"; String userName = "hulk";
@ -180,8 +186,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
"CN=Avengers,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com") "CN=Avengers,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
.put(ActiveDirectorySessionFactorySettings.AD_GROUP_SEARCH_SCOPE_SETTING, LdapSearchScope.BASE) .put(ActiveDirectorySessionFactorySettings.AD_GROUP_SEARCH_SCOPE_SETTING, LdapSearchScope.BASE)
.build(); .build();
RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-test", settings);
new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String userName = "hulk"; String userName = "hulk";
@ -198,8 +203,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
public void testAuthenticateWithUserPrincipalName() throws Exception { public void testAuthenticateWithUserPrincipalName() throws Exception {
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com",
LdapSearchScope.ONE_LEVEL, false); LdapSearchScope.ONE_LEVEL, false);
RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-test", settings);
new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
//Login with the UserPrincipalName //Login with the UserPrincipalName
@ -220,8 +224,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
public void testAuthenticateWithSAMAccountName() throws Exception { public void testAuthenticateWithSAMAccountName() throws Exception {
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com",
LdapSearchScope.ONE_LEVEL, false); LdapSearchScope.ONE_LEVEL, false);
RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-test", settings);
new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
//login with sAMAccountName //login with sAMAccountName
@ -247,8 +250,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
.put(ActiveDirectorySessionFactorySettings.AD_USER_SEARCH_FILTER_SETTING, .put(ActiveDirectorySessionFactorySettings.AD_USER_SEARCH_FILTER_SETTING,
"(&(objectclass=user)(userPrincipalName={0}@ad.test.elasticsearch.com))") "(&(objectclass=user)(userPrincipalName={0}@ad.test.elasticsearch.com))")
.build(); .build();
RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-test", settings);
new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
//Login with the UserPrincipalName //Login with the UserPrincipalName
@ -284,8 +286,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
.putList("ssl.certificate_authorities", certificatePaths) .putList("ssl.certificate_authorities", certificatePaths)
.build(); .build();
} }
RealmConfig config = new RealmConfig("ad-as-ldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-as-ldap-test", settings);
new ThreadContext(globalSettings));
LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool);
String user = "Bruce Banner"; String user = "Bruce Banner";
@ -348,8 +349,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
.putList("ssl.certificate_authorities", certificatePaths) .putList("ssl.certificate_authorities", certificatePaths)
.build(); .build();
} }
RealmConfig config = new RealmConfig("ad-as-ldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), RealmConfig config = configureRealm("ad-as-ldap-test", settings);
new ThreadContext(globalSettings));
LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool);
String user = "Bruce Banner"; String user = "Bruce Banner";
@ -366,9 +366,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
} }
public void testADLookup() throws Exception { public void testADLookup() throws Exception {
RealmConfig config = new RealmConfig("ad-test", RealmConfig config = configureRealm("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false, true));
buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false, true),
globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(Settings.EMPTY));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
List<String> users = randomSubsetOf(Arrays.asList("cap", "hawkeye", "hulk", "ironman", "thor", "blackwidow", List<String> users = randomSubsetOf(Arrays.asList("cap", "hawkeye", "hulk", "ironman", "thor", "blackwidow",