Run spotless and exclude checkstyle on libs module (#1428)
Signed-off-by: Owais Kazi <owaiskazi19@gmail.com>
This commit is contained in:
parent
a19c3736e5
commit
8394f541bc
|
@ -23,6 +23,8 @@
|
|||
<suppress files="client" checks="." />
|
||||
<!-- Excludes checkstyle run on plugins/examples -->
|
||||
<suppress files="plugins[/\\]examples" checks="." />
|
||||
<!-- Excludes checkstyle run on libs module -->
|
||||
<suppress files="libs" checks="." />
|
||||
|
||||
<!--
|
||||
Truly temporary suppressions suppression of snippets included in
|
||||
|
|
|
@ -57,16 +57,6 @@ import org.opensearch.gradle.BuildPlugin
|
|||
|
||||
// Do not add new sub-projects here!
|
||||
def projectPathsToExclude = [
|
||||
':libs:opensearch-cli',
|
||||
':libs:opensearch-core',
|
||||
':libs:opensearch-dissect',
|
||||
':libs:opensearch-geo',
|
||||
':libs:opensearch-grok',
|
||||
':libs:opensearch-nio',
|
||||
':libs:opensearch-plugin-classloader',
|
||||
':libs:opensearch-secure-sm',
|
||||
':libs:opensearch-ssl-config',
|
||||
':libs:opensearch-x-content',
|
||||
':modules:aggs-matrix-stats',
|
||||
':modules:analysis-common',
|
||||
':modules:ingest-common',
|
||||
|
|
|
@ -58,8 +58,8 @@ public abstract class Command implements Closeable {
|
|||
|
||||
private final OptionSpec<Void> helpOption = parser.acceptsAll(Arrays.asList("h", "help"), "Show help").forHelp();
|
||||
private final OptionSpec<Void> silentOption = parser.acceptsAll(Arrays.asList("s", "silent"), "Show minimal output");
|
||||
private final OptionSpec<Void> verboseOption =
|
||||
parser.acceptsAll(Arrays.asList("v", "verbose"), "Show verbose output").availableUnless(silentOption);
|
||||
private final OptionSpec<Void> verboseOption = parser.acceptsAll(Arrays.asList("v", "verbose"), "Show verbose output")
|
||||
.availableUnless(silentOption);
|
||||
|
||||
/**
|
||||
* Construct the command with the specified command description and runnable to execute before main is invoked.
|
||||
|
@ -82,9 +82,7 @@ public abstract class Command implements Closeable {
|
|||
try {
|
||||
this.close();
|
||||
} catch (final IOException e) {
|
||||
try (
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw)) {
|
||||
try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
|
||||
e.printStackTrace(pw);
|
||||
terminal.errorPrintln(sw.toString());
|
||||
} catch (final IOException impossible) {
|
||||
|
|
|
@ -37,19 +37,19 @@ package org.opensearch.cli;
|
|||
*/
|
||||
public class ExitCodes {
|
||||
public static final int OK = 0;
|
||||
public static final int USAGE = 64; /* command line usage error */
|
||||
public static final int DATA_ERROR = 65; /* data format error */
|
||||
public static final int NO_INPUT = 66; /* cannot open input */
|
||||
public static final int NO_USER = 67; /* addressee unknown */
|
||||
public static final int NO_HOST = 68; /* host name unknown */
|
||||
public static final int UNAVAILABLE = 69; /* service unavailable */
|
||||
public static final int CODE_ERROR = 70; /* internal software error */
|
||||
public static final int CANT_CREATE = 73; /* can't create (user) output file */
|
||||
public static final int IO_ERROR = 74; /* input/output error */
|
||||
public static final int TEMP_FAILURE = 75; /* temp failure; user is invited to retry */
|
||||
public static final int PROTOCOL = 76; /* remote error in protocol */
|
||||
public static final int NOPERM = 77; /* permission denied */
|
||||
public static final int CONFIG = 78; /* configuration error */
|
||||
public static final int USAGE = 64; /* command line usage error */
|
||||
public static final int DATA_ERROR = 65; /* data format error */
|
||||
public static final int NO_INPUT = 66; /* cannot open input */
|
||||
public static final int NO_USER = 67; /* addressee unknown */
|
||||
public static final int NO_HOST = 68; /* host name unknown */
|
||||
public static final int UNAVAILABLE = 69; /* service unavailable */
|
||||
public static final int CODE_ERROR = 70; /* internal software error */
|
||||
public static final int CANT_CREATE = 73; /* can't create (user) output file */
|
||||
public static final int IO_ERROR = 74; /* input/output error */
|
||||
public static final int TEMP_FAILURE = 75; /* temp failure; user is invited to retry */
|
||||
public static final int PROTOCOL = 76; /* remote error in protocol */
|
||||
public static final int NOPERM = 77; /* permission denied */
|
||||
public static final int CONFIG = 78; /* configuration error */
|
||||
|
||||
private ExitCodes() { /* no instance, just constants */ }
|
||||
}
|
||||
|
|
|
@ -44,4 +44,3 @@ import java.lang.annotation.Target;
|
|||
public @interface SuppressForbidden {
|
||||
String reason();
|
||||
}
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ public abstract class Terminal {
|
|||
len++;
|
||||
}
|
||||
|
||||
if (len > 0 && len < buf.length && buf[len-1] == '\r') {
|
||||
if (len > 0 && len < buf.length && buf[len - 1] == '\r') {
|
||||
len--;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ public class JarHell {
|
|||
output.accept("java.class.path: " + System.getProperty("java.class.path"));
|
||||
output.accept("sun.boot.class.path: " + System.getProperty("sun.boot.class.path"));
|
||||
if (loader instanceof URLClassLoader) {
|
||||
output.accept("classloader urls: " + Arrays.toString(((URLClassLoader)loader).getURLs()));
|
||||
output.accept("classloader urls: " + Arrays.toString(((URLClassLoader) loader).getURLs()));
|
||||
}
|
||||
checkJarHell(parseClassPath(), output);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class JarHell {
|
|||
* @return array of URLs
|
||||
* @throws IllegalStateException if the classpath contains empty elements
|
||||
*/
|
||||
public static Set<URL> parseClassPath() {
|
||||
public static Set<URL> parseClassPath() {
|
||||
return parseClassPath(System.getProperty("java.class.path"));
|
||||
}
|
||||
|
||||
|
@ -124,13 +124,17 @@ public class JarHell {
|
|||
// Technically empty classpath element behaves like CWD.
|
||||
// So below is the "correct" code, however in practice with ES, this is usually just a misconfiguration,
|
||||
// from old shell scripts left behind or something:
|
||||
// if (element.isEmpty()) {
|
||||
// element = System.getProperty("user.dir");
|
||||
// }
|
||||
// if (element.isEmpty()) {
|
||||
// element = System.getProperty("user.dir");
|
||||
// }
|
||||
// Instead we just throw an exception, and keep it clean.
|
||||
if (element.isEmpty()) {
|
||||
throw new IllegalStateException("Classpath should not contain empty elements! (outdated shell script from a previous" +
|
||||
" version?) classpath='" + classPath + "'");
|
||||
throw new IllegalStateException(
|
||||
"Classpath should not contain empty elements! (outdated shell script from a previous"
|
||||
+ " version?) classpath='"
|
||||
+ classPath
|
||||
+ "'"
|
||||
);
|
||||
}
|
||||
// we should be able to just Paths.get() each element, but unfortunately this is not the
|
||||
// whole story on how classpath parsing works: if you want to know, start at sun.misc.Launcher,
|
||||
|
@ -147,15 +151,16 @@ public class JarHell {
|
|||
}
|
||||
// now just parse as ordinary file
|
||||
try {
|
||||
if (element .equals("/")) {
|
||||
if (element.equals("/")) {
|
||||
// Eclipse adds this to the classpath when running unit tests...
|
||||
continue;
|
||||
}
|
||||
URL url = PathUtils.get(element).toUri().toURL();
|
||||
// junit4.childvm.count
|
||||
if (urlElements.add(url) == false && element.endsWith(".jar")) {
|
||||
throw new IllegalStateException("jar hell!" + System.lineSeparator() +
|
||||
"duplicate jar [" + element + "] on classpath: " + classPath);
|
||||
throw new IllegalStateException(
|
||||
"jar hell!" + System.lineSeparator() + "duplicate jar [" + element + "] on classpath: " + classPath
|
||||
);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
// should not happen, as we use the filesystem API
|
||||
|
@ -178,7 +183,7 @@ public class JarHell {
|
|||
// a "list" at all. So just exclude any elements underneath the java home
|
||||
String javaHome = System.getProperty("java.home");
|
||||
output.accept("java.home: " + javaHome);
|
||||
final Map<String,Path> clazzes = new HashMap<>(32768);
|
||||
final Map<String, Path> clazzes = new HashMap<>(32768);
|
||||
Set<Path> seenJars = new HashSet<>();
|
||||
for (final URL url : urls) {
|
||||
final Path path = PathUtils.get(url.toURI());
|
||||
|
@ -189,8 +194,7 @@ public class JarHell {
|
|||
}
|
||||
if (path.toString().endsWith(".jar")) {
|
||||
if (!seenJars.add(path)) {
|
||||
throw new IllegalStateException("jar hell!" + System.lineSeparator() +
|
||||
"duplicate jar on classpath: " + path);
|
||||
throw new IllegalStateException("jar hell!" + System.lineSeparator() + "duplicate jar on classpath: " + path);
|
||||
}
|
||||
output.accept("examining jar: " + path);
|
||||
try (JarFile file = new JarFile(path.toString())) {
|
||||
|
@ -248,12 +252,12 @@ public class JarHell {
|
|||
public static void checkVersionFormat(String targetVersion) {
|
||||
if (!JavaVersion.isValid(targetVersion)) {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"version string must be a sequence of nonnegative decimal integers separated by \".\"'s and may have " +
|
||||
"leading zeros but was %s",
|
||||
targetVersion
|
||||
)
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"version string must be a sequence of nonnegative decimal integers separated by \".\"'s and may have "
|
||||
+ "leading zeros but was %s",
|
||||
targetVersion
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -266,13 +270,13 @@ public class JarHell {
|
|||
JavaVersion version = JavaVersion.parse(targetVersion);
|
||||
if (JavaVersion.current().compareTo(version) < 0) {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"%s requires Java %s:, your system: %s",
|
||||
resource,
|
||||
targetVersion,
|
||||
JavaVersion.current().toString()
|
||||
)
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"%s requires Java %s:, your system: %s",
|
||||
resource,
|
||||
targetVersion,
|
||||
JavaVersion.current().toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -291,14 +295,29 @@ public class JarHell {
|
|||
// throw a better exception in this ridiculous case.
|
||||
// unfortunately the zip file format allows this buggy possibility
|
||||
// UweSays: It can, but should be considered as bug :-)
|
||||
throw new IllegalStateException("jar hell!" + System.lineSeparator() +
|
||||
"class: " + clazz + System.lineSeparator() +
|
||||
"exists multiple times in jar: " + jarpath + " !!!!!!!!!");
|
||||
throw new IllegalStateException(
|
||||
"jar hell!"
|
||||
+ System.lineSeparator()
|
||||
+ "class: "
|
||||
+ clazz
|
||||
+ System.lineSeparator()
|
||||
+ "exists multiple times in jar: "
|
||||
+ jarpath
|
||||
+ " !!!!!!!!!"
|
||||
);
|
||||
} else {
|
||||
throw new IllegalStateException("jar hell!" + System.lineSeparator() +
|
||||
"class: " + clazz + System.lineSeparator() +
|
||||
"jar1: " + previous + System.lineSeparator() +
|
||||
"jar2: " + jarpath);
|
||||
throw new IllegalStateException(
|
||||
"jar hell!"
|
||||
+ System.lineSeparator()
|
||||
+ "class: "
|
||||
+ clazz
|
||||
+ System.lineSeparator()
|
||||
+ "jar1: "
|
||||
+ previous
|
||||
+ System.lineSeparator()
|
||||
+ "jar2: "
|
||||
+ jarpath
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,10 +104,8 @@ public class JavaVersion implements Comparable<JavaVersion> {
|
|||
for (int i = 0; i < len; i++) {
|
||||
int d = (i < version.size() ? version.get(i) : 0);
|
||||
int s = (i < o.version.size() ? o.version.get(i) : 0);
|
||||
if (s < d)
|
||||
return 1;
|
||||
if (s > d)
|
||||
return -1;
|
||||
if (s < d) return 1;
|
||||
if (s > d) return -1;
|
||||
}
|
||||
if (prePart != null && o.prePart == null) {
|
||||
return -1;
|
||||
|
@ -121,11 +119,9 @@ public class JavaVersion implements Comparable<JavaVersion> {
|
|||
|
||||
private int comparePrePart(String prePart, String otherPrePart) {
|
||||
if (prePart.matches("\\d+")) {
|
||||
return otherPrePart.matches("\\d+") ?
|
||||
(new BigInteger(prePart)).compareTo(new BigInteger(otherPrePart)) : -1;
|
||||
return otherPrePart.matches("\\d+") ? (new BigInteger(prePart)).compareTo(new BigInteger(otherPrePart)) : -1;
|
||||
} else {
|
||||
return otherPrePart.matches("\\d+") ?
|
||||
1 : prePart.compareTo(otherPrePart);
|
||||
return otherPrePart.matches("\\d+") ? 1 : prePart.compareTo(otherPrePart);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ public final class Booleans {
|
|||
}
|
||||
return parseBooleanLenient(value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code false} if text is in "false", "0", "off", "no"; else, {@code true}.
|
||||
*
|
||||
|
@ -178,8 +179,11 @@ public final class Booleans {
|
|||
return !(text[offset] == 'o' && text[offset + 1] == 'f' && text[offset + 2] == 'f');
|
||||
}
|
||||
if (length == 5) {
|
||||
return !(text[offset] == 'f' && text[offset + 1] == 'a' && text[offset + 2] == 'l' && text[offset + 3] == 's' &&
|
||||
text[offset + 4] == 'e');
|
||||
return !(text[offset] == 'f'
|
||||
&& text[offset + 1] == 'a'
|
||||
&& text[offset + 2] == 'l'
|
||||
&& text[offset + 3] == 's'
|
||||
&& text[offset + 4] == 'e');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -205,15 +209,18 @@ public final class Booleans {
|
|||
return (text[offset] == 'n' && text[offset + 1] == 'o') || (text[offset] == 'o' && text[offset + 1] == 'n');
|
||||
}
|
||||
if (length == 3) {
|
||||
return (text[offset] == 'o' && text[offset + 1] == 'f' && text[offset + 2] == 'f') ||
|
||||
(text[offset] == 'y' && text[offset + 1] == 'e' && text[offset + 2] == 's');
|
||||
return (text[offset] == 'o' && text[offset + 1] == 'f' && text[offset + 2] == 'f')
|
||||
|| (text[offset] == 'y' && text[offset + 1] == 'e' && text[offset + 2] == 's');
|
||||
}
|
||||
if (length == 4) {
|
||||
return (text[offset] == 't' && text[offset + 1] == 'r' && text[offset + 2] == 'u' && text[offset + 3] == 'e');
|
||||
}
|
||||
if (length == 5) {
|
||||
return (text[offset] == 'f' && text[offset + 1] == 'a' && text[offset + 2] == 'l' && text[offset + 3] == 's' &&
|
||||
text[offset + 4] == 'e');
|
||||
return (text[offset] == 'f'
|
||||
&& text[offset + 1] == 'a'
|
||||
&& text[offset + 2] == 'l'
|
||||
&& text[offset + 3] == 's'
|
||||
&& text[offset + 4] == 'e');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -75,9 +75,9 @@ public class Glob {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
return (str.length() >= firstIndex &&
|
||||
pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
|
||||
globMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
|
||||
return (str.length() >= firstIndex
|
||||
&& pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex))
|
||||
&& globMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,6 @@ import java.lang.annotation.Target;
|
|||
@TypeQualifierNickname
|
||||
@CheckForNull
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
|
||||
@Target({ ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD })
|
||||
public @interface Nullable {
|
||||
}
|
||||
|
|
|
@ -31,11 +31,11 @@
|
|||
|
||||
package org.opensearch.common;
|
||||
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to suppress forbidden-apis errors inside a whole class, a method, or a field.
|
||||
*/
|
||||
|
|
|
@ -69,7 +69,7 @@ public class List {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> java.util.List<T> of(T e1, T e2) {
|
||||
return List.of((T[]) new Object[]{e1, e2});
|
||||
return List.of((T[]) new Object[] { e1, e2 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -83,40 +83,92 @@ public class Map {
|
|||
/**
|
||||
* Returns an unmodifiable map containing six mappings.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6) {
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
|
||||
return mapN(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable map containing seven mappings.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7) {
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
|
||||
return mapN(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable map containing eight mappings.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8) {
|
||||
public static <K, V> java.util.Map<K, V> of(
|
||||
K k1,
|
||||
V v1,
|
||||
K k2,
|
||||
V v2,
|
||||
K k3,
|
||||
V v3,
|
||||
K k4,
|
||||
V v4,
|
||||
K k5,
|
||||
V v5,
|
||||
K k6,
|
||||
V v6,
|
||||
K k7,
|
||||
V v7,
|
||||
K k8,
|
||||
V v8
|
||||
) {
|
||||
return mapN(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable map containing nine mappings.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
|
||||
public static <K, V> java.util.Map<K, V> of(
|
||||
K k1,
|
||||
V v1,
|
||||
K k2,
|
||||
V v2,
|
||||
K k3,
|
||||
V v3,
|
||||
K k4,
|
||||
V v4,
|
||||
K k5,
|
||||
V v5,
|
||||
K k6,
|
||||
V v6,
|
||||
K k7,
|
||||
V v7,
|
||||
K k8,
|
||||
V v8,
|
||||
K k9,
|
||||
V v9
|
||||
) {
|
||||
return mapN(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable map containing ten mappings.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
|
||||
public static <K, V> java.util.Map<K, V> of(
|
||||
K k1,
|
||||
V v1,
|
||||
K k2,
|
||||
V v2,
|
||||
K k3,
|
||||
V v3,
|
||||
K k4,
|
||||
V v4,
|
||||
K k5,
|
||||
V v5,
|
||||
K k6,
|
||||
V v6,
|
||||
K k7,
|
||||
V v7,
|
||||
K k8,
|
||||
V v8,
|
||||
K k9,
|
||||
V v9,
|
||||
K k10,
|
||||
V v10
|
||||
) {
|
||||
return mapN(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10);
|
||||
}
|
||||
|
||||
|
@ -177,7 +229,7 @@ public class Map {
|
|||
* @param map a {@code Map} from which entries are drawn, must be non-null
|
||||
* @return a {@code Map} containing the entries of the given {@code Map}
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static <K, V> java.util.Map<K, V> copyOf(java.util.Map<? extends K, ? extends V> map) {
|
||||
return (java.util.Map<K, V>) Map.ofEntries(map.entrySet().toArray(new java.util.Map.Entry[0]));
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public class Set {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> java.util.Set<T> of(T e1, T e2) {
|
||||
return Set.of((T[]) new Object[]{e1, e2});
|
||||
return Set.of((T[]) new Object[] { e1, e2 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -98,7 +98,7 @@ public final class PathUtils {
|
|||
for (Path root : roots) {
|
||||
Path normalizedRoot = root.normalize();
|
||||
Path normalizedPath = normalizedRoot.resolve(path).normalize();
|
||||
if(normalizedPath.startsWith(normalizedRoot)) {
|
||||
if (normalizedPath.startsWith(normalizedRoot)) {
|
||||
return normalizedPath;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -395,8 +395,9 @@ public class TimeValue implements Comparable<TimeValue> {
|
|||
return TimeValue.ZERO;
|
||||
} else {
|
||||
// Missing units:
|
||||
throw new IllegalArgumentException("failed to parse setting [" + settingName + "] with value [" + sValue +
|
||||
"] as a time value: unit is missing or unrecognized");
|
||||
throw new IllegalArgumentException(
|
||||
"failed to parse setting [" + settingName + "] with value [" + sValue + "] as a time value: unit is missing or unrecognized"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,13 +407,19 @@ public class TimeValue implements Comparable<TimeValue> {
|
|||
final long value = Long.parseLong(s);
|
||||
if (value < -1) {
|
||||
// -1 is magic, but reject any other negative values
|
||||
throw new IllegalArgumentException("failed to parse setting [" + settingName + "] with value [" + initialInput +
|
||||
"] as a time value: negative durations are not supported");
|
||||
throw new IllegalArgumentException(
|
||||
"failed to parse setting ["
|
||||
+ settingName
|
||||
+ "] with value ["
|
||||
+ initialInput
|
||||
+ "] as a time value: negative durations are not supported"
|
||||
);
|
||||
}
|
||||
return value;
|
||||
} catch (final NumberFormatException e) {
|
||||
try {
|
||||
@SuppressWarnings("unused") final double ignored = Double.parseDouble(s);
|
||||
@SuppressWarnings("unused")
|
||||
final double ignored = Double.parseDouble(s);
|
||||
throw new IllegalArgumentException("failed to parse [" + initialInput + "], fractional time values are not supported", e);
|
||||
} catch (final NumberFormatException ignored) {
|
||||
throw new IllegalArgumentException("failed to parse [" + initialInput + "]", e);
|
||||
|
|
|
@ -50,22 +50,22 @@ package org.opensearch.common.util;
|
|||
*/
|
||||
final class FastMath {
|
||||
|
||||
private FastMath() { }
|
||||
private FastMath() {}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
// RE-USABLE CONSTANTS
|
||||
//--------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
private static final double ONE_DIV_F2 = 1/2.0;
|
||||
private static final double ONE_DIV_F3 = 1/6.0;
|
||||
private static final double ONE_DIV_F4 = 1/24.0;
|
||||
private static final double ONE_DIV_F2 = 1 / 2.0;
|
||||
private static final double ONE_DIV_F3 = 1 / 6.0;
|
||||
private static final double ONE_DIV_F4 = 1 / 24.0;
|
||||
private static final double TWO_POW_N28 = Double.longBitsToDouble(0x3E30000000000000L);
|
||||
private static final double TWO_POW_66 = Double.longBitsToDouble(0x4410000000000000L);
|
||||
private static final double LOG_DOUBLE_MAX_VALUE = StrictMath.log(Double.MAX_VALUE);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
// CONSTANTS AND TABLES FOR ATAN
|
||||
//--------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// We use the formula atan(-x) = -atan(x)
|
||||
// ---> we only have to compute atan(x) on [0,+infinity[.
|
||||
|
@ -75,9 +75,9 @@ final class FastMath {
|
|||
// Supposed to be >= tan(67.7deg), as fdlibm code is supposed to work with values > 2.4375.
|
||||
private static final double ATAN_MAX_VALUE_FOR_TABS = StrictMath.tan(Math.toRadians(74.0));
|
||||
|
||||
private static final int ATAN_TABS_SIZE = 1<<12 + 1;
|
||||
private static final double ATAN_DELTA = ATAN_MAX_VALUE_FOR_TABS/(ATAN_TABS_SIZE - 1);
|
||||
private static final double ATAN_INDEXER = 1/ATAN_DELTA;
|
||||
private static final int ATAN_TABS_SIZE = 1 << 12 + 1;
|
||||
private static final double ATAN_DELTA = ATAN_MAX_VALUE_FOR_TABS / (ATAN_TABS_SIZE - 1);
|
||||
private static final double ATAN_INDEXER = 1 / ATAN_DELTA;
|
||||
private static final double[] atanTab = new double[ATAN_TABS_SIZE];
|
||||
private static final double[] atanDer1DivF1Tab = new double[ATAN_TABS_SIZE];
|
||||
private static final double[] atanDer2DivF2Tab = new double[ATAN_TABS_SIZE];
|
||||
|
@ -86,32 +86,32 @@ final class FastMath {
|
|||
|
||||
private static final double ATAN_HI3 = Double.longBitsToDouble(0x3ff921fb54442d18L); // 1.57079632679489655800e+00 atan(inf)hi
|
||||
private static final double ATAN_LO3 = Double.longBitsToDouble(0x3c91a62633145c07L); // 6.12323399573676603587e-17 atan(inf)lo
|
||||
private static final double ATAN_AT0 = Double.longBitsToDouble(0x3fd555555555550dL); // 3.33333333333329318027e-01
|
||||
private static final double ATAN_AT0 = Double.longBitsToDouble(0x3fd555555555550dL); // 3.33333333333329318027e-01
|
||||
private static final double ATAN_AT1 = Double.longBitsToDouble(0xbfc999999998ebc4L); // -1.99999999998764832476e-01
|
||||
private static final double ATAN_AT2 = Double.longBitsToDouble(0x3fc24924920083ffL); // 1.42857142725034663711e-01
|
||||
private static final double ATAN_AT2 = Double.longBitsToDouble(0x3fc24924920083ffL); // 1.42857142725034663711e-01
|
||||
private static final double ATAN_AT3 = Double.longBitsToDouble(0xbfbc71c6fe231671L); // -1.11111104054623557880e-01
|
||||
private static final double ATAN_AT4 = Double.longBitsToDouble(0x3fb745cdc54c206eL); // 9.09088713343650656196e-02
|
||||
private static final double ATAN_AT4 = Double.longBitsToDouble(0x3fb745cdc54c206eL); // 9.09088713343650656196e-02
|
||||
private static final double ATAN_AT5 = Double.longBitsToDouble(0xbfb3b0f2af749a6dL); // -7.69187620504482999495e-02
|
||||
private static final double ATAN_AT6 = Double.longBitsToDouble(0x3fb10d66a0d03d51L); // 6.66107313738753120669e-02
|
||||
private static final double ATAN_AT6 = Double.longBitsToDouble(0x3fb10d66a0d03d51L); // 6.66107313738753120669e-02
|
||||
private static final double ATAN_AT7 = Double.longBitsToDouble(0xbfadde2d52defd9aL); // -5.83357013379057348645e-02
|
||||
private static final double ATAN_AT8 = Double.longBitsToDouble(0x3fa97b4b24760debL); // 4.97687799461593236017e-02
|
||||
private static final double ATAN_AT8 = Double.longBitsToDouble(0x3fa97b4b24760debL); // 4.97687799461593236017e-02
|
||||
private static final double ATAN_AT9 = Double.longBitsToDouble(0xbfa2b4442c6a6c2fL); // -3.65315727442169155270e-02
|
||||
private static final double ATAN_AT10 = Double.longBitsToDouble(0x3f90ad3ae322da11L); // 1.62858201153657823623e-02
|
||||
|
||||
static {
|
||||
// atan
|
||||
for (int i=0;i<ATAN_TABS_SIZE;i++) {
|
||||
for (int i = 0; i < ATAN_TABS_SIZE; i++) {
|
||||
// x: in [0,ATAN_MAX_VALUE_FOR_TABS].
|
||||
double x = i * ATAN_DELTA;
|
||||
double onePlusXSqInv = 1.0/(1+x*x);
|
||||
double onePlusXSqInv2 = onePlusXSqInv*onePlusXSqInv;
|
||||
double onePlusXSqInv3 = onePlusXSqInv2*onePlusXSqInv;
|
||||
double onePlusXSqInv4 = onePlusXSqInv2*onePlusXSqInv2;
|
||||
double onePlusXSqInv = 1.0 / (1 + x * x);
|
||||
double onePlusXSqInv2 = onePlusXSqInv * onePlusXSqInv;
|
||||
double onePlusXSqInv3 = onePlusXSqInv2 * onePlusXSqInv;
|
||||
double onePlusXSqInv4 = onePlusXSqInv2 * onePlusXSqInv2;
|
||||
atanTab[i] = StrictMath.atan(x);
|
||||
atanDer1DivF1Tab[i] = onePlusXSqInv;
|
||||
atanDer2DivF2Tab[i] = (-2*x*onePlusXSqInv2) * ONE_DIV_F2;
|
||||
atanDer3DivF3Tab[i] = ((-2+6*x*x)*onePlusXSqInv3) * ONE_DIV_F3;
|
||||
atanDer4DivF4Tab[i] = ((24*x*(1-x*x))*onePlusXSqInv4) * ONE_DIV_F4;
|
||||
atanDer2DivF2Tab[i] = (-2 * x * onePlusXSqInv2) * ONE_DIV_F2;
|
||||
atanDer3DivF3Tab[i] = ((-2 + 6 * x * x) * onePlusXSqInv3) * ONE_DIV_F3;
|
||||
atanDer4DivF4Tab[i] = ((24 * x * (1 - x * x)) * onePlusXSqInv4) * ONE_DIV_F4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,13 +136,13 @@ final class FastMath {
|
|||
} else {
|
||||
double t = Math.expm1(value);
|
||||
// Might be more accurate, if value < 1: return h*((t+t)-t*t/(t+1.0)).
|
||||
return h * (t + t/(t+1.0));
|
||||
return h * (t + t / (t + 1.0));
|
||||
}
|
||||
} else if (value < LOG_DOUBLE_MAX_VALUE) {
|
||||
return h * Math.exp(value);
|
||||
} else {
|
||||
double t = Math.exp(value*0.5);
|
||||
return (h*t)*t;
|
||||
double t = Math.exp(value * 0.5);
|
||||
return (h * t) * t;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,28 +162,28 @@ final class FastMath {
|
|||
}
|
||||
if (value == 1.0) {
|
||||
// We want "exact" result for 1.0.
|
||||
return negateResult ? -Math.PI/4 : Math.PI/4;
|
||||
return negateResult ? -Math.PI / 4 : Math.PI / 4;
|
||||
} else if (value <= ATAN_MAX_VALUE_FOR_TABS) {
|
||||
int index = (int)(value * ATAN_INDEXER + 0.5);
|
||||
int index = (int) (value * ATAN_INDEXER + 0.5);
|
||||
double delta = value - index * ATAN_DELTA;
|
||||
double result = atanTab[index] + delta * (atanDer1DivF1Tab[index] + delta * (atanDer2DivF2Tab[index]
|
||||
+ delta * (atanDer3DivF3Tab[index] + delta * atanDer4DivF4Tab[index])));
|
||||
double result = atanTab[index] + delta * (atanDer1DivF1Tab[index] + delta * (atanDer2DivF2Tab[index] + delta
|
||||
* (atanDer3DivF3Tab[index] + delta * atanDer4DivF4Tab[index])));
|
||||
return negateResult ? -result : result;
|
||||
} else { // value > ATAN_MAX_VALUE_FOR_TABS, or value is NaN
|
||||
// This part is derived from fdlibm.
|
||||
if (value < TWO_POW_66) {
|
||||
double x = -1/value;
|
||||
double x2 = x*x;
|
||||
double x4 = x2*x2;
|
||||
double s1 = x2*(ATAN_AT0+x4*(ATAN_AT2+x4*(ATAN_AT4+x4*(ATAN_AT6+x4*(ATAN_AT8+x4*ATAN_AT10)))));
|
||||
double s2 = x4*(ATAN_AT1+x4*(ATAN_AT3+x4*(ATAN_AT5+x4*(ATAN_AT7+x4*ATAN_AT9))));
|
||||
double result = ATAN_HI3-((x*(s1+s2)-ATAN_LO3)-x);
|
||||
double x = -1 / value;
|
||||
double x2 = x * x;
|
||||
double x4 = x2 * x2;
|
||||
double s1 = x2 * (ATAN_AT0 + x4 * (ATAN_AT2 + x4 * (ATAN_AT4 + x4 * (ATAN_AT6 + x4 * (ATAN_AT8 + x4 * ATAN_AT10)))));
|
||||
double s2 = x4 * (ATAN_AT1 + x4 * (ATAN_AT3 + x4 * (ATAN_AT5 + x4 * (ATAN_AT7 + x4 * ATAN_AT9))));
|
||||
double result = ATAN_HI3 - ((x * (s1 + s2) - ATAN_LO3) - x);
|
||||
return negateResult ? -result : result;
|
||||
} else { // value >= 2^66, or value is NaN
|
||||
if (Double.isNaN(value)) {
|
||||
return Double.NaN;
|
||||
} else {
|
||||
return negateResult ? -Math.PI/2 : Math.PI/2;
|
||||
return negateResult ? -Math.PI / 2 : Math.PI / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,6 @@ public abstract class AbstractRefCounted implements RefCounted {
|
|||
return this.refCount.get();
|
||||
}
|
||||
|
||||
|
||||
/** gets the name of this instance */
|
||||
public String getName() {
|
||||
return name;
|
||||
|
|
|
@ -164,7 +164,7 @@ public final class IOUtils {
|
|||
*/
|
||||
public static void closeWhileHandlingException(final Iterable<? extends Closeable> objects) {
|
||||
for (final Closeable object : objects) {
|
||||
closeWhileHandlingException(object);
|
||||
closeWhileHandlingException(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,8 +175,7 @@ public final class IOUtils {
|
|||
// noinspection EmptyCatchBlock
|
||||
try {
|
||||
close(closeable);
|
||||
} catch (final IOException | RuntimeException e) {
|
||||
}
|
||||
} catch (final IOException | RuntimeException e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,21 +211,17 @@ public final class IOUtils {
|
|||
* @throws IOException if any of the given files (or their sub-hierarchy files in case of directories) cannot be removed.
|
||||
*/
|
||||
public static void rm(final Path... locations) throws IOException {
|
||||
final LinkedHashMap<Path,Throwable> unremoved = rm(new LinkedHashMap<>(), locations);
|
||||
final LinkedHashMap<Path, Throwable> unremoved = rm(new LinkedHashMap<>(), locations);
|
||||
if (!unremoved.isEmpty()) {
|
||||
final StringBuilder b = new StringBuilder("could not remove the following files (in the order of attempts):\n");
|
||||
for (final Map.Entry<Path,Throwable> kv : unremoved.entrySet()) {
|
||||
b.append(" ")
|
||||
.append(kv.getKey().toAbsolutePath())
|
||||
.append(": ")
|
||||
.append(kv.getValue())
|
||||
.append("\n");
|
||||
for (final Map.Entry<Path, Throwable> kv : unremoved.entrySet()) {
|
||||
b.append(" ").append(kv.getKey().toAbsolutePath()).append(": ").append(kv.getValue()).append("\n");
|
||||
}
|
||||
throw new IOException(b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static LinkedHashMap<Path,Throwable> rm(final LinkedHashMap<Path,Throwable> unremoved, final Path... locations) {
|
||||
private static LinkedHashMap<Path, Throwable> rm(final LinkedHashMap<Path, Throwable> unremoved, final Path... locations) {
|
||||
if (locations != null) {
|
||||
for (final Path location : locations) {
|
||||
// TODO: remove this leniency
|
||||
|
@ -306,9 +301,9 @@ public final class IOUtils {
|
|||
file.force(true);
|
||||
} catch (final IOException e) {
|
||||
if (isDir) {
|
||||
assert (LINUX || MAC_OS_X) == false :
|
||||
"on Linux and MacOSX fsyncing a directory should not throw IOException, "+
|
||||
"we just don't want to rely on that in production (undocumented); got: " + e;
|
||||
assert (LINUX || MAC_OS_X) == false : "on Linux and MacOSX fsyncing a directory should not throw IOException, "
|
||||
+ "we just don't want to rely on that in production (undocumented); got: "
|
||||
+ e;
|
||||
// ignore exception if it is a directory
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,8 @@ public class NetUtils {
|
|||
if (keepalive.booleanValue()) {
|
||||
for (SocketOption<Integer> option : Arrays.asList(
|
||||
NetUtils.getTcpKeepIdleSocketOptionOrNull(),
|
||||
NetUtils.getTcpKeepIntervalSocketOptionOrNull())) {
|
||||
NetUtils.getTcpKeepIntervalSocketOptionOrNull()
|
||||
)) {
|
||||
setMinValueForSocketOption(socketChannel, option, 300);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,40 +79,92 @@ public class Map {
|
|||
/**
|
||||
* Delegates to the Java9 {@code Map.of()} method.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6) {
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
|
||||
return java.util.Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the Java9 {@code Map.of()} method.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7) {
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
|
||||
return java.util.Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the Java9 {@code Map.of()} method.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8) {
|
||||
public static <K, V> java.util.Map<K, V> of(
|
||||
K k1,
|
||||
V v1,
|
||||
K k2,
|
||||
V v2,
|
||||
K k3,
|
||||
V v3,
|
||||
K k4,
|
||||
V v4,
|
||||
K k5,
|
||||
V v5,
|
||||
K k6,
|
||||
V v6,
|
||||
K k7,
|
||||
V v7,
|
||||
K k8,
|
||||
V v8
|
||||
) {
|
||||
return java.util.Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the Java9 {@code Map.of()} method.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
|
||||
public static <K, V> java.util.Map<K, V> of(
|
||||
K k1,
|
||||
V v1,
|
||||
K k2,
|
||||
V v2,
|
||||
K k3,
|
||||
V v3,
|
||||
K k4,
|
||||
V v4,
|
||||
K k5,
|
||||
V v5,
|
||||
K k6,
|
||||
V v6,
|
||||
K k7,
|
||||
V v7,
|
||||
K k8,
|
||||
V v8,
|
||||
K k9,
|
||||
V v9
|
||||
) {
|
||||
return java.util.Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the Java9 {@code Map.of()} method.
|
||||
*/
|
||||
public static <K, V> java.util.Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
|
||||
public static <K, V> java.util.Map<K, V> of(
|
||||
K k1,
|
||||
V v1,
|
||||
K k2,
|
||||
V v2,
|
||||
K k3,
|
||||
V v3,
|
||||
K k4,
|
||||
V v4,
|
||||
K k5,
|
||||
V v5,
|
||||
K k6,
|
||||
V v6,
|
||||
K k7,
|
||||
V v7,
|
||||
K k8,
|
||||
V v8,
|
||||
K k9,
|
||||
V v9,
|
||||
K k10,
|
||||
V v10
|
||||
) {
|
||||
return java.util.Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,8 +76,7 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
|
||||
public void testDifferentJars() throws Exception {
|
||||
Path dir = createTempDir();
|
||||
Set<URL> jars = asSet(makeJar(dir, "foo.jar", null, "DuplicateClass.class"),
|
||||
makeJar(dir, "bar.jar", null, "DuplicateClass.class"));
|
||||
Set<URL> jars = asSet(makeJar(dir, "foo.jar", null, "DuplicateClass.class"), makeJar(dir, "bar.jar", null, "DuplicateClass.class"));
|
||||
try {
|
||||
JarHell.checkJarHell(jars, logger::debug);
|
||||
fail("did not get expected exception");
|
||||
|
@ -92,10 +91,7 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
public void testModuleInfo() throws Exception {
|
||||
Path dir = createTempDir();
|
||||
JarHell.checkJarHell(
|
||||
asSet(
|
||||
makeJar(dir, "foo.jar", null, "module-info.class"),
|
||||
makeJar(dir, "bar.jar", null, "module-info.class")
|
||||
),
|
||||
asSet(makeJar(dir, "foo.jar", null, "module-info.class"), makeJar(dir, "bar.jar", null, "module-info.class")),
|
||||
logger::debug
|
||||
);
|
||||
}
|
||||
|
@ -103,10 +99,7 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
public void testModuleInfoPackage() throws Exception {
|
||||
Path dir = createTempDir();
|
||||
JarHell.checkJarHell(
|
||||
asSet(
|
||||
makeJar(dir, "foo.jar", null, "foo/bar/module-info.class"),
|
||||
makeJar(dir, "bar.jar", null, "foo/bar/module-info.class")
|
||||
),
|
||||
asSet(makeJar(dir, "foo.jar", null, "foo/bar/module-info.class"), makeJar(dir, "bar.jar", null, "foo/bar/module-info.class")),
|
||||
logger::debug
|
||||
);
|
||||
}
|
||||
|
@ -114,8 +107,7 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
public void testDirsOnClasspath() throws Exception {
|
||||
Path dir1 = createTempDir();
|
||||
Path dir2 = createTempDir();
|
||||
Set<URL> dirs = asSet(makeFile(dir1, "DuplicateClass.class"),
|
||||
makeFile(dir2, "DuplicateClass.class"));
|
||||
Set<URL> dirs = asSet(makeFile(dir1, "DuplicateClass.class"), makeFile(dir2, "DuplicateClass.class"));
|
||||
try {
|
||||
JarHell.checkJarHell(dirs, logger::debug);
|
||||
fail("did not get expected exception");
|
||||
|
@ -130,8 +122,7 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
public void testDirAndJar() throws Exception {
|
||||
Path dir1 = createTempDir();
|
||||
Path dir2 = createTempDir();
|
||||
Set<URL> dirs = asSet(makeJar(dir1, "foo.jar", null, "DuplicateClass.class"),
|
||||
makeFile(dir2, "DuplicateClass.class"));
|
||||
Set<URL> dirs = asSet(makeJar(dir1, "foo.jar", null, "DuplicateClass.class"), makeFile(dir2, "DuplicateClass.class"));
|
||||
try {
|
||||
JarHell.checkJarHell(dirs, logger::debug);
|
||||
fail("did not get expected exception");
|
||||
|
@ -172,7 +163,6 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
}
|
||||
JavaVersion targetVersion = JavaVersion.parse(Strings.collectionToDelimitedString(target, "."));
|
||||
|
||||
|
||||
Manifest manifest = new Manifest();
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
|
||||
|
@ -198,8 +188,13 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
JarHell.checkJarHell(jars, logger::debug);
|
||||
fail("did not get expected exception");
|
||||
} catch (IllegalStateException e) {
|
||||
assertTrue(e.getMessage().equals("version string must be a sequence of nonnegative decimal integers separated " +
|
||||
"by \".\"'s and may have leading zeros but was bogus"));
|
||||
assertTrue(
|
||||
e.getMessage()
|
||||
.equals(
|
||||
"version string must be a sequence of nonnegative decimal integers separated "
|
||||
+ "by \".\"'s and may have leading zeros but was bogus"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,7 +209,7 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testValidVersions() {
|
||||
String[] versions = new String[]{"1.7", "1.7.0", "0.1.7", "1.7.0.80"};
|
||||
String[] versions = new String[] { "1.7", "1.7.0", "0.1.7", "1.7.0.80" };
|
||||
for (String version : versions) {
|
||||
try {
|
||||
JarHell.checkVersionFormat(version);
|
||||
|
@ -225,13 +220,12 @@ public class JarHellTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testInvalidVersions() {
|
||||
String[] versions = new String[]{"", "1.7.0_80", "1.7."};
|
||||
String[] versions = new String[] { "", "1.7.0_80", "1.7." };
|
||||
for (String version : versions) {
|
||||
try {
|
||||
JarHell.checkVersionFormat(version);
|
||||
fail("\"" + version + "\"" + " should be rejected as an invalid version format");
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
} catch (IllegalStateException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public class ListTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testStringListOfOne() {
|
||||
final String[] strings = {"foo"};
|
||||
final String[] strings = { "foo" };
|
||||
final java.util.List<String> stringsList = List.of(strings);
|
||||
assertThat(stringsList.size(), equalTo(strings.length));
|
||||
assertTrue(stringsList.containsAll(Arrays.asList(strings)));
|
||||
|
@ -58,7 +58,7 @@ public class ListTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testStringListOfTwo() {
|
||||
final String[] strings = {"foo", "bar"};
|
||||
final String[] strings = { "foo", "bar" };
|
||||
final java.util.List<String> stringsList = List.of(strings);
|
||||
assertThat(stringsList.size(), equalTo(strings.length));
|
||||
assertTrue(stringsList.containsAll(Arrays.asList(strings)));
|
||||
|
@ -66,7 +66,7 @@ public class ListTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testStringListOfN() {
|
||||
final String[] strings = {"foo", "bar", "baz"};
|
||||
final String[] strings = { "foo", "bar", "baz" };
|
||||
final java.util.List<String> stringsList = List.of(strings);
|
||||
assertThat(stringsList.size(), equalTo(strings.length));
|
||||
assertTrue(stringsList.containsAll(Arrays.asList(strings)));
|
||||
|
|
|
@ -38,7 +38,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
|||
|
||||
public class MapTests extends OpenSearchTestCase {
|
||||
|
||||
private static final String[] numbers = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
|
||||
private static final String[] numbers = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
|
||||
|
||||
public void testMapOfZero() {
|
||||
final java.util.Map<String, Integer> map = Map.of();
|
||||
|
@ -66,38 +66,117 @@ public class MapTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testMapOfFive() {
|
||||
final java.util.Map<String, Integer> map = Map.of(numbers[0], 0, numbers[1], 1, numbers[2], 2, numbers[3], 3,
|
||||
numbers[4], 4);
|
||||
final java.util.Map<String, Integer> map = Map.of(numbers[0], 0, numbers[1], 1, numbers[2], 2, numbers[3], 3, numbers[4], 4);
|
||||
validateMapContents(map, 5);
|
||||
}
|
||||
|
||||
public void testMapOfSix() {
|
||||
final java.util.Map<String, Integer> map = Map.of(numbers[0], 0, numbers[1], 1, numbers[2], 2, numbers[3], 3,
|
||||
numbers[4], 4, numbers[5], 5);
|
||||
final java.util.Map<String, Integer> map = Map.of(
|
||||
numbers[0],
|
||||
0,
|
||||
numbers[1],
|
||||
1,
|
||||
numbers[2],
|
||||
2,
|
||||
numbers[3],
|
||||
3,
|
||||
numbers[4],
|
||||
4,
|
||||
numbers[5],
|
||||
5
|
||||
);
|
||||
validateMapContents(map, 6);
|
||||
}
|
||||
|
||||
public void testMapOfSeven() {
|
||||
final java.util.Map<String, Integer> map = Map.of(numbers[0], 0, numbers[1], 1, numbers[2], 2, numbers[3], 3,
|
||||
numbers[4], 4, numbers[5], 5, numbers[6], 6);
|
||||
final java.util.Map<String, Integer> map = Map.of(
|
||||
numbers[0],
|
||||
0,
|
||||
numbers[1],
|
||||
1,
|
||||
numbers[2],
|
||||
2,
|
||||
numbers[3],
|
||||
3,
|
||||
numbers[4],
|
||||
4,
|
||||
numbers[5],
|
||||
5,
|
||||
numbers[6],
|
||||
6
|
||||
);
|
||||
validateMapContents(map, 7);
|
||||
}
|
||||
|
||||
public void testMapOfEight() {
|
||||
final java.util.Map<String, Integer> map = Map.of(numbers[0], 0, numbers[1], 1, numbers[2], 2, numbers[3], 3,
|
||||
numbers[4], 4, numbers[5], 5, numbers[6], 6, numbers[7], 7);
|
||||
final java.util.Map<String, Integer> map = Map.of(
|
||||
numbers[0],
|
||||
0,
|
||||
numbers[1],
|
||||
1,
|
||||
numbers[2],
|
||||
2,
|
||||
numbers[3],
|
||||
3,
|
||||
numbers[4],
|
||||
4,
|
||||
numbers[5],
|
||||
5,
|
||||
numbers[6],
|
||||
6,
|
||||
numbers[7],
|
||||
7
|
||||
);
|
||||
validateMapContents(map, 8);
|
||||
}
|
||||
|
||||
public void testMapOfNine() {
|
||||
final java.util.Map<String, Integer> map = Map.of(numbers[0], 0, numbers[1], 1, numbers[2], 2, numbers[3], 3,
|
||||
numbers[4], 4, numbers[5], 5, numbers[6], 6, numbers[7], 7, numbers[8], 8);
|
||||
final java.util.Map<String, Integer> map = Map.of(
|
||||
numbers[0],
|
||||
0,
|
||||
numbers[1],
|
||||
1,
|
||||
numbers[2],
|
||||
2,
|
||||
numbers[3],
|
||||
3,
|
||||
numbers[4],
|
||||
4,
|
||||
numbers[5],
|
||||
5,
|
||||
numbers[6],
|
||||
6,
|
||||
numbers[7],
|
||||
7,
|
||||
numbers[8],
|
||||
8
|
||||
);
|
||||
validateMapContents(map, 9);
|
||||
}
|
||||
|
||||
public void testMapOfTen() {
|
||||
final java.util.Map<String, Integer> map = Map.of(numbers[0], 0, numbers[1], 1, numbers[2], 2, numbers[3], 3,
|
||||
numbers[4], 4, numbers[5], 5, numbers[6], 6, numbers[7], 7, numbers[8], 8, numbers[9], 9);
|
||||
final java.util.Map<String, Integer> map = Map.of(
|
||||
numbers[0],
|
||||
0,
|
||||
numbers[1],
|
||||
1,
|
||||
numbers[2],
|
||||
2,
|
||||
numbers[3],
|
||||
3,
|
||||
numbers[4],
|
||||
4,
|
||||
numbers[5],
|
||||
5,
|
||||
numbers[6],
|
||||
6,
|
||||
numbers[7],
|
||||
7,
|
||||
numbers[8],
|
||||
8,
|
||||
numbers[9],
|
||||
9
|
||||
);
|
||||
validateMapContents(map, 10);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public class SetTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testStringSetOfOne() {
|
||||
final String[] strings = {"foo"};
|
||||
final String[] strings = { "foo" };
|
||||
final java.util.Set<String> stringsSet = Set.of(strings);
|
||||
assertThat(stringsSet.size(), equalTo(strings.length));
|
||||
assertTrue(stringsSet.containsAll(Arrays.asList(strings)));
|
||||
|
@ -58,7 +58,7 @@ public class SetTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testStringSetOfTwo() {
|
||||
final String[] strings = {"foo", "bar"};
|
||||
final String[] strings = { "foo", "bar" };
|
||||
final java.util.Set<String> stringsSet = Set.of(strings);
|
||||
assertThat(stringsSet.size(), equalTo(strings.length));
|
||||
assertTrue(stringsSet.containsAll(Arrays.asList(strings)));
|
||||
|
@ -66,7 +66,7 @@ public class SetTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testStringSetOfN() {
|
||||
final String[] strings = {"foo", "bar", "baz"};
|
||||
final String[] strings = { "foo", "bar", "baz" };
|
||||
final java.util.Set<String> stringsSet = Set.of(strings);
|
||||
assertThat(stringsSet.size(), equalTo(strings.length));
|
||||
assertTrue(stringsSet.containsAll(Arrays.asList(strings)));
|
||||
|
|
|
@ -89,57 +89,35 @@ public class TimeValueTests extends OpenSearchTestCase {
|
|||
|
||||
public void testParseTimeValue() {
|
||||
// Space is allowed before unit:
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS),
|
||||
TimeValue.parseTimeValue("10 ms", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS),
|
||||
TimeValue.parseTimeValue("10ms", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS),
|
||||
TimeValue.parseTimeValue("10 MS", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS),
|
||||
TimeValue.parseTimeValue("10MS", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS), TimeValue.parseTimeValue("10 ms", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS), TimeValue.parseTimeValue("10ms", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS), TimeValue.parseTimeValue("10 MS", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MILLISECONDS), TimeValue.parseTimeValue("10MS", null, "test"));
|
||||
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS),
|
||||
TimeValue.parseTimeValue("10 s", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS),
|
||||
TimeValue.parseTimeValue("10s", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS),
|
||||
TimeValue.parseTimeValue("10 S", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS),
|
||||
TimeValue.parseTimeValue("10S", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS), TimeValue.parseTimeValue("10 s", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS), TimeValue.parseTimeValue("10s", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS), TimeValue.parseTimeValue("10 S", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.SECONDS), TimeValue.parseTimeValue("10S", null, "test"));
|
||||
|
||||
assertEquals(new TimeValue(10, TimeUnit.MINUTES),
|
||||
TimeValue.parseTimeValue("10 m", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MINUTES),
|
||||
TimeValue.parseTimeValue("10m", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MINUTES), TimeValue.parseTimeValue("10 m", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.MINUTES), TimeValue.parseTimeValue("10m", null, "test"));
|
||||
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS),
|
||||
TimeValue.parseTimeValue("10 h", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS),
|
||||
TimeValue.parseTimeValue("10h", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS),
|
||||
TimeValue.parseTimeValue("10 H", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS),
|
||||
TimeValue.parseTimeValue("10H", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS), TimeValue.parseTimeValue("10 h", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS), TimeValue.parseTimeValue("10h", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS), TimeValue.parseTimeValue("10 H", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.HOURS), TimeValue.parseTimeValue("10H", null, "test"));
|
||||
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS),
|
||||
TimeValue.parseTimeValue("10 d", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS),
|
||||
TimeValue.parseTimeValue("10d", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS),
|
||||
TimeValue.parseTimeValue("10 D", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS),
|
||||
TimeValue.parseTimeValue("10D", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS), TimeValue.parseTimeValue("10 d", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS), TimeValue.parseTimeValue("10d", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS), TimeValue.parseTimeValue("10 D", null, "test"));
|
||||
assertEquals(new TimeValue(10, TimeUnit.DAYS), TimeValue.parseTimeValue("10D", null, "test"));
|
||||
|
||||
// Time values of months should throw an exception as months are not
|
||||
// supported. Note that this is the only unit that is not case sensitive
|
||||
// as `m` is the only character that is overloaded in terms of which
|
||||
// time unit is expected between the upper and lower case versions
|
||||
expectThrows(IllegalArgumentException.class, () -> {
|
||||
TimeValue.parseTimeValue("10 M", null, "test");
|
||||
});
|
||||
expectThrows(IllegalArgumentException.class, () -> {
|
||||
TimeValue.parseTimeValue("10M", null, "test");
|
||||
});
|
||||
expectThrows(IllegalArgumentException.class, () -> { TimeValue.parseTimeValue("10 M", null, "test"); });
|
||||
expectThrows(IllegalArgumentException.class, () -> { TimeValue.parseTimeValue("10M", null, "test"); });
|
||||
|
||||
final int length = randomIntBetween(0, 8);
|
||||
final String zeros = new String(new char[length]).replace('\0', '0');
|
||||
|
@ -158,8 +136,7 @@ public class TimeValueTests extends OpenSearchTestCase {
|
|||
|
||||
public void testNonFractionalTimeValues() {
|
||||
final String s = randomAlphaOfLength(10) + randomTimeUnit();
|
||||
final IllegalArgumentException e =
|
||||
expectThrows(IllegalArgumentException.class, () -> TimeValue.parseTimeValue(s, null, "test"));
|
||||
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> TimeValue.parseTimeValue(s, null, "test"));
|
||||
assertThat(e, hasToString(containsString("failed to parse [" + s + "]")));
|
||||
assertThat(e, not(hasToString(containsString(FRACTIONAL_TIME_VALUES_ARE_NOT_SUPPORTED))));
|
||||
assertThat(e.getCause(), instanceOf(NumberFormatException.class));
|
||||
|
@ -171,8 +148,7 @@ public class TimeValueTests extends OpenSearchTestCase {
|
|||
value = randomDouble();
|
||||
} while (value == 0);
|
||||
final String s = Double.toString(randomIntBetween(0, 128) + value) + randomTimeUnit();
|
||||
final IllegalArgumentException e =
|
||||
expectThrows(IllegalArgumentException.class, () -> TimeValue.parseTimeValue(s, null, "test"));
|
||||
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> TimeValue.parseTimeValue(s, null, "test"));
|
||||
assertThat(e, hasToString(containsString("failed to parse [" + s + "]")));
|
||||
assertThat(e, hasToString(containsString(FRACTIONAL_TIME_VALUES_ARE_NOT_SUPPORTED)));
|
||||
assertThat(e.getCause(), instanceOf(NumberFormatException.class));
|
||||
|
@ -239,7 +215,7 @@ public class TimeValueTests extends OpenSearchTestCase {
|
|||
|
||||
public void testCompareUnits() {
|
||||
long number = randomNonNegativeLong();
|
||||
TimeUnit randomUnit = randomValueOtherThan(TimeUnit.DAYS, ()->randomFrom(TimeUnit.values()));
|
||||
TimeUnit randomUnit = randomValueOtherThan(TimeUnit.DAYS, () -> randomFrom(TimeUnit.values()));
|
||||
TimeValue firstValue = new TimeValue(number, randomUnit);
|
||||
TimeValue secondValue = new TimeValue(number, TimeUnit.DAYS);
|
||||
assertTrue(firstValue.compareTo(secondValue) < 0);
|
||||
|
@ -256,11 +232,20 @@ public class TimeValueTests extends OpenSearchTestCase {
|
|||
final String settingName = "test-value";
|
||||
final long negativeValue = randomLongBetween(Long.MIN_VALUE, -2);
|
||||
final String negativeTimeValueString = Long.toString(negativeValue) + randomTimeUnit();
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> TimeValue.parseTimeValue(negativeTimeValueString, settingName));
|
||||
assertThat(ex.getMessage(),
|
||||
equalTo("failed to parse setting [" + settingName + "] with value [" + negativeTimeValueString +
|
||||
"] as a time value: negative durations are not supported"));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> TimeValue.parseTimeValue(negativeTimeValueString, settingName)
|
||||
);
|
||||
assertThat(
|
||||
ex.getMessage(),
|
||||
equalTo(
|
||||
"failed to parse setting ["
|
||||
+ settingName
|
||||
+ "] with value ["
|
||||
+ negativeTimeValueString
|
||||
+ "] as a time value: negative durations are not supported"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void testRejectsNegativeValuesAtCreation() {
|
||||
|
@ -270,7 +255,14 @@ public class TimeValueTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
private TimeUnit randomTimeUnitObject() {
|
||||
return randomFrom(TimeUnit.NANOSECONDS, TimeUnit.MICROSECONDS, TimeUnit.MILLISECONDS, TimeUnit.SECONDS,
|
||||
TimeUnit.MINUTES, TimeUnit.HOURS, TimeUnit.DAYS);
|
||||
return randomFrom(
|
||||
TimeUnit.NANOSECONDS,
|
||||
TimeUnit.MICROSECONDS,
|
||||
TimeUnit.MILLISECONDS,
|
||||
TimeUnit.SECONDS,
|
||||
TimeUnit.MINUTES,
|
||||
TimeUnit.HOURS,
|
||||
TimeUnit.DAYS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,8 +46,8 @@ public class OpenSearchSloppyMathTests extends OpenSearchTestCase {
|
|||
|
||||
public void testAtan() {
|
||||
assertTrue(Double.isNaN(atan(Double.NaN)));
|
||||
assertEquals(-Math.PI/2, atan(Double.NEGATIVE_INFINITY), ATAN_DELTA);
|
||||
assertEquals(Math.PI/2, atan(Double.POSITIVE_INFINITY), ATAN_DELTA);
|
||||
assertEquals(-Math.PI / 2, atan(Double.NEGATIVE_INFINITY), ATAN_DELTA);
|
||||
assertEquals(Math.PI / 2, atan(Double.POSITIVE_INFINITY), ATAN_DELTA);
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
assertEquals(StrictMath.atan(i), atan(i), ATAN_DELTA);
|
||||
assertEquals(StrictMath.atan(-i), atan(-i), ATAN_DELTA);
|
||||
|
|
|
@ -97,8 +97,8 @@ public class IOUtilsTests extends OpenSearchTestCase {
|
|||
runTestCloseWithIOExceptions((Function<Closeable[], List<Closeable>>) Arrays::asList, IOUtils::close);
|
||||
}
|
||||
|
||||
private <T> void runTestCloseWithIOExceptions(
|
||||
final Function<Closeable[], T> function, final CheckedConsumer<T, IOException> close) throws IOException {
|
||||
private <T> void runTestCloseWithIOExceptions(final Function<Closeable[], T> function, final CheckedConsumer<T, IOException> close)
|
||||
throws IOException {
|
||||
final int numberOfCloseables = randomIntBetween(1, 8);
|
||||
final Closeable[] closeables = new Closeable[numberOfCloseables];
|
||||
final List<Integer> indexesThatThrow = new ArrayList<>(numberOfCloseables);
|
||||
|
@ -137,7 +137,9 @@ public class IOUtilsTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
private <T> void runDeleteFilesIgnoringExceptionsTest(
|
||||
final Function<Path[], T> function, CheckedConsumer<T, IOException> deleteFilesIgnoringExceptions) throws IOException {
|
||||
final Function<Path[], T> function,
|
||||
CheckedConsumer<T, IOException> deleteFilesIgnoringExceptions
|
||||
) throws IOException {
|
||||
final int numberOfFiles = randomIntBetween(0, 7);
|
||||
final Path[] files = new Path[numberOfFiles];
|
||||
for (int i = 0; i < numberOfFiles; i++) {
|
||||
|
@ -170,8 +172,9 @@ public class IOUtilsTests extends OpenSearchTestCase {
|
|||
for (int i = 0; i < numberOfLocations; i++) {
|
||||
if (exception && randomBoolean()) {
|
||||
final Path location = createTempDir();
|
||||
final FileSystem fs =
|
||||
new AccessDeniedWhileDeletingFileSystem(location.getFileSystem()).getFileSystem(URI.create("file:///"));
|
||||
final FileSystem fs = new AccessDeniedWhileDeletingFileSystem(location.getFileSystem()).getFileSystem(
|
||||
URI.create("file:///")
|
||||
);
|
||||
final Path wrapped = new FilterPath(location, fs);
|
||||
locations[i] = wrapped.resolve(randomAlphaOfLength(8));
|
||||
Files.createDirectory(locations[i]);
|
||||
|
@ -241,10 +244,8 @@ public class IOUtilsTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public FileChannel newFileChannel(
|
||||
final Path path,
|
||||
final Set<? extends OpenOption> options,
|
||||
final FileAttribute<?>... attrs) throws IOException {
|
||||
public FileChannel newFileChannel(final Path path, final Set<? extends OpenOption> options, final FileAttribute<?>... attrs)
|
||||
throws IOException {
|
||||
if (Files.isDirectory(path)) {
|
||||
throw new AccessDeniedException(path.toString());
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ public final class DissectKey {
|
|||
* @param key The key to copy (except for the modifier)
|
||||
* @param modifier the modifer to use for this copy
|
||||
*/
|
||||
DissectKey(DissectKey key, DissectKey.Modifier modifier){
|
||||
DissectKey(DissectKey key, DissectKey.Modifier modifier) {
|
||||
this.modifier = modifier;
|
||||
this.skipRightPadding = key.skipRightPadding;
|
||||
this.skip = key.skip;
|
||||
|
@ -152,19 +152,29 @@ public final class DissectKey {
|
|||
return name;
|
||||
}
|
||||
|
||||
//generated
|
||||
// generated
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DissectKey{" +
|
||||
"modifier=" + modifier +
|
||||
", skip=" + skip +
|
||||
", appendPosition=" + appendPosition +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
return "DissectKey{"
|
||||
+ "modifier="
|
||||
+ modifier
|
||||
+ ", skip="
|
||||
+ skip
|
||||
+ ", appendPosition="
|
||||
+ appendPosition
|
||||
+ ", name='"
|
||||
+ name
|
||||
+ '\''
|
||||
+ '}';
|
||||
}
|
||||
|
||||
public enum Modifier {
|
||||
NONE(""), APPEND_WITH_ORDER("/"), APPEND("+"), FIELD_NAME("*"), FIELD_VALUE("&"), NAMED_SKIP("?");
|
||||
NONE(""),
|
||||
APPEND_WITH_ORDER("/"),
|
||||
APPEND("+"),
|
||||
FIELD_NAME("*"),
|
||||
FIELD_VALUE("&"),
|
||||
NAMED_SKIP("?");
|
||||
|
||||
private static final Pattern MODIFIER_PATTERN = Pattern.compile("[/+*&?]");
|
||||
|
||||
|
@ -179,10 +189,13 @@ public final class DissectKey {
|
|||
this.modifier = modifier;
|
||||
}
|
||||
|
||||
//package private for testing
|
||||
// package private for testing
|
||||
static Modifier fromString(String modifier) {
|
||||
return EnumSet.allOf(Modifier.class).stream().filter(km -> km.modifier.equals(modifier))
|
||||
.findFirst().orElseThrow(() -> new IllegalArgumentException("Found invalid modifier.")); //throw should never happen
|
||||
return EnumSet.allOf(Modifier.class)
|
||||
.stream()
|
||||
.filter(km -> km.modifier.equals(modifier))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Found invalid modifier.")); // throw should never happen
|
||||
}
|
||||
|
||||
private static Modifier findModifier(String key) {
|
||||
|
|
|
@ -59,7 +59,7 @@ final class DissectMatch {
|
|||
|
||||
DissectMatch(String appendSeparator, int maxMatches, int maxResults, int appendCount, int referenceCount) {
|
||||
if (maxMatches <= 0 || maxResults <= 0) {
|
||||
throw new IllegalArgumentException("Expected results are zero, can not construct DissectMatch");//should never happen
|
||||
throw new IllegalArgumentException("Expected results are zero, can not construct DissectMatch");// should never happen
|
||||
}
|
||||
this.maxMatches = maxMatches;
|
||||
this.maxResults = maxResults;
|
||||
|
@ -91,8 +91,8 @@ final class DissectMatch {
|
|||
appendResults.computeIfAbsent(key.getName(), k -> new AppendResult(appendSeparator)).addValue(value, implicitAppendOrder++);
|
||||
break;
|
||||
case APPEND_WITH_ORDER:
|
||||
appendResults.computeIfAbsent(key.getName(),
|
||||
k -> new AppendResult(appendSeparator)).addValue(value, key.getAppendPosition());
|
||||
appendResults.computeIfAbsent(key.getName(), k -> new AppendResult(appendSeparator))
|
||||
.addValue(value, key.getAppendPosition());
|
||||
break;
|
||||
case FIELD_NAME:
|
||||
referenceResults.computeIfAbsent(key.getName(), k -> new ReferenceResult()).setKey(value);
|
||||
|
|
|
@ -110,10 +110,12 @@ public final class DissectParser {
|
|||
private static final Pattern KEY_DELIMITER_FIELD_PATTERN = Pattern.compile("%\\{([^}]*?)}([^%]*)", Pattern.DOTALL);
|
||||
private static final EnumSet<DissectKey.Modifier> ASSOCIATE_MODIFIERS = EnumSet.of(
|
||||
DissectKey.Modifier.FIELD_NAME,
|
||||
DissectKey.Modifier.FIELD_VALUE);
|
||||
DissectKey.Modifier.FIELD_VALUE
|
||||
);
|
||||
private static final EnumSet<DissectKey.Modifier> APPEND_MODIFIERS = EnumSet.of(
|
||||
DissectKey.Modifier.APPEND,
|
||||
DissectKey.Modifier.APPEND_WITH_ORDER);
|
||||
DissectKey.Modifier.APPEND_WITH_ORDER
|
||||
);
|
||||
private static final Function<DissectPair, String> KEY_NAME = val -> val.getKey().getName();
|
||||
private final List<DissectPair> matchPairs;
|
||||
private final String pattern;
|
||||
|
@ -139,16 +141,19 @@ public final class DissectParser {
|
|||
matchPairs.add(new DissectPair(key, delimiter));
|
||||
}
|
||||
this.maxMatches = matchPairs.size();
|
||||
this.maxResults = Long.valueOf(matchPairs.stream()
|
||||
.filter(dissectPair -> !dissectPair.getKey().skip()).map(KEY_NAME).distinct().count()).intValue();
|
||||
this.maxResults = Long.valueOf(
|
||||
matchPairs.stream().filter(dissectPair -> !dissectPair.getKey().skip()).map(KEY_NAME).distinct().count()
|
||||
).intValue();
|
||||
if (this.maxMatches == 0 || maxResults == 0) {
|
||||
throw new DissectException.PatternParse(pattern, "Unable to find any keys or delimiters.");
|
||||
}
|
||||
//append validation - look through all of the keys to see if there are any keys that need to participate in an append operation
|
||||
// append validation - look through all of the keys to see if there are any keys that need to participate in an append operation
|
||||
// but don't have the '+' defined
|
||||
Set<String> appendKeyNames = matchPairs.stream()
|
||||
.filter(dissectPair -> APPEND_MODIFIERS.contains(dissectPair.getKey().getModifier()))
|
||||
.map(KEY_NAME).distinct().collect(Collectors.toSet());
|
||||
.map(KEY_NAME)
|
||||
.distinct()
|
||||
.collect(Collectors.toSet());
|
||||
if (appendKeyNames.size() > 0) {
|
||||
List<DissectPair> modifiedMatchPairs = new ArrayList<>(matchPairs.size());
|
||||
for (DissectPair p : matchPairs) {
|
||||
|
@ -162,15 +167,18 @@ public final class DissectParser {
|
|||
}
|
||||
appendCount = appendKeyNames.size();
|
||||
|
||||
//reference validation - ensure that '*' and '&' come in pairs
|
||||
// reference validation - ensure that '*' and '&' come in pairs
|
||||
Map<String, List<DissectPair>> referenceGroupings = matchPairs.stream()
|
||||
.filter(dissectPair -> ASSOCIATE_MODIFIERS.contains(dissectPair.getKey().getModifier()))
|
||||
.collect(Collectors.groupingBy(KEY_NAME));
|
||||
for (Map.Entry<String, List<DissectPair>> entry : referenceGroupings.entrySet()) {
|
||||
if (entry.getValue().size() != 2) {
|
||||
throw new DissectException.PatternParse(pattern, "Found invalid key/reference associations: '"
|
||||
+ entry.getValue().stream().map(KEY_NAME).collect(Collectors.joining(",")) +
|
||||
"' Please ensure each '*<key>' is matched with a matching '&<key>");
|
||||
throw new DissectException.PatternParse(
|
||||
pattern,
|
||||
"Found invalid key/reference associations: '"
|
||||
+ entry.getValue().stream().map(KEY_NAME).collect(Collectors.joining(","))
|
||||
+ "' Please ensure each '*<key>' is matched with a matching '&<key>"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +186,6 @@ public final class DissectParser {
|
|||
this.matchPairs = Collections.unmodifiableList(matchPairs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Entry point to dissect a string into it's parts.</p>
|
||||
*
|
||||
|
@ -210,38 +217,39 @@ public final class DissectParser {
|
|||
*/
|
||||
DissectMatch dissectMatch = new DissectMatch(appendSeparator, maxMatches, maxResults, appendCount, referenceCount);
|
||||
Iterator<DissectPair> it = matchPairs.iterator();
|
||||
//ensure leading delimiter matches
|
||||
if (inputString != null && inputString.length() > leadingDelimiter.length()
|
||||
// ensure leading delimiter matches
|
||||
if (inputString != null
|
||||
&& inputString.length() > leadingDelimiter.length()
|
||||
&& leadingDelimiter.equals(inputString.substring(0, leadingDelimiter.length()))) {
|
||||
byte[] input = inputString.getBytes(StandardCharsets.UTF_8);
|
||||
//grab the first key/delimiter pair
|
||||
// grab the first key/delimiter pair
|
||||
DissectPair dissectPair = it.next();
|
||||
DissectKey key = dissectPair.getKey();
|
||||
byte[] delimiter = dissectPair.getDelimiter().getBytes(StandardCharsets.UTF_8);
|
||||
//start dissection after the first delimiter
|
||||
// start dissection after the first delimiter
|
||||
int i = leadingDelimiter.length();
|
||||
int valueStart = i;
|
||||
int lookAheadMatches;
|
||||
//start walking the input string byte by byte, look ahead for matches where needed
|
||||
//if a match is found jump forward to the end of the match
|
||||
// start walking the input string byte by byte, look ahead for matches where needed
|
||||
// if a match is found jump forward to the end of the match
|
||||
for (; i < input.length; i++) {
|
||||
lookAheadMatches = 0;
|
||||
//potential match between delimiter and input string
|
||||
// potential match between delimiter and input string
|
||||
if (delimiter.length > 0 && input[i] == delimiter[0]) {
|
||||
//look ahead to see if the entire delimiter matches the input string
|
||||
// look ahead to see if the entire delimiter matches the input string
|
||||
for (int j = 0; j < delimiter.length; j++) {
|
||||
if (i + j < input.length && input[i + j] == delimiter[j]) {
|
||||
lookAheadMatches++;
|
||||
}
|
||||
}
|
||||
//found a full delimiter match
|
||||
// found a full delimiter match
|
||||
if (lookAheadMatches == delimiter.length) {
|
||||
//record the key/value tuple
|
||||
// record the key/value tuple
|
||||
byte[] value = Arrays.copyOfRange(input, valueStart, i);
|
||||
dissectMatch.add(key, new String(value, StandardCharsets.UTF_8));
|
||||
//jump to the end of the match
|
||||
// jump to the end of the match
|
||||
i += lookAheadMatches;
|
||||
//look for consecutive delimiters (e.g. a,,,,d,e)
|
||||
// look for consecutive delimiters (e.g. a,,,,d,e)
|
||||
while (i < input.length) {
|
||||
lookAheadMatches = 0;
|
||||
for (int j = 0; j < delimiter.length; j++) {
|
||||
|
@ -249,39 +257,39 @@ public final class DissectParser {
|
|||
lookAheadMatches++;
|
||||
}
|
||||
}
|
||||
//found consecutive delimiters
|
||||
// found consecutive delimiters
|
||||
if (lookAheadMatches == delimiter.length) {
|
||||
//jump to the end of the match
|
||||
// jump to the end of the match
|
||||
i += lookAheadMatches;
|
||||
if (!key.skipRightPadding()) {
|
||||
//progress the keys/delimiter if possible
|
||||
// progress the keys/delimiter if possible
|
||||
if (!it.hasNext()) {
|
||||
break; //the while loop
|
||||
break; // the while loop
|
||||
}
|
||||
dissectPair = it.next();
|
||||
key = dissectPair.getKey();
|
||||
//add the key with an empty value for the empty delimiter
|
||||
// add the key with an empty value for the empty delimiter
|
||||
dissectMatch.add(key, "");
|
||||
}
|
||||
} else {
|
||||
break; //the while loop
|
||||
break; // the while loop
|
||||
}
|
||||
}
|
||||
//progress the keys/delimiter if possible
|
||||
// progress the keys/delimiter if possible
|
||||
if (!it.hasNext()) {
|
||||
break; //the for loop
|
||||
break; // the for loop
|
||||
}
|
||||
dissectPair = it.next();
|
||||
key = dissectPair.getKey();
|
||||
delimiter = dissectPair.getDelimiter().getBytes(StandardCharsets.UTF_8);
|
||||
//i is always one byte after the last found delimiter, aka the start of the next value
|
||||
// i is always one byte after the last found delimiter, aka the start of the next value
|
||||
valueStart = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
//the last key, grab the rest of the input (unless consecutive delimiters already grabbed the last key)
|
||||
//and there is no trailing delimiter
|
||||
if (!dissectMatch.fullyMatched() && delimiter.length == 0 ) {
|
||||
// the last key, grab the rest of the input (unless consecutive delimiters already grabbed the last key)
|
||||
// and there is no trailing delimiter
|
||||
if (!dissectMatch.fullyMatched() && delimiter.length == 0) {
|
||||
byte[] value = Arrays.copyOfRange(input, valueStart, input.length);
|
||||
String valueString = new String(value, StandardCharsets.UTF_8);
|
||||
dissectMatch.add(key, valueString);
|
||||
|
@ -318,6 +326,3 @@ public final class DissectParser {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -135,7 +135,8 @@ public class DissectKeyTests extends OpenSearchTestCase {
|
|||
|
||||
public void testMultipleLeftModifiers() {
|
||||
String keyName = randomAlphaOfLengthBetween(1, 10);
|
||||
List<String> validModifiers = EnumSet.allOf(DissectKey.Modifier.class).stream()
|
||||
List<String> validModifiers = EnumSet.allOf(DissectKey.Modifier.class)
|
||||
.stream()
|
||||
.filter(m -> !m.equals(DissectKey.Modifier.NONE))
|
||||
.map(DissectKey.Modifier::toString)
|
||||
.collect(Collectors.toList());
|
||||
|
@ -154,9 +155,10 @@ public class DissectKeyTests extends OpenSearchTestCase {
|
|||
assertThat(dissectKey.getAppendPosition(), equalTo(0));
|
||||
assertThat(dissectKey.getName(), equalTo(keyName));
|
||||
}
|
||||
|
||||
public void testNamedSkipKey() {
|
||||
String keyName = "myname";
|
||||
DissectKey dissectKey = new DissectKey("?" +keyName);
|
||||
DissectKey dissectKey = new DissectKey("?" + keyName);
|
||||
assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NAMED_SKIP));
|
||||
assertThat(dissectKey.skip(), is(true));
|
||||
assertThat(dissectKey.skipRightPadding(), is(false));
|
||||
|
@ -166,16 +168,17 @@ public class DissectKeyTests extends OpenSearchTestCase {
|
|||
|
||||
public void testSkipKeyWithPadding() {
|
||||
String keyName = "";
|
||||
DissectKey dissectKey = new DissectKey(keyName + "->");
|
||||
DissectKey dissectKey = new DissectKey(keyName + "->");
|
||||
assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NONE));
|
||||
assertThat(dissectKey.skip(), is(true));
|
||||
assertThat(dissectKey.skipRightPadding(), is(true));
|
||||
assertThat(dissectKey.getAppendPosition(), equalTo(0));
|
||||
assertThat(dissectKey.getName(), equalTo(keyName));
|
||||
}
|
||||
|
||||
public void testNamedEmptySkipKeyWithPadding() {
|
||||
String keyName = "";
|
||||
DissectKey dissectKey = new DissectKey("?" +keyName + "->");
|
||||
DissectKey dissectKey = new DissectKey("?" + keyName + "->");
|
||||
assertThat(dissectKey.getModifier(), equalTo(DissectKey.Modifier.NAMED_SKIP));
|
||||
assertThat(dissectKey.skip(), is(true));
|
||||
assertThat(dissectKey.skipRightPadding(), is(true));
|
||||
|
@ -184,7 +187,7 @@ public class DissectKeyTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testInvalidModifiers() {
|
||||
//should never happen due to regex
|
||||
// should never happen due to regex
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> DissectKey.Modifier.fromString("x"));
|
||||
assertThat(e.getMessage(), CoreMatchers.containsString("invalid modifier"));
|
||||
}
|
||||
|
|
|
@ -51,8 +51,8 @@ public class DissectMatchTests extends OpenSearchTestCase {
|
|||
public void testValidAndFullyMatched() {
|
||||
int expectedMatches = randomIntBetween(1, 26);
|
||||
DissectMatch dissectMatch = new DissectMatch("", expectedMatches, expectedMatches, 0, 0);
|
||||
IntStream.range(97, 97 + expectedMatches) //allow for a-z values
|
||||
.forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[]{(byte) i}, StandardCharsets.UTF_8)), ""));
|
||||
IntStream.range(97, 97 + expectedMatches) // allow for a-z values
|
||||
.forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[] { (byte) i }, StandardCharsets.UTF_8)), ""));
|
||||
assertThat(dissectMatch.fullyMatched(), equalTo(true));
|
||||
assertThat(dissectMatch.isValid(dissectMatch.getResults()), equalTo(true));
|
||||
}
|
||||
|
@ -60,21 +60,21 @@ public class DissectMatchTests extends OpenSearchTestCase {
|
|||
public void testNotValidAndFullyMatched() {
|
||||
int expectedMatches = randomIntBetween(1, 26);
|
||||
DissectMatch dissectMatch = new DissectMatch("", expectedMatches, expectedMatches, 0, 0);
|
||||
IntStream.range(97, 97 + expectedMatches - 1) //allow for a-z values
|
||||
.forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[]{(byte) i}, StandardCharsets.UTF_8)), ""));
|
||||
IntStream.range(97, 97 + expectedMatches - 1) // allow for a-z values
|
||||
.forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[] { (byte) i }, StandardCharsets.UTF_8)), ""));
|
||||
assertThat(dissectMatch.fullyMatched(), equalTo(false));
|
||||
assertThat(dissectMatch.isValid(dissectMatch.getResults()), equalTo(false));
|
||||
}
|
||||
|
||||
public void testGetResultsIdempotent(){
|
||||
public void testGetResultsIdempotent() {
|
||||
int expectedMatches = randomIntBetween(1, 26);
|
||||
DissectMatch dissectMatch = new DissectMatch("", expectedMatches, expectedMatches, 0, 0);
|
||||
IntStream.range(97, 97 + expectedMatches) //allow for a-z values
|
||||
.forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[]{(byte) i}, StandardCharsets.UTF_8)), ""));
|
||||
IntStream.range(97, 97 + expectedMatches) // allow for a-z values
|
||||
.forEach(i -> dissectMatch.add(new DissectKey(new String(new byte[] { (byte) i }, StandardCharsets.UTF_8)), ""));
|
||||
assertThat(dissectMatch.getResults(), equalTo(dissectMatch.getResults()));
|
||||
}
|
||||
|
||||
public void testAppend(){
|
||||
public void testAppend() {
|
||||
DissectMatch dissectMatch = new DissectMatch("-", 3, 1, 3, 0);
|
||||
dissectMatch.add(new DissectKey("+a"), "x");
|
||||
dissectMatch.add(new DissectKey("+a"), "y");
|
||||
|
@ -84,7 +84,7 @@ public class DissectMatchTests extends OpenSearchTestCase {
|
|||
assertThat(results, equalTo(MapBuilder.newMapBuilder().put("a", "x-y-z").map()));
|
||||
}
|
||||
|
||||
public void testAppendWithOrder(){
|
||||
public void testAppendWithOrder() {
|
||||
DissectMatch dissectMatch = new DissectMatch("-", 3, 1, 3, 0);
|
||||
dissectMatch.add(new DissectKey("+a/3"), "x");
|
||||
dissectMatch.add(new DissectKey("+a"), "y");
|
||||
|
@ -94,7 +94,7 @@ public class DissectMatchTests extends OpenSearchTestCase {
|
|||
assertThat(results, equalTo(MapBuilder.newMapBuilder().put("a", "y-z-x").map()));
|
||||
}
|
||||
|
||||
public void testReference(){
|
||||
public void testReference() {
|
||||
DissectMatch dissectMatch = new DissectMatch("-", 2, 1, 0, 1);
|
||||
dissectMatch.add(new DissectKey("&a"), "x");
|
||||
dissectMatch.add(new DissectKey("*a"), "y");
|
||||
|
|
|
@ -77,46 +77,103 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
assertMatch("%{a} %{b} %{+b} %{z}", "foo bar baz quux", Arrays.asList("a", "b", "z"), Arrays.asList("foo", "bar baz", "quux"), " ");
|
||||
assertMatch("%{a}------->%{b}", "foo------->bar baz quux", Arrays.asList("a", "b"), Arrays.asList("foo", "bar baz quux"));
|
||||
assertMatch("%{a}------->%{}", "foo------->bar baz quux", Arrays.asList("a"), Arrays.asList("foo"));
|
||||
assertMatch("%{a} » %{b}»%{c}€%{d}", "foo » bar»baz€quux",
|
||||
Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "bar", "baz", "quux"));
|
||||
assertMatch(
|
||||
"%{a} » %{b}»%{c}€%{d}",
|
||||
"foo » bar»baz€quux",
|
||||
Arrays.asList("a", "b", "c", "d"),
|
||||
Arrays.asList("foo", "bar", "baz", "quux")
|
||||
);
|
||||
assertMatch("%{a} %{b} %{+a}", "foo bar baz quux", Arrays.asList("a", "b"), Arrays.asList("foo baz quux", "bar"), " ");
|
||||
//Logstash supports implicit ordering based anchored by the key without the '+'
|
||||
//This implementation will only honor implicit ordering for appending right to left else explicit order (/N) is required.
|
||||
//The results of this test differ from Logstash.
|
||||
assertMatch("%{+a} %{a} %{+a} %{b}", "December 31 1999 quux",
|
||||
Arrays.asList("a", "b"), Arrays.asList("December 31 1999", "quux"), " ");
|
||||
//Same test as above, but with same result as Logstash using explicit ordering in the pattern
|
||||
assertMatch("%{+a/1} %{a} %{+a/2} %{b}", "December 31 1999 quux",
|
||||
Arrays.asList("a", "b"), Arrays.asList("31 December 1999", "quux"), " ");
|
||||
// Logstash supports implicit ordering based anchored by the key without the '+'
|
||||
// This implementation will only honor implicit ordering for appending right to left else explicit order (/N) is required.
|
||||
// The results of this test differ from Logstash.
|
||||
assertMatch(
|
||||
"%{+a} %{a} %{+a} %{b}",
|
||||
"December 31 1999 quux",
|
||||
Arrays.asList("a", "b"),
|
||||
Arrays.asList("December 31 1999", "quux"),
|
||||
" "
|
||||
);
|
||||
// Same test as above, but with same result as Logstash using explicit ordering in the pattern
|
||||
assertMatch(
|
||||
"%{+a/1} %{a} %{+a/2} %{b}",
|
||||
"December 31 1999 quux",
|
||||
Arrays.asList("a", "b"),
|
||||
Arrays.asList("31 December 1999", "quux"),
|
||||
" "
|
||||
);
|
||||
assertMatch("%{+a/2} %{+a/4} %{+a/1} %{+a/3}", "bar quux foo baz", Arrays.asList("a"), Arrays.asList("foo bar baz quux"), " ");
|
||||
assertMatch("%{+a} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{+a} %{b} %{+a} %{c}", "foo bar baz quux",
|
||||
Arrays.asList("a", "b", "c"), Arrays.asList("foo baz", "bar", "quux"), " ");
|
||||
assertMatch("%{} %{syslog_timestamp} %{hostname} %{rt}: %{reason} %{+reason} %{src_ip}/%{src_port}->%{dst_ip}/%{dst_port} " +
|
||||
"%{polrt} %{+polrt} %{+polrt} %{from_zone} %{to_zone} %{rest}",
|
||||
"42 2016-05-25T14:47:23Z host.name.com RT_FLOW - RT_FLOW_SESSION_DENY: session denied 2.2.2.20/60000->1.1.1.10/8090 None " +
|
||||
"6(0) DEFAULT-DENY ZONE-UNTRUST ZONE-DMZ UNKNOWN UNKNOWN N/A(N/A) ge-0/0/0.0",
|
||||
Arrays.asList("syslog_timestamp", "hostname", "rt", "reason", "src_ip", "src_port", "dst_ip", "dst_port", "polrt"
|
||||
, "from_zone", "to_zone", "rest"),
|
||||
Arrays.asList("2016-05-25T14:47:23Z", "host.name.com", "RT_FLOW - RT_FLOW_SESSION_DENY", "session denied", "2.2.2.20", "60000"
|
||||
, "1.1.1.10", "8090", "None 6(0) DEFAULT-DENY", "ZONE-UNTRUST", "ZONE-DMZ", "UNKNOWN UNKNOWN N/A(N/A) ge-0/0/0.0"), " ");
|
||||
assertMatch(
|
||||
"%{+a} %{b} %{+a} %{c}",
|
||||
"foo bar baz quux",
|
||||
Arrays.asList("a", "b", "c"),
|
||||
Arrays.asList("foo baz", "bar", "quux"),
|
||||
" "
|
||||
);
|
||||
assertMatch(
|
||||
"%{} %{syslog_timestamp} %{hostname} %{rt}: %{reason} %{+reason} %{src_ip}/%{src_port}->%{dst_ip}/%{dst_port} "
|
||||
+ "%{polrt} %{+polrt} %{+polrt} %{from_zone} %{to_zone} %{rest}",
|
||||
"42 2016-05-25T14:47:23Z host.name.com RT_FLOW - RT_FLOW_SESSION_DENY: session denied 2.2.2.20/60000->1.1.1.10/8090 None "
|
||||
+ "6(0) DEFAULT-DENY ZONE-UNTRUST ZONE-DMZ UNKNOWN UNKNOWN N/A(N/A) ge-0/0/0.0",
|
||||
Arrays.asList(
|
||||
"syslog_timestamp",
|
||||
"hostname",
|
||||
"rt",
|
||||
"reason",
|
||||
"src_ip",
|
||||
"src_port",
|
||||
"dst_ip",
|
||||
"dst_port",
|
||||
"polrt",
|
||||
"from_zone",
|
||||
"to_zone",
|
||||
"rest"
|
||||
),
|
||||
Arrays.asList(
|
||||
"2016-05-25T14:47:23Z",
|
||||
"host.name.com",
|
||||
"RT_FLOW - RT_FLOW_SESSION_DENY",
|
||||
"session denied",
|
||||
"2.2.2.20",
|
||||
"60000",
|
||||
"1.1.1.10",
|
||||
"8090",
|
||||
"None 6(0) DEFAULT-DENY",
|
||||
"ZONE-UNTRUST",
|
||||
"ZONE-DMZ",
|
||||
"UNKNOWN UNKNOWN N/A(N/A) ge-0/0/0.0"
|
||||
),
|
||||
" "
|
||||
);
|
||||
assertBadKey("%{+/2}");
|
||||
assertBadKey("%{&+a_field}");
|
||||
assertMatch("%{a->} %{b->}---%{c}", "foo bar------------baz",
|
||||
Arrays.asList("a", "b", "c"), Arrays.asList("foo", "bar", "baz"));
|
||||
assertMatch(
|
||||
"%{a->} %{b->}---%{c}",
|
||||
"foo bar------------baz",
|
||||
Arrays.asList("a", "b", "c"),
|
||||
Arrays.asList("foo", "bar", "baz")
|
||||
);
|
||||
assertMatch("%{->}-%{a}", "-----666", Arrays.asList("a"), Arrays.asList("666"));
|
||||
assertMatch("%{?skipme->}-%{a}", "-----666", Arrays.asList("a"), Arrays.asList("666"));
|
||||
assertMatch("%{a},%{b},%{c},%{d},%{e},%{f}", "111,,333,,555,666",
|
||||
Arrays.asList("a", "b", "c", "d", "e", "f"), Arrays.asList("111", "", "333", "", "555", "666"));
|
||||
assertMatch(
|
||||
"%{a},%{b},%{c},%{d},%{e},%{f}",
|
||||
"111,,333,,555,666",
|
||||
Arrays.asList("a", "b", "c", "d", "e", "f"),
|
||||
Arrays.asList("111", "", "333", "", "555", "666")
|
||||
);
|
||||
assertMatch("%{a}.࿏.%{b}", "⟳༒.࿏.༒⟲", Arrays.asList("a", "b"), Arrays.asList("⟳༒", "༒⟲"));
|
||||
assertMatch("%{a}", "子", Arrays.asList("a"), Arrays.asList("子"));
|
||||
assertMatch("%{a}{\n}%{b}", "aaa{\n}bbb", Arrays.asList("a", "b"), Arrays.asList("aaa", "bbb"));
|
||||
assertMiss("MACHINE[%{a}] %{b}", "1234567890 MACHINE[foo] bar");
|
||||
assertMiss("%{a} %{b} %{c}", "foo:bar:baz");
|
||||
assertMatch("/var/%{key1}/log/%{key2}.log", "/var/foo/log/bar.log", Arrays.asList("key1", "key2"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{a->} %{b}-.-%{c}-%{d}-..-%{e}-%{f}-%{g}-%{h}", "foo bar-.-baz-1111-..-22-333-4444-55555",
|
||||
assertMatch(
|
||||
"%{a->} %{b}-.-%{c}-%{d}-..-%{e}-%{f}-%{g}-%{h}",
|
||||
"foo bar-.-baz-1111-..-22-333-4444-55555",
|
||||
Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h"),
|
||||
Arrays.asList("foo", "bar", "baz", "1111", "22", "333", "4444", "55555"));
|
||||
Arrays.asList("foo", "bar", "baz", "1111", "22", "333", "4444", "55555")
|
||||
);
|
||||
}
|
||||
|
||||
public void testBasicMatch() {
|
||||
|
@ -124,12 +181,13 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
String keyFirstPattern = "";
|
||||
String delimiterFirstInput = "";
|
||||
String delimiterFirstPattern = "";
|
||||
//parallel arrays
|
||||
// parallel arrays
|
||||
List<String> expectedKeys = new ArrayList<>(Sets.newSet(generateRandomStringArray(100, 10, false, false)));
|
||||
List<String> expectedValues = new ArrayList<>(expectedKeys.size());
|
||||
for (String key : expectedKeys) {
|
||||
String value = randomAsciiAlphanumOfLengthBetween(1, 100);
|
||||
String delimiter = Integer.toString(randomInt()); //int to ensures values and delimiters don't overlap, else validation can fail
|
||||
String delimiter = Integer.toString(randomInt()); // int to ensures values and delimiters don't overlap, else validation can
|
||||
// fail
|
||||
keyFirstPattern += "%{" + key + "}" + delimiter;
|
||||
valueFirstInput += value + delimiter;
|
||||
delimiterFirstPattern += delimiter + "%{" + key + "}";
|
||||
|
@ -145,7 +203,7 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
String keyFirstPattern = "";
|
||||
String delimiterFirstInput = "";
|
||||
String delimiterFirstPattern = "";
|
||||
//parallel arrays
|
||||
// parallel arrays
|
||||
List<String> expectedKeys = new ArrayList<>();
|
||||
List<String> expectedValues = new ArrayList<>();
|
||||
for (int i = 0; i < randomIntBetween(1, 100); i++) {
|
||||
|
@ -154,7 +212,8 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
key = randomAsciiAlphanumOfLengthBetween(1, 100);
|
||||
}
|
||||
String value = randomRealisticUnicodeOfCodepointLengthBetween(1, 100);
|
||||
String delimiter = Integer.toString(randomInt()); //int to ensures values and delimiters don't overlap, else validation can fail
|
||||
String delimiter = Integer.toString(randomInt()); // int to ensures values and delimiters don't overlap, else validation can
|
||||
// fail
|
||||
keyFirstPattern += "%{" + key + "}" + delimiter;
|
||||
valueFirstInput += value + delimiter;
|
||||
delimiterFirstPattern += delimiter + "%{" + key + "}";
|
||||
|
@ -196,8 +255,12 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
assertMatch("%{*a} %{&a}", "foo bar", Arrays.asList("foo"), Arrays.asList("bar"));
|
||||
assertMatch("%{&a} %{*a}", "foo bar", Arrays.asList("bar"), Arrays.asList("foo"));
|
||||
assertMatch("%{*a} %{&a} %{*b} %{&b}", "foo bar baz lol", Arrays.asList("foo", "baz"), Arrays.asList("bar", "lol"));
|
||||
assertMatch("%{*a} %{&a} %{c} %{*b} %{&b}", "foo bar x baz lol",
|
||||
Arrays.asList("foo", "baz", "c"), Arrays.asList("bar", "lol", "x"));
|
||||
assertMatch(
|
||||
"%{*a} %{&a} %{c} %{*b} %{&b}",
|
||||
"foo bar x baz lol",
|
||||
Arrays.asList("foo", "baz", "c"),
|
||||
Arrays.asList("bar", "lol", "x")
|
||||
);
|
||||
assertBadPattern("%{*a} %{a}");
|
||||
assertBadPattern("%{a} %{&a}");
|
||||
assertMiss("%{*a} %{&a} {a} %{*b} %{&b}", "foo bar x baz lol");
|
||||
|
@ -205,8 +268,12 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
|
||||
public void testAppendAndAssociate() {
|
||||
assertMatch("%{a} %{+a} %{*b} %{&b}", "foo bar baz lol", Arrays.asList("a", "baz"), Arrays.asList("foobar", "lol"));
|
||||
assertMatch("%{a->} %{+a/2} %{+a/1} %{*b} %{&b}", "foo bar baz lol x",
|
||||
Arrays.asList("a", "lol"), Arrays.asList("foobazbar", "x"));
|
||||
assertMatch(
|
||||
"%{a->} %{+a/2} %{+a/1} %{*b} %{&b}",
|
||||
"foo bar baz lol x",
|
||||
Arrays.asList("a", "lol"),
|
||||
Arrays.asList("foobazbar", "x")
|
||||
);
|
||||
}
|
||||
|
||||
public void testEmptyKey() {
|
||||
|
@ -230,19 +297,19 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testConsecutiveDelimiters() {
|
||||
//leading
|
||||
// leading
|
||||
assertMatch("%{->},%{a}", ",,,,,foo", Arrays.asList("a"), Arrays.asList("foo"));
|
||||
assertMatch("%{a->},%{b}", ",,,,,foo", Arrays.asList("a", "b"), Arrays.asList("", "foo"));
|
||||
//trailing
|
||||
// trailing
|
||||
assertMatch("%{a->},", "foo,,,,,", Arrays.asList("a"), Arrays.asList("foo"));
|
||||
assertMatch("%{a} %{b},", "foo bar,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{a} %{b->},", "foo bar,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
//middle
|
||||
// middle
|
||||
assertMatch("%{a->},%{b}", "foo,,,,,bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{a->} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{a->}x%{b}", "fooxxxxxbar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{a->} xyz%{b}", "foo xyz xyz xyz xyz xyzbar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
//skipped with empty values
|
||||
// skipped with empty values
|
||||
assertMatch("%{a},%{b},%{c},%{d}", "foo,,,", Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "", "", ""));
|
||||
assertMatch("%{a},%{b},%{c},%{d}", "foo,,bar,baz", Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "", "bar", "baz"));
|
||||
assertMatch("%{a},%{b},%{c},%{d}", "foo,,,baz", Arrays.asList("a", "b", "c", "d"), Arrays.asList("foo", "", "", "baz"));
|
||||
|
@ -259,16 +326,20 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
assertMatch("%{a->} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{a->} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{->} %{a}", "foo bar", Arrays.asList("a"), Arrays.asList("bar"));
|
||||
assertMatch("%{a->} %{+a->} %{*b->} %{&b->} %{c}", "foo bar baz lol x",
|
||||
Arrays.asList("a", "baz", "c"), Arrays.asList("foobar", "lol", "x"));
|
||||
assertMatch(
|
||||
"%{a->} %{+a->} %{*b->} %{&b->} %{c}",
|
||||
"foo bar baz lol x",
|
||||
Arrays.asList("a", "baz", "c"),
|
||||
Arrays.asList("foobar", "lol", "x")
|
||||
);
|
||||
}
|
||||
|
||||
public void testTrimmedEnd() {
|
||||
assertMatch("%{a} %{b}", "foo bar", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
assertMatch("%{a} %{b->} ", "foo bar ", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
//only whitespace is trimmed in the absence of trailing characters
|
||||
// only whitespace is trimmed in the absence of trailing characters
|
||||
assertMatch("%{a} %{b->}", "foo bar,,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar,,,,,,"));
|
||||
//consecutive delimiters + right padding can be used to skip over the trailing delimiters
|
||||
// consecutive delimiters + right padding can be used to skip over the trailing delimiters
|
||||
assertMatch("%{a} %{b->},", "foo bar,,,,,,", Arrays.asList("a", "b"), Arrays.asList("foo", "bar"));
|
||||
}
|
||||
|
||||
|
@ -305,23 +376,50 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testSyslog() {
|
||||
assertMatch("%{timestamp} %{+timestamp} %{+timestamp} %{logsource} %{program}[%{pid}]: %{message}",
|
||||
assertMatch(
|
||||
"%{timestamp} %{+timestamp} %{+timestamp} %{logsource} %{program}[%{pid}]: %{message}",
|
||||
"Mar 16 00:01:25 evita postfix/smtpd[1713]: connect from camomile.cloud9.net[168.100.1.3]",
|
||||
Arrays.asList("timestamp", "logsource", "program", "pid", "message"),
|
||||
Arrays.asList("Mar 16 00:01:25", "evita", "postfix/smtpd", "1713", "connect from camomile.cloud9.net[168.100.1.3]"), " ");
|
||||
Arrays.asList("Mar 16 00:01:25", "evita", "postfix/smtpd", "1713", "connect from camomile.cloud9.net[168.100.1.3]"),
|
||||
" "
|
||||
);
|
||||
}
|
||||
|
||||
public void testApacheLog() {
|
||||
assertMatch("%{clientip} %{ident} %{auth} [%{timestamp}] \"%{verb} %{request} HTTP/%{httpversion}\" %{response} %{bytes}" +
|
||||
" \"%{referrer}\" \"%{agent}\" %{->}",
|
||||
"31.184.238.164 - - [24/Jul/2014:05:35:37 +0530] \"GET /logs/access.log HTTP/1.0\" 200 69849 " +
|
||||
"\"http://8rursodiol.enjin.com\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36\" \"www.dlwindianrailways.com\"",
|
||||
Arrays.asList("clientip", "ident", "auth", "timestamp", "verb", "request", "httpversion", "response", "bytes",
|
||||
"referrer", "agent"),
|
||||
Arrays.asList("31.184.238.164", "-", "-", "24/Jul/2014:05:35:37 +0530", "GET", "/logs/access.log", "1.0", "200", "69849",
|
||||
"http://8rursodiol.enjin.com", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36" +
|
||||
" (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"));
|
||||
assertMatch(
|
||||
"%{clientip} %{ident} %{auth} [%{timestamp}] \"%{verb} %{request} HTTP/%{httpversion}\" %{response} %{bytes}"
|
||||
+ " \"%{referrer}\" \"%{agent}\" %{->}",
|
||||
"31.184.238.164 - - [24/Jul/2014:05:35:37 +0530] \"GET /logs/access.log HTTP/1.0\" 200 69849 "
|
||||
+ "\"http://8rursodiol.enjin.com\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
+ "Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36\" \"www.dlwindianrailways.com\"",
|
||||
Arrays.asList(
|
||||
"clientip",
|
||||
"ident",
|
||||
"auth",
|
||||
"timestamp",
|
||||
"verb",
|
||||
"request",
|
||||
"httpversion",
|
||||
"response",
|
||||
"bytes",
|
||||
"referrer",
|
||||
"agent"
|
||||
),
|
||||
Arrays.asList(
|
||||
"31.184.238.164",
|
||||
"-",
|
||||
"-",
|
||||
"24/Jul/2014:05:35:37 +0530",
|
||||
"GET",
|
||||
"/logs/access.log",
|
||||
"1.0",
|
||||
"200",
|
||||
"69849",
|
||||
"http://8rursodiol.enjin.com",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36"
|
||||
+ " (KHTML, like Gecko) Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -357,7 +455,7 @@ public class DissectParserTests extends OpenSearchTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private DissectException assertFail(String pattern, String input){
|
||||
private DissectException assertFail(String pattern, String input) {
|
||||
return expectThrows(DissectException.class, () -> new DissectParser(pattern, null).parse(input));
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ public class Circle implements Geometry {
|
|||
this.x = x;
|
||||
this.radiusMeters = radiusMeters;
|
||||
this.z = z;
|
||||
if (radiusMeters < 0 ) {
|
||||
if (radiusMeters < 0) {
|
||||
throw new IllegalArgumentException("Circle radius [" + radiusMeters + "] cannot be negative");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,8 +156,7 @@ public class Line implements Geometry {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Line line = (Line) o;
|
||||
return Arrays.equals(y, line.y) &&
|
||||
Arrays.equals(x, line.x) && Arrays.equals(z, line.z);
|
||||
return Arrays.equals(y, line.y) && Arrays.equals(x, line.x) && Arrays.equals(z, line.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -42,8 +42,7 @@ import java.util.Arrays;
|
|||
public class LinearRing extends Line {
|
||||
public static final LinearRing EMPTY = new LinearRing();
|
||||
|
||||
private LinearRing() {
|
||||
}
|
||||
private LinearRing() {}
|
||||
|
||||
public LinearRing(double[] x, double[] y) {
|
||||
this(x, y, null);
|
||||
|
@ -56,10 +55,22 @@ public class LinearRing extends Line {
|
|||
}
|
||||
int last = x.length - 1;
|
||||
if (x[0] != x[last] || y[0] != y[last] || (z != null && z[0] != z[last])) {
|
||||
throw new IllegalArgumentException("first and last points of the linear ring must be the same (it must close itself):" +
|
||||
" x[0]=" + x[0] + " x[" + last + "]=" + x[last] +
|
||||
" y[0]=" + y[0] + " y[" + last + "]=" + y[last] +
|
||||
(z == null ? "" : " z[0]=" + z[0] + " z[" + last + "]=" + z[last] ));
|
||||
throw new IllegalArgumentException(
|
||||
"first and last points of the linear ring must be the same (it must close itself):"
|
||||
+ " x[0]="
|
||||
+ x[0]
|
||||
+ " x["
|
||||
+ last
|
||||
+ "]="
|
||||
+ x[last]
|
||||
+ " y[0]="
|
||||
+ y[0]
|
||||
+ " y["
|
||||
+ last
|
||||
+ "]="
|
||||
+ y[last]
|
||||
+ (z == null ? "" : " z[0]=" + z[0] + " z[" + last + "]=" + z[last])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,8 +86,11 @@ public class LinearRing extends Line {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "linearring(x=" + Arrays.toString(getX()) +
|
||||
", y=" + Arrays.toString(getY()) +
|
||||
(hasZ() ? ", z=" + Arrays.toString(getZ()) : "") + ")";
|
||||
return "linearring(x="
|
||||
+ Arrays.toString(getX())
|
||||
+ ", y="
|
||||
+ Arrays.toString(getY())
|
||||
+ (hasZ() ? ", z=" + Arrays.toString(getZ()) : "")
|
||||
+ ")";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,7 @@ import java.util.List;
|
|||
public class MultiLine extends GeometryCollection<Line> {
|
||||
public static final MultiLine EMPTY = new MultiLine();
|
||||
|
||||
private MultiLine() {
|
||||
}
|
||||
private MultiLine() {}
|
||||
|
||||
public MultiLine(List<Line> lines) {
|
||||
super(lines);
|
||||
|
|
|
@ -40,8 +40,7 @@ import java.util.List;
|
|||
public class MultiPoint extends GeometryCollection<Point> {
|
||||
public static final MultiPoint EMPTY = new MultiPoint();
|
||||
|
||||
private MultiPoint() {
|
||||
}
|
||||
private MultiPoint() {}
|
||||
|
||||
public MultiPoint(List<Point> points) {
|
||||
super(points);
|
||||
|
|
|
@ -40,8 +40,7 @@ import java.util.List;
|
|||
public class MultiPolygon extends GeometryCollection<Polygon> {
|
||||
public static final MultiPolygon EMPTY = new MultiPolygon();
|
||||
|
||||
private MultiPolygon() {
|
||||
}
|
||||
private MultiPolygon() {}
|
||||
|
||||
public MultiPolygon(List<Polygon> polygons) {
|
||||
super(polygons);
|
||||
|
|
|
@ -135,8 +135,7 @@ public final class Polygon implements Geometry {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Polygon polygon1 = (Polygon) o;
|
||||
return Objects.equals(polygon, polygon1.polygon) &&
|
||||
Objects.equals(holes, polygon1.holes);
|
||||
return Objects.equals(polygon, polygon1.polygon) && Objects.equals(holes, polygon1.holes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -82,6 +82,7 @@ public class Rectangle implements Geometry {
|
|||
public Rectangle(double minX, double maxX, double maxY, double minY) {
|
||||
this(minX, maxX, maxY, minY, Double.NaN, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a bounding box by first validating the provided latitude and longitude coordinates
|
||||
*/
|
||||
|
@ -133,7 +134,6 @@ public class Rectangle implements Geometry {
|
|||
return minX;
|
||||
}
|
||||
|
||||
|
||||
public double getMinAlt() {
|
||||
return minZ;
|
||||
}
|
||||
|
@ -160,7 +160,6 @@ public class Rectangle implements Geometry {
|
|||
return WellKnownText.INSTANCE.toWKT(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Common Geometry classes
|
||||
*/
|
||||
|
|
|
@ -36,13 +36,15 @@ package org.opensearch.geometry.utils;
|
|||
*/
|
||||
public class BitUtil { // magic numbers for bit interleaving
|
||||
private static final long MAGIC[] = {
|
||||
0x5555555555555555L, 0x3333333333333333L,
|
||||
0x0F0F0F0F0F0F0F0FL, 0x00FF00FF00FF00FFL,
|
||||
0x0000FFFF0000FFFFL, 0x00000000FFFFFFFFL,
|
||||
0xAAAAAAAAAAAAAAAAL
|
||||
};
|
||||
0x5555555555555555L,
|
||||
0x3333333333333333L,
|
||||
0x0F0F0F0F0F0F0F0FL,
|
||||
0x00FF00FF00FF00FFL,
|
||||
0x0000FFFF0000FFFFL,
|
||||
0x00000000FFFFFFFFL,
|
||||
0xAAAAAAAAAAAAAAAAL };
|
||||
// shift values for bit interleaving
|
||||
private static final short SHIFT[] = {1, 2, 4, 8, 16};
|
||||
private static final short SHIFT[] = { 1, 2, 4, 8, 16 };
|
||||
|
||||
/**
|
||||
* Interleaves the first 32 bits of each long value
|
||||
|
@ -63,7 +65,7 @@ public class BitUtil { // magic numbers for bit interleaving
|
|||
v2 = (v2 | (v2 << SHIFT[1])) & MAGIC[1];
|
||||
v2 = (v2 | (v2 << SHIFT[0])) & MAGIC[0];
|
||||
|
||||
return (v2<<1) | v1;
|
||||
return (v2 << 1) | v1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,6 +85,6 @@ public class BitUtil { // magic numbers for bit interleaving
|
|||
* flip flops odd with even bits
|
||||
*/
|
||||
public static final long flipFlop(final long b) {
|
||||
return ((b & MAGIC[6]) >>> 1) | ((b & MAGIC[0]) << 1 );
|
||||
return ((b & MAGIC[6]) >>> 1) | ((b & MAGIC[0]) << 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,8 @@ public class GeographyValidator implements GeometryValidator {
|
|||
protected void checkLatitude(double latitude) {
|
||||
if (Double.isNaN(latitude) || latitude < MIN_LAT_INCL || latitude > MAX_LAT_INCL) {
|
||||
throw new IllegalArgumentException(
|
||||
"invalid latitude " + latitude + "; must be between " + MIN_LAT_INCL + " and " + MAX_LAT_INCL);
|
||||
"invalid latitude " + latitude + "; must be between " + MIN_LAT_INCL + " and " + MAX_LAT_INCL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,14 +94,16 @@ public class GeographyValidator implements GeometryValidator {
|
|||
protected void checkLongitude(double longitude) {
|
||||
if (Double.isNaN(longitude) || longitude < MIN_LON_INCL || longitude > MAX_LON_INCL) {
|
||||
throw new IllegalArgumentException(
|
||||
"invalid longitude " + longitude + "; must be between " + MIN_LON_INCL + " and " + MAX_LON_INCL);
|
||||
"invalid longitude " + longitude + "; must be between " + MIN_LON_INCL + " and " + MAX_LON_INCL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkAltitude(double zValue) {
|
||||
if (ignoreZValue == false && Double.isNaN(zValue) == false) {
|
||||
throw new IllegalArgumentException("found Z value [" + zValue + "] but [ignore_z_value] "
|
||||
+ "parameter is [" + ignoreZValue + "]");
|
||||
throw new IllegalArgumentException(
|
||||
"found Z value [" + zValue + "] but [ignore_z_value] " + "parameter is [" + ignoreZValue + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,21 +48,51 @@ import java.util.Collection;
|
|||
* NOTE: this will replace {@code org.opensearch.common.geo.GeoHashUtils}
|
||||
*/
|
||||
public class Geohash {
|
||||
private static final char[] BASE_32 = {'0', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
|
||||
private static final char[] BASE_32 = {
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'b',
|
||||
'c',
|
||||
'd',
|
||||
'e',
|
||||
'f',
|
||||
'g',
|
||||
'h',
|
||||
'j',
|
||||
'k',
|
||||
'm',
|
||||
'n',
|
||||
'p',
|
||||
'q',
|
||||
'r',
|
||||
's',
|
||||
't',
|
||||
'u',
|
||||
'v',
|
||||
'w',
|
||||
'x',
|
||||
'y',
|
||||
'z' };
|
||||
|
||||
private static final String BASE_32_STRING = new String(BASE_32);
|
||||
/** maximum precision for geohash strings */
|
||||
public static final int PRECISION = 12;
|
||||
/** number of bits used for quantizing latitude and longitude values */
|
||||
private static final short BITS = 32;
|
||||
private static final double LAT_SCALE = (0x1L<<(BITS-1))/180.0D;
|
||||
private static final double LAT_DECODE = 180.0D/(0x1L<<BITS);
|
||||
private static final double LON_SCALE = (0x1L<<(BITS-1))/360.0D;
|
||||
private static final double LON_DECODE = 360.0D/(0x1L<<BITS);
|
||||
private static final double LAT_SCALE = (0x1L << (BITS - 1)) / 180.0D;
|
||||
private static final double LAT_DECODE = 180.0D / (0x1L << BITS);
|
||||
private static final double LON_SCALE = (0x1L << (BITS - 1)) / 360.0D;
|
||||
private static final double LON_DECODE = 360.0D / (0x1L << BITS);
|
||||
|
||||
private static final short MORTON_OFFSET = (BITS<<1) - (PRECISION*5);
|
||||
private static final short MORTON_OFFSET = (BITS << 1) - (PRECISION * 5);
|
||||
/** Bit encoded representation of the latitude of north pole */
|
||||
private static final long MAX_LAT_BITS = (0x1L << (PRECISION * 5 / 2)) - 1;
|
||||
|
||||
|
@ -71,19 +101,18 @@ public class Geohash {
|
|||
static {
|
||||
precisionToLatHeight = new double[PRECISION + 1];
|
||||
precisionToLonWidth = new double[PRECISION + 1];
|
||||
precisionToLatHeight[0] = 90*2;
|
||||
precisionToLonWidth[0] = 180*2;
|
||||
precisionToLatHeight[0] = 90 * 2;
|
||||
precisionToLonWidth[0] = 180 * 2;
|
||||
boolean even = false;
|
||||
for(int i = 1; i <= PRECISION; i++) {
|
||||
precisionToLatHeight[i] = precisionToLatHeight[i-1] / (even ? 8 : 4);
|
||||
precisionToLonWidth[i] = precisionToLonWidth[i-1] / (even ? 4 : 8);
|
||||
even = ! even;
|
||||
for (int i = 1; i <= PRECISION; i++) {
|
||||
precisionToLatHeight[i] = precisionToLatHeight[i - 1] / (even ? 8 : 4);
|
||||
precisionToLonWidth[i] = precisionToLonWidth[i - 1] / (even ? 4 : 8);
|
||||
even = !even;
|
||||
}
|
||||
}
|
||||
|
||||
// no instance:
|
||||
private Geohash() {
|
||||
}
|
||||
private Geohash() {}
|
||||
|
||||
/** Returns a {@link Point} instance from a geohash string */
|
||||
public static Point toPoint(final String geohash) throws IllegalArgumentException {
|
||||
|
@ -110,14 +139,14 @@ public class Geohash {
|
|||
final int shift = (12 - len) * 5 + 2;
|
||||
if (lat < MAX_LAT_BITS) {
|
||||
// add 1 to lat and lon to get topRight
|
||||
ghLong = BitUtil.interleave((int)(lat + 1), (int)(lon + 1)) << 4 | len;
|
||||
ghLong = BitUtil.interleave((int) (lat + 1), (int) (lon + 1)) << 4 | len;
|
||||
final long mortonHash = BitUtil.flipFlop((ghLong >>> 4) << shift);
|
||||
Point topRight = new Point(decodeLongitude(mortonHash), decodeLatitude(mortonHash));
|
||||
return new Rectangle(bottomLeft.getX(), topRight.getX(), topRight.getY(), bottomLeft.getY());
|
||||
} else {
|
||||
// We cannot go north of north pole, so just using 90 degrees instead of calculating it using
|
||||
// add 1 to lon to get lon of topRight, we are going to use 90 for lat
|
||||
ghLong = BitUtil.interleave((int)lat, (int)(lon + 1)) << 4 | len;
|
||||
ghLong = BitUtil.interleave((int) lat, (int) (lon + 1)) << 4 | len;
|
||||
final long mortonHash = BitUtil.flipFlop((ghLong >>> 4) << shift);
|
||||
Point topRight = new Point(decodeLongitude(mortonHash), decodeLatitude(mortonHash));
|
||||
return new Rectangle(bottomLeft.getX(), topRight.getX(), 90D, bottomLeft.getY());
|
||||
|
@ -127,9 +156,9 @@ public class Geohash {
|
|||
/** Array of geohashes one level below the baseGeohash. Sorted. */
|
||||
public static String[] getSubGeohashes(String baseGeohash) {
|
||||
String[] hashes = new String[BASE_32.length];
|
||||
for (int i = 0; i < BASE_32.length; i++) {//note: already sorted
|
||||
for (int i = 0; i < BASE_32.length; i++) {// note: already sorted
|
||||
char c = BASE_32[i];
|
||||
hashes[i] = baseGeohash+c;
|
||||
hashes[i] = baseGeohash + c;
|
||||
}
|
||||
return hashes;
|
||||
}
|
||||
|
@ -143,6 +172,7 @@ public class Geohash {
|
|||
public static Collection<? extends CharSequence> getNeighbors(String geohash) {
|
||||
return addNeighborsAtLevel(geohash, geohash.length(), new ArrayList<CharSequence>(8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all geohashes of the cells next to a given geohash to a list.
|
||||
*
|
||||
|
@ -162,8 +192,7 @@ public class Geohash {
|
|||
* @param neighbors list to add the neighbors to
|
||||
* @return the given list
|
||||
*/
|
||||
public static final <E extends Collection<? super String>> E addNeighborsAtLevel(String geohash,
|
||||
int level, E neighbors) {
|
||||
public static final <E extends Collection<? super String>> E addNeighborsAtLevel(String geohash, int level, E neighbors) {
|
||||
String south = getNeighbor(geohash, level, 0, -1);
|
||||
String north = getNeighbor(geohash, level, 0, +1);
|
||||
if (north != null) {
|
||||
|
@ -194,7 +223,7 @@ public class Geohash {
|
|||
* @return geohash of the defined cell
|
||||
*/
|
||||
public static final String getNeighbor(String geohash, int level, int dx, int dy) {
|
||||
int cell = BASE_32_STRING.indexOf(geohash.charAt(level -1));
|
||||
int cell = BASE_32_STRING.indexOf(geohash.charAt(level - 1));
|
||||
|
||||
// Decoding the Geohash bit pattern to determine grid coordinates
|
||||
int x0 = cell & 1; // first bit of x
|
||||
|
@ -250,7 +279,7 @@ public class Geohash {
|
|||
*/
|
||||
public static final long longEncode(final double lon, final double lat, final int level) {
|
||||
// shift to appropriate level
|
||||
final short msf = (short)(((12 - level) * 5) + (MORTON_OFFSET - 2));
|
||||
final short msf = (short) (((12 - level) * 5) + (MORTON_OFFSET - 2));
|
||||
return ((encodeLatLon(lat, lon) >>> msf) << 4) | level;
|
||||
}
|
||||
|
||||
|
@ -276,13 +305,13 @@ public class Geohash {
|
|||
* Encode to a geohash string from the geohash based long format
|
||||
*/
|
||||
public static final String stringEncode(long geoHashLong) {
|
||||
int level = (int)geoHashLong&15;
|
||||
int level = (int) geoHashLong & 15;
|
||||
geoHashLong >>>= 4;
|
||||
char[] chars = new char[level];
|
||||
do {
|
||||
chars[--level] = BASE_32[(int) (geoHashLong&31L)];
|
||||
geoHashLong>>>=5;
|
||||
} while(level > 0);
|
||||
chars[--level] = BASE_32[(int) (geoHashLong & 31L)];
|
||||
geoHashLong >>>= 5;
|
||||
} while (level > 0);
|
||||
|
||||
return new String(chars);
|
||||
}
|
||||
|
@ -299,9 +328,9 @@ public class Geohash {
|
|||
int level = length - 1;
|
||||
long b;
|
||||
long l = 0L;
|
||||
for(char c : hash.toCharArray()) {
|
||||
b = (long)(BASE_32_STRING.indexOf(c));
|
||||
l |= (b<<(level--*5));
|
||||
for (char c : hash.toCharArray()) {
|
||||
b = (long) (BASE_32_STRING.indexOf(c));
|
||||
l |= (b << (level-- * 5));
|
||||
if (level < 0) {
|
||||
// We cannot handle more than 12 levels
|
||||
break;
|
||||
|
@ -320,12 +349,12 @@ public class Geohash {
|
|||
int level = 11;
|
||||
long b;
|
||||
long l = 0L;
|
||||
for(char c : hash.toCharArray()) {
|
||||
b = (long)(BASE_32_STRING.indexOf(c));
|
||||
for (char c : hash.toCharArray()) {
|
||||
b = (long) (BASE_32_STRING.indexOf(c));
|
||||
if (b < 0) {
|
||||
throw new IllegalArgumentException("unsupported symbol [" + c + "] in geohash [" + hash + "]");
|
||||
}
|
||||
l |= (b<<((level--*5) + (MORTON_OFFSET - 2)));
|
||||
l |= (b << ((level-- * 5) + (MORTON_OFFSET - 2)));
|
||||
if (level < 0) {
|
||||
// We cannot handle more than 12 levels
|
||||
break;
|
||||
|
@ -351,7 +380,6 @@ public class Geohash {
|
|||
return BitUtil.interleave(latEnc, lonEnc) >>> 2;
|
||||
}
|
||||
|
||||
|
||||
/** encode latitude to integer */
|
||||
public static int encodeLatitude(double latitude) {
|
||||
// the maximum possible value cannot be encoded without overflow
|
||||
|
|
|
@ -53,13 +53,14 @@ public class StandardValidator implements GeometryValidator {
|
|||
private final boolean ignoreZValue;
|
||||
|
||||
public StandardValidator(boolean ignoreZValue) {
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
}
|
||||
|
||||
protected void checkZ(double zValue) {
|
||||
if (ignoreZValue == false && Double.isNaN(zValue) == false) {
|
||||
throw new IllegalArgumentException("found Z value [" + zValue + "] but [ignore_z_value] "
|
||||
+ "parameter is [" + ignoreZValue + "]");
|
||||
throw new IllegalArgumentException(
|
||||
"found Z value [" + zValue + "] but [ignore_z_value] " + "parameter is [" + ignoreZValue + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,4 +139,3 @@ public class StandardValidator implements GeometryValidator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -446,8 +446,9 @@ public class WellKnownText {
|
|||
private void closeLinearRingIfCoerced(ArrayList<Double> lats, ArrayList<Double> lons, ArrayList<Double> alts) {
|
||||
if (coerce && lats.isEmpty() == false && lons.isEmpty() == false) {
|
||||
int last = lats.size() - 1;
|
||||
if (!lats.get(0).equals(lats.get(last)) || !lons.get(0).equals(lons.get(last)) ||
|
||||
(alts.isEmpty() == false && !alts.get(0).equals(alts.get(last)))) {
|
||||
if (!lats.get(0).equals(lats.get(last))
|
||||
|| !lons.get(0).equals(lons.get(last))
|
||||
|| (alts.isEmpty() == false && !alts.get(0).equals(alts.get(last)))) {
|
||||
lons.add(lons.get(0));
|
||||
lats.add(lats.get(0));
|
||||
if (alts.isEmpty() == false) {
|
||||
|
@ -486,7 +487,6 @@ public class WellKnownText {
|
|||
return new Rectangle(minLon, maxLon, maxLat, minLat);
|
||||
}
|
||||
|
||||
|
||||
private Circle parseCircle(StreamTokenizer stream) throws IOException, ParseException {
|
||||
if (nextEmptyOrOpen(stream).equals(EMPTY)) {
|
||||
return Circle.EMPTY;
|
||||
|
@ -561,8 +561,7 @@ public class WellKnownText {
|
|||
if (next.equals(EMPTY) || next.equals(LPAREN)) {
|
||||
return next;
|
||||
}
|
||||
throw new ParseException("expected " + EMPTY + " or " + LPAREN
|
||||
+ " but found: " + tokenString(stream), stream.lineno());
|
||||
throw new ParseException("expected " + EMPTY + " or " + LPAREN + " but found: " + tokenString(stream), stream.lineno());
|
||||
}
|
||||
|
||||
private String nextCloser(StreamTokenizer stream) throws IOException, ParseException {
|
||||
|
@ -591,8 +590,7 @@ public class WellKnownText {
|
|||
if (token.equals(COMMA) || token.equals(RPAREN)) {
|
||||
return token;
|
||||
}
|
||||
throw new ParseException("expected " + COMMA + " or " + RPAREN
|
||||
+ " but found: " + tokenString(stream), stream.lineno());
|
||||
throw new ParseException("expected " + COMMA + " or " + RPAREN + " but found: " + tokenString(stream), stream.lineno());
|
||||
}
|
||||
|
||||
private static String getWKTName(Geometry geometry) {
|
||||
|
|
|
@ -87,7 +87,8 @@ abstract class BaseGeometryTestCase<T extends Geometry> extends AbstractWireTest
|
|||
|
||||
@Override
|
||||
public Object visit(GeometryCollection<?> collection) {
|
||||
return verify(collection, "GeometryCollection"); }
|
||||
return verify(collection, "GeometryCollection");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(Line line) {
|
||||
|
|
|
@ -44,9 +44,13 @@ public class CircleTests extends BaseGeometryTestCase<Circle> {
|
|||
@Override
|
||||
protected Circle createTestInstance(boolean hasAlt) {
|
||||
if (hasAlt) {
|
||||
return new Circle(randomDoubleBetween(-180, 180, true), randomDoubleBetween(-90, 90, true), randomDouble(),
|
||||
randomDoubleBetween(0, 100, false));
|
||||
} else {
|
||||
return new Circle(
|
||||
randomDoubleBetween(-180, 180, true),
|
||||
randomDoubleBetween(-90, 90, true),
|
||||
randomDouble(),
|
||||
randomDoubleBetween(0, 100, false)
|
||||
);
|
||||
} else {
|
||||
return new Circle(randomDoubleBetween(-180, 180, true), randomDoubleBetween(-90, 90, true), randomDoubleBetween(0, 100, false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,15 @@ public class GeometryCollectionTests extends BaseGeometryTestCase<GeometryCollec
|
|||
|
||||
public void testBasicSerialization() throws IOException, ParseException {
|
||||
WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
|
||||
assertEquals("GEOMETRYCOLLECTION (POINT (20.0 10.0),POINT EMPTY)",
|
||||
wkt.toWKT(new GeometryCollection<Geometry>(Arrays.asList(new Point(20, 10), Point.EMPTY))));
|
||||
assertEquals(
|
||||
"GEOMETRYCOLLECTION (POINT (20.0 10.0),POINT EMPTY)",
|
||||
wkt.toWKT(new GeometryCollection<Geometry>(Arrays.asList(new Point(20, 10), Point.EMPTY)))
|
||||
);
|
||||
|
||||
assertEquals(new GeometryCollection<Geometry>(Arrays.asList(new Point(20, 10), Point.EMPTY)),
|
||||
wkt.fromWKT("GEOMETRYCOLLECTION (POINT (20.0 10.0),POINT EMPTY)"));
|
||||
assertEquals(
|
||||
new GeometryCollection<Geometry>(Arrays.asList(new Point(20, 10), Point.EMPTY)),
|
||||
wkt.fromWKT("GEOMETRYCOLLECTION (POINT (20.0 10.0),POINT EMPTY)")
|
||||
);
|
||||
|
||||
assertEquals("GEOMETRYCOLLECTION EMPTY", wkt.toWKT(GeometryCollection.EMPTY));
|
||||
assertEquals(GeometryCollection.EMPTY, wkt.fromWKT("GEOMETRYCOLLECTION EMPTY)"));
|
||||
|
@ -68,12 +72,16 @@ public class GeometryCollectionTests extends BaseGeometryTestCase<GeometryCollec
|
|||
ex = expectThrows(IllegalArgumentException.class, () -> new GeometryCollection<>(null));
|
||||
assertEquals("the list of shapes cannot be null or empty", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> new GeometryCollection<>(
|
||||
Arrays.asList(new Point(20, 10), new Point(20, 10, 30))));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new GeometryCollection<>(Arrays.asList(new Point(20, 10), new Point(20, 10, 30)))
|
||||
);
|
||||
assertEquals("all elements of the collection should have the same number of dimension", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new GeometryCollection<Geometry>(Collections.singletonList(new Point(20, 10, 30)))));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(new GeometryCollection<Geometry>(Collections.singletonList(new Point(20, 10, 30))))
|
||||
);
|
||||
assertEquals("found Z value [30.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(new GeometryCollection<Geometry>(Collections.singletonList(new Point(20, 10, 30))));
|
||||
|
|
|
@ -86,7 +86,8 @@ public class GeometryValidatorTests extends OpenSearchTestCase {
|
|||
protected void checkLatitude(double latitude) {
|
||||
if (Double.isNaN(latitude) || latitude < MIN_LAT_INCL || latitude > MAX_LAT_INCL) {
|
||||
throw new IllegalArgumentException(
|
||||
"invalid latitude " + latitude + "; must be between " + MIN_LAT_INCL + " and " + MAX_LAT_INCL);
|
||||
"invalid latitude " + latitude + "; must be between " + MIN_LAT_INCL + " and " + MAX_LAT_INCL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +95,8 @@ public class GeometryValidatorTests extends OpenSearchTestCase {
|
|||
protected void checkLongitude(double longitude) {
|
||||
if (Double.isNaN(longitude) || longitude < MIN_LON_INCL || longitude > MAX_LON_INCL) {
|
||||
throw new IllegalArgumentException(
|
||||
"invalid longitude " + longitude + "; must be between " + MIN_LON_INCL + " and " + MAX_LON_INCL);
|
||||
"invalid longitude " + longitude + "; must be between " + MIN_LON_INCL + " and " + MAX_LON_INCL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +104,8 @@ public class GeometryValidatorTests extends OpenSearchTestCase {
|
|||
protected void checkAltitude(double zValue) {
|
||||
if (Double.isNaN(zValue) == false && (zValue < MIN_ALT_INCL || zValue > MAX_ALT_INCL)) {
|
||||
throw new IllegalArgumentException(
|
||||
"invalid altitude " + zValue + "; must be between " + MIN_ALT_INCL + " and " + MAX_ALT_INCL);
|
||||
"invalid altitude " + zValue + "; must be between " + MIN_ALT_INCL + " and " + MAX_ALT_INCL
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,12 +132,13 @@ public class GeometryValidatorTests extends OpenSearchTestCase {
|
|||
assertEquals("invalid altitude 2.0; must be between -1.0 and 1.0", ex.getMessage());
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT("POLYGON ((0.3 0.1, 0.4 0.2, 5 0.3, 0.3 0.1))"));
|
||||
assertEquals("invalid longitude 5.0; must be between -1.0 and 1.0", ex.getMessage());
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT(
|
||||
"POLYGON ((0.3 0.1, 0.4 0.2, 0.5 0.3, 0.3 0.1), (0.5 1.5, 2.5 1.5, 2.0 1.0))"));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> parser.fromWKT("POLYGON ((0.3 0.1, 0.4 0.2, 0.5 0.3, 0.3 0.1), (0.5 1.5, 2.5 1.5, 2.0 1.0))")
|
||||
);
|
||||
assertEquals("invalid latitude 1.5; must be between -1.0 and 1.0", ex.getMessage());
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> parser.fromWKT("MULTIPOINT (0 1, -2 1)"));
|
||||
assertEquals("invalid longitude -2.0; must be between -1.0 and 1.0", ex.getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -49,13 +49,17 @@ public class LineTests extends BaseGeometryTestCase<Line> {
|
|||
|
||||
public void testBasicSerialization() throws IOException, ParseException {
|
||||
WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
|
||||
assertEquals("LINESTRING (3.0 1.0, 4.0 2.0)", wkt.toWKT(new Line(new double[]{3, 4}, new double[]{1, 2})));
|
||||
assertEquals(new Line(new double[]{3, 4}, new double[]{1, 2}), wkt.fromWKT("LINESTRING (3 1, 4 2)"));
|
||||
assertEquals("LINESTRING (3.0 1.0, 4.0 2.0)", wkt.toWKT(new Line(new double[] { 3, 4 }, new double[] { 1, 2 })));
|
||||
assertEquals(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }), wkt.fromWKT("LINESTRING (3 1, 4 2)"));
|
||||
|
||||
assertEquals("LINESTRING (3.0 1.0 5.0, 4.0 2.0 6.0)", wkt.toWKT(new Line(new double[]{3, 4}, new double[]{1, 2},
|
||||
new double[]{5, 6})));
|
||||
assertEquals(new Line(new double[]{3, 4}, new double[]{1, 2}, new double[]{6, 5}),
|
||||
wkt.fromWKT("LINESTRING (3 1 6, 4 2 5)"));
|
||||
assertEquals(
|
||||
"LINESTRING (3.0 1.0 5.0, 4.0 2.0 6.0)",
|
||||
wkt.toWKT(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }, new double[] { 5, 6 }))
|
||||
);
|
||||
assertEquals(
|
||||
new Line(new double[] { 3, 4 }, new double[] { 1, 2 }, new double[] { 6, 5 }),
|
||||
wkt.fromWKT("LINESTRING (3 1 6, 4 2 5)")
|
||||
);
|
||||
|
||||
assertEquals("LINESTRING EMPTY", wkt.toWKT(Line.EMPTY));
|
||||
assertEquals(Line.EMPTY, wkt.fromWKT("LINESTRING EMPTY)"));
|
||||
|
@ -63,28 +67,38 @@ public class LineTests extends BaseGeometryTestCase<Line> {
|
|||
|
||||
public void testInitValidation() {
|
||||
GeometryValidator validator = new GeographyValidator(true);
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new Line(new double[]{3}, new double[]{1})));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> validator.validate(new Line(new double[] { 3 }, new double[] { 1 }))
|
||||
);
|
||||
assertEquals("at least two points in the line is required", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new Line(new double[]{3, 4, 500, 3}, new double[]{1, 2, 3, 1})));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> validator.validate(new Line(new double[] { 3, 4, 500, 3 }, new double[] { 1, 2, 3, 1 }))
|
||||
);
|
||||
assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new Line(new double[]{3, 4, 5, 3}, new double[]{1, 100, 3, 1})));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> validator.validate(new Line(new double[] { 3, 4, 5, 3 }, new double[] { 1, 100, 3, 1 }))
|
||||
);
|
||||
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new Line(new double[]{3, 4}, new double[]{1, 2}, new double[]{6, 5})));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }, new double[] { 6, 5 }))
|
||||
);
|
||||
assertEquals("found Z value [6.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(new Line(new double[]{3, 4}, new double[]{1, 2}, new double[]{6, 5}));
|
||||
new StandardValidator(true).validate(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }, new double[] { 6, 5 }));
|
||||
}
|
||||
|
||||
public void testWKTValidation() {
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("linestring (3 1 6, 4 2 5)"));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("linestring (3 1 6, 4 2 5)")
|
||||
);
|
||||
assertEquals("found Z value [6.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,46 +41,65 @@ import org.opensearch.test.OpenSearchTestCase;
|
|||
public class LinearRingTests extends OpenSearchTestCase {
|
||||
|
||||
public void testBasicSerialization() {
|
||||
UnsupportedOperationException ex = expectThrows(UnsupportedOperationException.class,
|
||||
() -> new WellKnownText(true, new GeographyValidator(true))
|
||||
.toWKT(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1})));
|
||||
UnsupportedOperationException ex = expectThrows(
|
||||
UnsupportedOperationException.class,
|
||||
() -> new WellKnownText(true, new GeographyValidator(true)).toWKT(
|
||||
new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 })
|
||||
)
|
||||
);
|
||||
assertEquals("line ring cannot be serialized using WKT", ex.getMessage());
|
||||
}
|
||||
|
||||
public void testInitValidation() {
|
||||
GeometryValidator validator = new GeographyValidator(true);
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[]{3, 4, 5}, new double[]{1, 2, 3})));
|
||||
assertEquals("first and last points of the linear ring must be the same (it must close itself): x[0]=3.0 x[2]=5.0 y[0]=1.0 " +
|
||||
"y[2]=3.0",
|
||||
ex.getMessage());
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[] { 3, 4, 5 }, new double[] { 1, 2, 3 }))
|
||||
);
|
||||
assertEquals(
|
||||
"first and last points of the linear ring must be the same (it must close itself): x[0]=3.0 x[2]=5.0 y[0]=1.0 " + "y[2]=3.0",
|
||||
ex.getMessage()
|
||||
);
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[]{3, 4, 3}, new double[]{1, 2, 1}, new double[]{1, 2, 3})));
|
||||
assertEquals("first and last points of the linear ring must be the same (it must close itself): x[0]=3.0 x[2]=3.0 y[0]=1.0 " +
|
||||
"y[2]=1.0 z[0]=1.0 z[2]=3.0",
|
||||
ex.getMessage());
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[] { 3, 4, 3 }, new double[] { 1, 2, 1 }, new double[] { 1, 2, 3 }))
|
||||
);
|
||||
assertEquals(
|
||||
"first and last points of the linear ring must be the same (it must close itself): x[0]=3.0 x[2]=3.0 y[0]=1.0 "
|
||||
+ "y[2]=1.0 z[0]=1.0 z[2]=3.0",
|
||||
ex.getMessage()
|
||||
);
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[]{3}, new double[]{1})));
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new LinearRing(new double[] { 3 }, new double[] { 1 })));
|
||||
assertEquals("at least two points in the line is required", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[]{3, 4, 500, 3}, new double[]{1, 2, 3, 1})));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[] { 3, 4, 500, 3 }, new double[] { 1, 2, 3, 1 }))
|
||||
);
|
||||
assertEquals("invalid longitude 500.0; must be between -180.0 and 180.0", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 100, 3, 1})));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> validator.validate(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 100, 3, 1 }))
|
||||
);
|
||||
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{1, 1, 1, 1})));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(
|
||||
new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 1, 1, 1, 1 })
|
||||
)
|
||||
);
|
||||
assertEquals("found Z value [1.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{1, 1, 1, 1}));
|
||||
new StandardValidator(true).validate(
|
||||
new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 1, 1, 1, 1 })
|
||||
);
|
||||
}
|
||||
|
||||
public void testVisitor() {
|
||||
BaseGeometryTestCase.testVisitor(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}));
|
||||
BaseGeometryTestCase.testVisitor(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,21 +57,30 @@ public class MultiLineTests extends BaseGeometryTestCase<MultiLine> {
|
|||
|
||||
public void testBasicSerialization() throws IOException, ParseException {
|
||||
WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
|
||||
assertEquals("MULTILINESTRING ((3.0 1.0, 4.0 2.0))", wkt.toWKT(
|
||||
new MultiLine(Collections.singletonList(new Line(new double[]{3, 4}, new double[]{1, 2})))));
|
||||
assertEquals(new MultiLine(Collections.singletonList(new Line(new double[]{3, 4}, new double[]{1, 2}))),
|
||||
wkt.fromWKT("MULTILINESTRING ((3 1, 4 2))"));
|
||||
assertEquals(
|
||||
"MULTILINESTRING ((3.0 1.0, 4.0 2.0))",
|
||||
wkt.toWKT(new MultiLine(Collections.singletonList(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }))))
|
||||
);
|
||||
assertEquals(
|
||||
new MultiLine(Collections.singletonList(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }))),
|
||||
wkt.fromWKT("MULTILINESTRING ((3 1, 4 2))")
|
||||
);
|
||||
|
||||
assertEquals("MULTILINESTRING EMPTY", wkt.toWKT(MultiLine.EMPTY));
|
||||
assertEquals(MultiLine.EMPTY, wkt.fromWKT("MULTILINESTRING EMPTY)"));
|
||||
}
|
||||
|
||||
public void testValidation() {
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new MultiLine(Collections.singletonList(new Line(new double[]{3, 4}, new double[]{1, 2}, new double[]{6, 5})))));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(
|
||||
new MultiLine(Collections.singletonList(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }, new double[] { 6, 5 })))
|
||||
)
|
||||
);
|
||||
assertEquals("found Z value [6.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(
|
||||
new MultiLine(Collections.singletonList(new Line(new double[]{3, 4}, new double[]{1, 2}, new double[]{6, 5}))));
|
||||
new MultiLine(Collections.singletonList(new Line(new double[] { 3, 4 }, new double[] { 1, 2 }, new double[] { 6, 5 })))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,28 +58,27 @@ public class MultiPointTests extends BaseGeometryTestCase<MultiPoint> {
|
|||
|
||||
public void testBasicSerialization() throws IOException, ParseException {
|
||||
WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
|
||||
assertEquals("MULTIPOINT (2.0 1.0)", wkt.toWKT(
|
||||
new MultiPoint(Collections.singletonList(new Point(2, 1)))));
|
||||
assertEquals(new MultiPoint(Collections.singletonList(new Point(2, 1))),
|
||||
wkt.fromWKT("MULTIPOINT (2 1)"));
|
||||
assertEquals("MULTIPOINT (2.0 1.0)", wkt.toWKT(new MultiPoint(Collections.singletonList(new Point(2, 1)))));
|
||||
assertEquals(new MultiPoint(Collections.singletonList(new Point(2, 1))), wkt.fromWKT("MULTIPOINT (2 1)"));
|
||||
|
||||
assertEquals("MULTIPOINT (2.0 1.0, 3.0 4.0)",
|
||||
wkt.toWKT(new MultiPoint(Arrays.asList(new Point(2, 1), new Point(3, 4)))));
|
||||
assertEquals(new MultiPoint(Arrays.asList(new Point(2, 1), new Point(3, 4))),
|
||||
wkt.fromWKT("MULTIPOINT (2 1, 3 4)"));
|
||||
assertEquals("MULTIPOINT (2.0 1.0, 3.0 4.0)", wkt.toWKT(new MultiPoint(Arrays.asList(new Point(2, 1), new Point(3, 4)))));
|
||||
assertEquals(new MultiPoint(Arrays.asList(new Point(2, 1), new Point(3, 4))), wkt.fromWKT("MULTIPOINT (2 1, 3 4)"));
|
||||
|
||||
assertEquals("MULTIPOINT (2.0 1.0 10.0, 3.0 4.0 20.0)",
|
||||
wkt.toWKT(new MultiPoint(Arrays.asList(new Point(2, 1, 10), new Point(3, 4, 20)))));
|
||||
assertEquals(new MultiPoint(Arrays.asList(new Point(2, 1, 10), new Point(3, 4, 20))),
|
||||
wkt.fromWKT("MULTIPOINT (2 1 10, 3 4 20)"));
|
||||
assertEquals(
|
||||
"MULTIPOINT (2.0 1.0 10.0, 3.0 4.0 20.0)",
|
||||
wkt.toWKT(new MultiPoint(Arrays.asList(new Point(2, 1, 10), new Point(3, 4, 20))))
|
||||
);
|
||||
assertEquals(new MultiPoint(Arrays.asList(new Point(2, 1, 10), new Point(3, 4, 20))), wkt.fromWKT("MULTIPOINT (2 1 10, 3 4 20)"));
|
||||
|
||||
assertEquals("MULTIPOINT EMPTY", wkt.toWKT(MultiPoint.EMPTY));
|
||||
assertEquals(MultiPoint.EMPTY, wkt.fromWKT("MULTIPOINT EMPTY)"));
|
||||
}
|
||||
|
||||
public void testValidation() {
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new MultiPoint(Collections.singletonList(new Point(2, 1, 3)))));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(new MultiPoint(Collections.singletonList(new Point(2, 1, 3))))
|
||||
);
|
||||
assertEquals("found Z value [3.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(new MultiPoint(Collections.singletonList(new Point(2, 1, 3))));
|
||||
|
|
|
@ -57,26 +57,44 @@ public class MultiPolygonTests extends BaseGeometryTestCase<MultiPolygon> {
|
|||
|
||||
public void testBasicSerialization() throws IOException, ParseException {
|
||||
WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
|
||||
assertEquals("MULTIPOLYGON (((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0)))",
|
||||
wkt.toWKT(new MultiPolygon(Collections.singletonList(
|
||||
new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}))))));
|
||||
assertEquals(new MultiPolygon(Collections.singletonList(
|
||||
new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1})))),
|
||||
wkt.fromWKT("MULTIPOLYGON (((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0)))"));
|
||||
assertEquals(
|
||||
"MULTIPOLYGON (((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0)))",
|
||||
wkt.toWKT(
|
||||
new MultiPolygon(
|
||||
Collections.singletonList(new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 })))
|
||||
)
|
||||
)
|
||||
);
|
||||
assertEquals(
|
||||
new MultiPolygon(
|
||||
Collections.singletonList(new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 })))
|
||||
),
|
||||
wkt.fromWKT("MULTIPOLYGON (((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0)))")
|
||||
);
|
||||
|
||||
assertEquals("MULTIPOLYGON EMPTY", wkt.toWKT(MultiPolygon.EMPTY));
|
||||
assertEquals(MultiPolygon.EMPTY, wkt.fromWKT("MULTIPOLYGON EMPTY)"));
|
||||
}
|
||||
|
||||
public void testValidation() {
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new MultiPolygon(Collections.singletonList(
|
||||
new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{1, 2, 3, 1}))
|
||||
))));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(
|
||||
new MultiPolygon(
|
||||
Collections.singletonList(
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 1, 2, 3, 1 }))
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
assertEquals("found Z value [1.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(
|
||||
new MultiPolygon(Collections.singletonList(
|
||||
new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{1, 2, 3, 1})))));
|
||||
new MultiPolygon(
|
||||
Collections.singletonList(
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 1, 2, 3, 1 }))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,8 +74,10 @@ public class PointTests extends BaseGeometryTestCase<Point> {
|
|||
}
|
||||
|
||||
public void testWKTValidation() {
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("point (20.0 10.0 100.0)"));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("point (20.0 10.0 100.0)")
|
||||
);
|
||||
assertEquals("found Z value [100.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,65 +49,106 @@ public class PolygonTests extends BaseGeometryTestCase<Polygon> {
|
|||
|
||||
public void testBasicSerialization() throws IOException, ParseException {
|
||||
WellKnownText wkt = new WellKnownText(true, new GeographyValidator(true));
|
||||
assertEquals("POLYGON ((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0))",
|
||||
wkt.toWKT(new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}))));
|
||||
assertEquals(new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1})),
|
||||
wkt.fromWKT("POLYGON ((3 1, 4 2, 5 3, 3 1))"));
|
||||
assertEquals(
|
||||
"POLYGON ((3.0 1.0, 4.0 2.0, 5.0 3.0, 3.0 1.0))",
|
||||
wkt.toWKT(new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 })))
|
||||
);
|
||||
assertEquals(
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 })),
|
||||
wkt.fromWKT("POLYGON ((3 1, 4 2, 5 3, 3 1))")
|
||||
);
|
||||
|
||||
assertEquals("POLYGON ((3.0 1.0 5.0, 4.0 2.0 4.0, 5.0 3.0 3.0, 3.0 1.0 5.0))",
|
||||
wkt.toWKT(new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{5, 4, 3, 5}))));
|
||||
assertEquals(new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{5, 4, 3, 5})),
|
||||
wkt.fromWKT("POLYGON ((3 1 5, 4 2 4, 5 3 3, 3 1 5))"));
|
||||
assertEquals(
|
||||
"POLYGON ((3.0 1.0 5.0, 4.0 2.0 4.0, 5.0 3.0 3.0, 3.0 1.0 5.0))",
|
||||
wkt.toWKT(new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 5, 4, 3, 5 })))
|
||||
);
|
||||
assertEquals(
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 5, 4, 3, 5 })),
|
||||
wkt.fromWKT("POLYGON ((3 1 5, 4 2 4, 5 3 3, 3 1 5))")
|
||||
);
|
||||
|
||||
// Auto closing in coerce mode
|
||||
assertEquals(new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1})),
|
||||
wkt.fromWKT("POLYGON ((3 1, 4 2, 5 3))"));
|
||||
assertEquals(new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{5, 4, 3, 5})),
|
||||
wkt.fromWKT("POLYGON ((3 1 5, 4 2 4, 5 3 3))"));
|
||||
assertEquals(new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}),
|
||||
Collections.singletonList(new LinearRing(new double[]{0.5, 2.5, 2.0, 0.5}, new double[]{1.5, 1.5, 1.0, 1.5}))),
|
||||
wkt.fromWKT("POLYGON ((3 1, 4 2, 5 3, 3 1), (0.5 1.5, 2.5 1.5, 2.0 1.0))"));
|
||||
assertEquals(
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 })),
|
||||
wkt.fromWKT("POLYGON ((3 1, 4 2, 5 3))")
|
||||
);
|
||||
assertEquals(
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 5, 4, 3, 5 })),
|
||||
wkt.fromWKT("POLYGON ((3 1 5, 4 2 4, 5 3 3))")
|
||||
);
|
||||
assertEquals(
|
||||
new Polygon(
|
||||
new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }),
|
||||
Collections.singletonList(new LinearRing(new double[] { 0.5, 2.5, 2.0, 0.5 }, new double[] { 1.5, 1.5, 1.0, 1.5 }))
|
||||
),
|
||||
wkt.fromWKT("POLYGON ((3 1, 4 2, 5 3, 3 1), (0.5 1.5, 2.5 1.5, 2.0 1.0))")
|
||||
);
|
||||
|
||||
assertEquals("POLYGON EMPTY", wkt.toWKT(Polygon.EMPTY));
|
||||
assertEquals(Polygon.EMPTY, wkt.fromWKT("POLYGON EMPTY)"));
|
||||
}
|
||||
|
||||
public void testInitValidation() {
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> new Polygon(new LinearRing(new double[]{3, 4, 3}, new double[]{1, 2, 1})));
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new Polygon(new LinearRing(new double[] { 3, 4, 3 }, new double[] { 1, 2, 1 }))
|
||||
);
|
||||
assertEquals("at least 4 polygon points required", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}), null));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }), null)
|
||||
);
|
||||
assertEquals("holes must not be null", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{5, 4, 3, 5}),
|
||||
Collections.singletonList(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}))));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new Polygon(
|
||||
new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 5, 4, 3, 5 }),
|
||||
Collections.singletonList(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }))
|
||||
)
|
||||
);
|
||||
assertEquals("holes must have the same number of dimensions as the polygon", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{1, 2, 3, 1}))));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 1, 2, 3, 1 }))
|
||||
)
|
||||
);
|
||||
assertEquals("found Z value [1.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(
|
||||
new Polygon(new LinearRing(new double[]{3, 4, 5, 3}, new double[]{1, 2, 3, 1}, new double[]{1, 2, 3, 1})));
|
||||
new Polygon(new LinearRing(new double[] { 3, 4, 5, 3 }, new double[] { 1, 2, 3, 1 }, new double[] { 1, 2, 3, 1 }))
|
||||
);
|
||||
}
|
||||
|
||||
public void testWKTValidation() {
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> new WellKnownText(false, new GeographyValidator(true)).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3))"));
|
||||
assertEquals("first and last points of the linear ring must be the same (it must close itself): " +
|
||||
"x[0]=3.0 x[2]=5.0 y[0]=1.0 y[2]=3.0 z[0]=5.0 z[2]=3.0", ex.getMessage());
|
||||
IllegalArgumentException ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new WellKnownText(false, new GeographyValidator(true)).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3))")
|
||||
);
|
||||
assertEquals(
|
||||
"first and last points of the linear ring must be the same (it must close itself): "
|
||||
+ "x[0]=3.0 x[2]=5.0 y[0]=1.0 y[2]=3.0 z[0]=5.0 z[2]=3.0",
|
||||
ex.getMessage()
|
||||
);
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3, 3 1 5))"));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new WellKnownText(randomBoolean(), new GeographyValidator(false)).fromWKT("polygon ((3 1 5, 4 2 4, 5 3 3, 3 1 5))")
|
||||
);
|
||||
assertEquals("found Z value [5.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new WellKnownText(false, new GeographyValidator(randomBoolean())).fromWKT(
|
||||
"polygon ((3 1, 4 2, 5 3, 3 1), (0.5 1.5, 2.5 1.5, 2.0 1.0))"));
|
||||
assertEquals("first and last points of the linear ring must be the same (it must close itself): " +
|
||||
"x[0]=0.5 x[2]=2.0 y[0]=1.5 y[2]=1.0", ex.getMessage());
|
||||
"polygon ((3 1, 4 2, 5 3, 3 1), (0.5 1.5, 2.5 1.5, 2.0 1.0))"
|
||||
)
|
||||
);
|
||||
assertEquals(
|
||||
"first and last points of the linear ring must be the same (it must close itself): " + "x[0]=0.5 x[2]=2.0 y[0]=1.5 y[2]=1.0",
|
||||
ex.getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,24 +59,22 @@ public class RectangleTests extends BaseGeometryTestCase<Rectangle> {
|
|||
|
||||
public void testInitValidation() {
|
||||
GeometryValidator validator = new GeographyValidator(true);
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new Rectangle(2, 3, 100, 1)));
|
||||
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Rectangle(2, 3, 100, 1)));
|
||||
assertEquals("invalid latitude 100.0; must be between -90.0 and 90.0", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new Rectangle(200, 3, 2, 1)));
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Rectangle(200, 3, 2, 1)));
|
||||
assertEquals("invalid longitude 200.0; must be between -180.0 and 180.0", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new Rectangle(2, 3, 1, 2)));
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Rectangle(2, 3, 1, 2)));
|
||||
assertEquals("max y cannot be less than min x", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> validator.validate(new Rectangle(2, 3, 2, 1, 5, Double.NaN)));
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> validator.validate(new Rectangle(2, 3, 2, 1, 5, Double.NaN)));
|
||||
assertEquals("only one z value is specified", ex.getMessage());
|
||||
|
||||
ex = expectThrows(IllegalArgumentException.class, () -> new StandardValidator(false).validate(
|
||||
new Rectangle(50, 10, 40, 30, 20, 60)));
|
||||
ex = expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new StandardValidator(false).validate(new Rectangle(50, 10, 40, 30, 20, 60))
|
||||
);
|
||||
assertEquals("found Z value [20.0] but [ignore_z_value] parameter is [false]", ex.getMessage());
|
||||
|
||||
new StandardValidator(true).validate(new Rectangle(50, 10, 40, 30, 20, 60));
|
||||
|
|
|
@ -42,15 +42,12 @@ public class GeoHashTests extends OpenSearchTestCase {
|
|||
public void testGeohashAsLongRoutines() {
|
||||
final GeoPoint expected = new GeoPoint();
|
||||
final GeoPoint actual = new GeoPoint();
|
||||
//Ensure that for all points at all supported levels of precision
|
||||
// Ensure that for all points at all supported levels of precision
|
||||
// that the long encoding of a geohash is compatible with its
|
||||
// String based counterpart
|
||||
for (double lat=-90;lat<90;lat++)
|
||||
{
|
||||
for (double lng=-180;lng<180;lng++)
|
||||
{
|
||||
for(int p=1;p<=12;p++)
|
||||
{
|
||||
for (double lat = -90; lat < 90; lat++) {
|
||||
for (double lng = -180; lng < 180; lng++) {
|
||||
for (int p = 1; p <= 12; p++) {
|
||||
long geoAsLong = Geohash.longEncode(lng, lat, p);
|
||||
|
||||
// string encode from geohashlong encoded location
|
||||
|
@ -104,11 +101,11 @@ public class GeoHashTests extends OpenSearchTestCase {
|
|||
// Adding some random geohash characters at the end
|
||||
String extendedGeohash = geohash + randomGeohash(1, 10);
|
||||
GeoPoint actual = GeoPoint.fromGeohash(extendedGeohash);
|
||||
assertEquals("Additional data points above 12 should be ignored [" + extendedGeohash + "]" , expected, actual);
|
||||
assertEquals("Additional data points above 12 should be ignored [" + extendedGeohash + "]", expected, actual);
|
||||
|
||||
Rectangle expectedBbox = Geohash.toBoundingBox(geohash);
|
||||
Rectangle actualBbox = Geohash.toBoundingBox(extendedGeohash);
|
||||
assertEquals("Additional data points above 12 should be ignored [" + extendedGeohash + "]" , expectedBbox, actualBbox);
|
||||
assertEquals("Additional data points above 12 should be ignored [" + extendedGeohash + "]", expectedBbox, actualBbox);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,20 +68,26 @@ public final class Grok {
|
|||
private static final String SUBNAME_GROUP = "subname";
|
||||
private static final String PATTERN_GROUP = "pattern";
|
||||
private static final String DEFINITION_GROUP = "definition";
|
||||
private static final String GROK_PATTERN =
|
||||
"%\\{" +
|
||||
"(?<name>" +
|
||||
"(?<pattern>[A-z0-9]+)" +
|
||||
"(?::(?<subname>[[:alnum:]@\\[\\]_:.-]+))?" +
|
||||
")" +
|
||||
"(?:=(?<definition>" +
|
||||
"(?:[^{}]+|\\.+)+" +
|
||||
")" +
|
||||
")?" + "\\}";
|
||||
private static final Regex GROK_PATTERN_REGEX = new Regex(GROK_PATTERN.getBytes(StandardCharsets.UTF_8), 0,
|
||||
GROK_PATTERN.getBytes(StandardCharsets.UTF_8).length, Option.NONE, UTF8Encoding.INSTANCE, Syntax.DEFAULT);
|
||||
private static final String GROK_PATTERN = "%\\{"
|
||||
+ "(?<name>"
|
||||
+ "(?<pattern>[A-z0-9]+)"
|
||||
+ "(?::(?<subname>[[:alnum:]@\\[\\]_:.-]+))?"
|
||||
+ ")"
|
||||
+ "(?:=(?<definition>"
|
||||
+ "(?:[^{}]+|\\.+)+"
|
||||
+ ")"
|
||||
+ ")?"
|
||||
+ "\\}";
|
||||
private static final Regex GROK_PATTERN_REGEX = new Regex(
|
||||
GROK_PATTERN.getBytes(StandardCharsets.UTF_8),
|
||||
0,
|
||||
GROK_PATTERN.getBytes(StandardCharsets.UTF_8).length,
|
||||
Option.NONE,
|
||||
UTF8Encoding.INSTANCE,
|
||||
Syntax.DEFAULT
|
||||
);
|
||||
|
||||
private static final int MAX_TO_REGEX_ITERATIONS = 100_000; //sanity limit
|
||||
private static final int MAX_TO_REGEX_ITERATIONS = 100_000; // sanity limit
|
||||
|
||||
private final Map<String, String> patternBank;
|
||||
private final boolean namedCaptures;
|
||||
|
@ -101,8 +107,13 @@ public final class Grok {
|
|||
this(patternBank, grokPattern, namedCaptures, MatcherWatchdog.noop(), logCallBack);
|
||||
}
|
||||
|
||||
private Grok(Map<String, String> patternBank, String grokPattern, boolean namedCaptures, MatcherWatchdog matcherWatchdog,
|
||||
Consumer<String> logCallBack) {
|
||||
private Grok(
|
||||
Map<String, String> patternBank,
|
||||
String grokPattern,
|
||||
boolean namedCaptures,
|
||||
MatcherWatchdog matcherWatchdog,
|
||||
Consumer<String> logCallBack
|
||||
) {
|
||||
this.patternBank = patternBank;
|
||||
this.namedCaptures = namedCaptures;
|
||||
this.matcherWatchdog = matcherWatchdog;
|
||||
|
@ -111,8 +122,14 @@ public final class Grok {
|
|||
|
||||
String expression = toRegex(grokPattern);
|
||||
byte[] expressionBytes = expression.getBytes(StandardCharsets.UTF_8);
|
||||
this.compiledExpression = new Regex(expressionBytes, 0, expressionBytes.length, Option.DEFAULT, UTF8Encoding.INSTANCE,
|
||||
message -> logCallBack.accept(message));
|
||||
this.compiledExpression = new Regex(
|
||||
expressionBytes,
|
||||
0,
|
||||
expressionBytes.length,
|
||||
Option.DEFAULT,
|
||||
UTF8Encoding.INSTANCE,
|
||||
message -> logCallBack.accept(message)
|
||||
);
|
||||
|
||||
List<GrokCaptureConfig> captureConfig = new ArrayList<>();
|
||||
for (Iterator<NameEntry> entry = compiledExpression.namedBackrefIterator(); entry.hasNext();) {
|
||||
|
@ -141,8 +158,7 @@ public final class Grok {
|
|||
*/
|
||||
private void validatePatternBank(String patternName, Stack<String> path) {
|
||||
String pattern = patternBank.get(patternName);
|
||||
boolean isSelfReference = pattern.contains("%{" + patternName + "}") ||
|
||||
pattern.contains("%{" + patternName + ":");
|
||||
boolean isSelfReference = pattern.contains("%{" + patternName + "}") || pattern.contains("%{" + patternName + ":");
|
||||
if (isSelfReference) {
|
||||
throwExceptionForCircularReference(patternName, pattern);
|
||||
} else if (path.contains(patternName)) {
|
||||
|
@ -156,7 +172,7 @@ public final class Grok {
|
|||
int begin = i + 2;
|
||||
int syntaxEndIndex = pattern.indexOf('}', begin);
|
||||
if (syntaxEndIndex == -1) {
|
||||
throw new IllegalArgumentException("Malformed pattern [" + patternName + "][" + pattern +"]");
|
||||
throw new IllegalArgumentException("Malformed pattern [" + patternName + "][" + pattern + "]");
|
||||
}
|
||||
int semanticNameIndex = pattern.indexOf(':', begin);
|
||||
int end = syntaxEndIndex;
|
||||
|
@ -173,8 +189,12 @@ public final class Grok {
|
|||
throwExceptionForCircularReference(patternName, pattern, null, null);
|
||||
}
|
||||
|
||||
private static void throwExceptionForCircularReference(String patternName, String pattern, String originPatterName,
|
||||
Stack<String> path) {
|
||||
private static void throwExceptionForCircularReference(
|
||||
String patternName,
|
||||
String pattern,
|
||||
String originPatterName,
|
||||
Stack<String> path
|
||||
) {
|
||||
StringBuilder message = new StringBuilder("circular reference in pattern [");
|
||||
message.append(patternName).append("][").append(pattern).append("]");
|
||||
if (originPatterName != null) {
|
||||
|
@ -188,8 +208,12 @@ public final class Grok {
|
|||
|
||||
private String groupMatch(String name, Region region, String pattern) {
|
||||
try {
|
||||
int number = GROK_PATTERN_REGEX.nameToBackrefNumber(name.getBytes(StandardCharsets.UTF_8), 0,
|
||||
name.getBytes(StandardCharsets.UTF_8).length, region);
|
||||
int number = GROK_PATTERN_REGEX.nameToBackrefNumber(
|
||||
name.getBytes(StandardCharsets.UTF_8),
|
||||
0,
|
||||
name.getBytes(StandardCharsets.UTF_8).length,
|
||||
region
|
||||
);
|
||||
int begin = region.beg[number];
|
||||
int end = region.end[number];
|
||||
return new String(pattern.getBytes(StandardCharsets.UTF_8), begin, end - begin, StandardCharsets.UTF_8);
|
||||
|
@ -305,8 +329,9 @@ public final class Grok {
|
|||
matcherWatchdog.unregister(matcher);
|
||||
}
|
||||
if (result == Matcher.INTERRUPTED) {
|
||||
throw new RuntimeException("grok pattern matching was interrupted after [" +
|
||||
matcherWatchdog.maxExecutionTimeInMillis() + "] ms");
|
||||
throw new RuntimeException(
|
||||
"grok pattern matching was interrupted after [" + matcherWatchdog.maxExecutionTimeInMillis() + "] ms"
|
||||
);
|
||||
}
|
||||
if (result == Matcher.FAILED) {
|
||||
return false;
|
||||
|
@ -327,14 +352,30 @@ public final class Grok {
|
|||
*/
|
||||
private static Map<String, String> loadBuiltinPatterns() {
|
||||
String[] patternNames = new String[] {
|
||||
"aws", "bacula", "bind", "bro", "exim", "firewalls", "grok-patterns", "haproxy",
|
||||
"java", "junos", "linux-syslog", "maven", "mcollective-patterns", "mongodb", "nagios",
|
||||
"postgresql", "rails", "redis", "ruby", "squid"
|
||||
};
|
||||
"aws",
|
||||
"bacula",
|
||||
"bind",
|
||||
"bro",
|
||||
"exim",
|
||||
"firewalls",
|
||||
"grok-patterns",
|
||||
"haproxy",
|
||||
"java",
|
||||
"junos",
|
||||
"linux-syslog",
|
||||
"maven",
|
||||
"mcollective-patterns",
|
||||
"mongodb",
|
||||
"nagios",
|
||||
"postgresql",
|
||||
"rails",
|
||||
"redis",
|
||||
"ruby",
|
||||
"squid" };
|
||||
Map<String, String> builtinPatterns = new LinkedHashMap<>();
|
||||
for (String pattern : patternNames) {
|
||||
try {
|
||||
try(InputStream is = Grok.class.getResourceAsStream("/patterns/" + pattern)) {
|
||||
try (InputStream is = Grok.class.getResourceAsStream("/patterns/" + pattern)) {
|
||||
loadPatterns(builtinPatterns, is);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@ -361,4 +402,3 @@ public final class Grok {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -83,10 +83,12 @@ public interface MatcherWatchdog {
|
|||
* @param relativeTimeSupplier A supplier that returns relative time
|
||||
* @param scheduler A scheduler that is able to execute a command for each fixed interval
|
||||
*/
|
||||
static MatcherWatchdog newInstance(long interval,
|
||||
long maxExecutionTime,
|
||||
LongSupplier relativeTimeSupplier,
|
||||
BiConsumer<Long, Runnable> scheduler) {
|
||||
static MatcherWatchdog newInstance(
|
||||
long interval,
|
||||
long maxExecutionTime,
|
||||
LongSupplier relativeTimeSupplier,
|
||||
BiConsumer<Long, Runnable> scheduler
|
||||
) {
|
||||
return new Default(interval, maxExecutionTime, relativeTimeSupplier, scheduler);
|
||||
}
|
||||
|
||||
|
@ -101,12 +103,10 @@ public interface MatcherWatchdog {
|
|||
|
||||
private static final Noop INSTANCE = new Noop();
|
||||
|
||||
private Noop() {
|
||||
}
|
||||
private Noop() {}
|
||||
|
||||
@Override
|
||||
public void register(Matcher matcher) {
|
||||
}
|
||||
public void register(Matcher matcher) {}
|
||||
|
||||
@Override
|
||||
public long maxExecutionTimeInMillis() {
|
||||
|
@ -114,8 +114,7 @@ public interface MatcherWatchdog {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void unregister(Matcher matcher) {
|
||||
}
|
||||
public void unregister(Matcher matcher) {}
|
||||
}
|
||||
|
||||
class Default implements MatcherWatchdog {
|
||||
|
@ -128,10 +127,7 @@ public interface MatcherWatchdog {
|
|||
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||
final ConcurrentHashMap<Matcher, Long> registry = new ConcurrentHashMap<>();
|
||||
|
||||
private Default(long interval,
|
||||
long maxExecutionTime,
|
||||
LongSupplier relativeTimeSupplier,
|
||||
BiConsumer<Long, Runnable> scheduler) {
|
||||
private Default(long interval, long maxExecutionTime, LongSupplier relativeTimeSupplier, BiConsumer<Long, Runnable> scheduler) {
|
||||
this.interval = interval;
|
||||
this.maxExecutionTime = maxExecutionTime;
|
||||
this.relativeTimeSupplier = relativeTimeSupplier;
|
||||
|
|
|
@ -62,7 +62,6 @@ import static org.opensearch.grok.GrokCaptureType.INTEGER;
|
|||
import static org.opensearch.grok.GrokCaptureType.LONG;
|
||||
import static org.opensearch.grok.GrokCaptureType.STRING;
|
||||
|
||||
|
||||
public class GrokTests extends OpenSearchTestCase {
|
||||
public void testMatchWithoutCaptures() {
|
||||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, "value", logger::warn);
|
||||
|
@ -130,8 +129,8 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testSyslog5424Line() {
|
||||
String line = "<191>1 2009-06-30T18:30:00+02:00 paxton.local grokdebug 4123 - [id1 foo=\\\"bar\\\"][id2 baz=\\\"something\\\"] " +
|
||||
"Hello, syslog.";
|
||||
String line = "<191>1 2009-06-30T18:30:00+02:00 paxton.local grokdebug 4123 - [id1 foo=\\\"bar\\\"][id2 baz=\\\"something\\\"] "
|
||||
+ "Hello, syslog.";
|
||||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, "%{SYSLOG5424LINE}", logger::warn);
|
||||
assertCaptureConfig(
|
||||
grok,
|
||||
|
@ -186,9 +185,13 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testUnicodeSyslog() {
|
||||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, "<%{POSINT:syslog_pri}>%{SPACE}%{SYSLOGTIMESTAMP:syslog_timestamp} " +
|
||||
"%{SYSLOGHOST:syslog_hostname} %{PROG:syslog_program}(:?)(?:\\[%{GREEDYDATA:syslog_pid}\\])?(:?) " +
|
||||
"%{GREEDYDATA:syslog_message}", logger::warn);
|
||||
Grok grok = new Grok(
|
||||
Grok.BUILTIN_PATTERNS,
|
||||
"<%{POSINT:syslog_pri}>%{SPACE}%{SYSLOGTIMESTAMP:syslog_timestamp} "
|
||||
+ "%{SYSLOGHOST:syslog_hostname} %{PROG:syslog_program}(:?)(?:\\[%{GREEDYDATA:syslog_pid}\\])?(:?) "
|
||||
+ "%{GREEDYDATA:syslog_message}",
|
||||
logger::warn
|
||||
);
|
||||
assertCaptureConfig(
|
||||
grok,
|
||||
org.opensearch.common.collect.Map.ofEntries(
|
||||
|
@ -200,9 +203,11 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
org.opensearch.common.collect.Map.entry("syslog_timestamp", STRING)
|
||||
)
|
||||
);
|
||||
Map<String, Object> matches = grok.captures("<22>Jan 4 07:50:46 mailmaster postfix/policy-spf[9454]: : " +
|
||||
"SPF permerror (Junk encountered in record 'v=spf1 mx a:mail.domain.no ip4:192.168.0.4 <20>all'): Envelope-from: " +
|
||||
"email@domain.no");
|
||||
Map<String, Object> matches = grok.captures(
|
||||
"<22>Jan 4 07:50:46 mailmaster postfix/policy-spf[9454]: : "
|
||||
+ "SPF permerror (Junk encountered in record 'v=spf1 mx a:mail.domain.no ip4:192.168.0.4 <20>all'): Envelope-from: "
|
||||
+ "email@domain.no"
|
||||
);
|
||||
assertThat(matches.get("syslog_pri"), equalTo("22"));
|
||||
assertThat(matches.get("syslog_program"), equalTo("postfix/policy-spf"));
|
||||
assertThat(matches.get("tags"), nullValue());
|
||||
|
@ -226,21 +231,21 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, "^%{TIMESTAMP_ISO8601}$", logger::warn);
|
||||
assertCaptureConfig(grok, org.opensearch.common.collect.Map.of());
|
||||
List<String> timeMessages = Arrays.asList(
|
||||
"2001-01-01T00:00:00",
|
||||
"1974-03-02T04:09:09",
|
||||
"2010-05-03T08:18:18+00:00",
|
||||
"2004-07-04T12:27:27-00:00",
|
||||
"2001-09-05T16:36:36+0000",
|
||||
"2001-11-06T20:45:45-0000",
|
||||
"2001-12-07T23:54:54Z",
|
||||
"2001-01-01T00:00:00.123456",
|
||||
"1974-03-02T04:09:09.123456",
|
||||
"2010-05-03T08:18:18.123456+00:00",
|
||||
"2004-07-04T12:27:27.123456-00:00",
|
||||
"2001-09-05T16:36:36.123456+0000",
|
||||
"2001-11-06T20:45:45.123456-0000",
|
||||
"2001-12-07T23:54:54.123456Z",
|
||||
"2001-12-07T23:54:60.123456Z" // '60' second is a leap second.
|
||||
"2001-01-01T00:00:00",
|
||||
"1974-03-02T04:09:09",
|
||||
"2010-05-03T08:18:18+00:00",
|
||||
"2004-07-04T12:27:27-00:00",
|
||||
"2001-09-05T16:36:36+0000",
|
||||
"2001-11-06T20:45:45-0000",
|
||||
"2001-12-07T23:54:54Z",
|
||||
"2001-01-01T00:00:00.123456",
|
||||
"1974-03-02T04:09:09.123456",
|
||||
"2010-05-03T08:18:18.123456+00:00",
|
||||
"2004-07-04T12:27:27.123456-00:00",
|
||||
"2001-09-05T16:36:36.123456+0000",
|
||||
"2001-11-06T20:45:45.123456-0000",
|
||||
"2001-12-07T23:54:54.123456Z",
|
||||
"2001-12-07T23:54:60.123456Z" // '60' second is a leap second.
|
||||
);
|
||||
for (String msg : timeMessages) {
|
||||
assertThat(grok.match(msg), is(true));
|
||||
|
@ -251,28 +256,28 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, "^%{TIMESTAMP_ISO8601}$", logger::warn);
|
||||
assertCaptureConfig(grok, org.opensearch.common.collect.Map.of());
|
||||
List<String> timeMessages = Arrays.asList(
|
||||
"2001-13-01T00:00:00", // invalid month
|
||||
"2001-00-01T00:00:00", // invalid month
|
||||
"2001-01-00T00:00:00", // invalid day
|
||||
"2001-01-32T00:00:00", // invalid day
|
||||
"2001-01-aT00:00:00", // invalid day
|
||||
"2001-01-1aT00:00:00", // invalid day
|
||||
"2001-01-01Ta0:00:00", // invalid hour
|
||||
"2001-01-01T0:00:00", // invalid hour
|
||||
"2001-01-01T25:00:00", // invalid hour
|
||||
"2001-01-01T01:60:00", // invalid minute
|
||||
"2001-01-01T00:aa:00", // invalid minute
|
||||
"2001-01-01T00:00:aa", // invalid second
|
||||
"2001-01-01T00:00:-1", // invalid second
|
||||
"2001-01-01T00:00:61", // invalid second
|
||||
"2001-01-01T00:00:00A", // invalid timezone
|
||||
"2001-01-01T00:00:00+", // invalid timezone
|
||||
"2001-01-01T00:00:00+25", // invalid timezone
|
||||
"2001-01-01T00:00:00+2500", // invalid timezone
|
||||
"2001-01-01T00:00:00+25:00", // invalid timezone
|
||||
"2001-01-01T00:00:00-25", // invalid timezone
|
||||
"2001-01-01T00:00:00-2500", // invalid timezone
|
||||
"2001-01-01T00:00:00-00:61" // invalid timezone
|
||||
"2001-13-01T00:00:00", // invalid month
|
||||
"2001-00-01T00:00:00", // invalid month
|
||||
"2001-01-00T00:00:00", // invalid day
|
||||
"2001-01-32T00:00:00", // invalid day
|
||||
"2001-01-aT00:00:00", // invalid day
|
||||
"2001-01-1aT00:00:00", // invalid day
|
||||
"2001-01-01Ta0:00:00", // invalid hour
|
||||
"2001-01-01T0:00:00", // invalid hour
|
||||
"2001-01-01T25:00:00", // invalid hour
|
||||
"2001-01-01T01:60:00", // invalid minute
|
||||
"2001-01-01T00:aa:00", // invalid minute
|
||||
"2001-01-01T00:00:aa", // invalid second
|
||||
"2001-01-01T00:00:-1", // invalid second
|
||||
"2001-01-01T00:00:61", // invalid second
|
||||
"2001-01-01T00:00:00A", // invalid timezone
|
||||
"2001-01-01T00:00:00+", // invalid timezone
|
||||
"2001-01-01T00:00:00+25", // invalid timezone
|
||||
"2001-01-01T00:00:00+2500", // invalid timezone
|
||||
"2001-01-01T00:00:00+25:00", // invalid timezone
|
||||
"2001-01-01T00:00:00-25", // invalid timezone
|
||||
"2001-01-01T00:00:00-2500", // invalid timezone
|
||||
"2001-01-01T00:00:00-00:61" // invalid timezone
|
||||
);
|
||||
for (String msg : timeMessages) {
|
||||
assertThat(grok.match(msg), is(false));
|
||||
|
@ -344,8 +349,10 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
String pattern = "%{NAME1}";
|
||||
new Grok(bank, pattern, false, logger::warn);
|
||||
});
|
||||
assertEquals("circular reference in pattern [NAME3][!!!%{NAME1}!!!] back to pattern [NAME1] via patterns [NAME1=>NAME2]",
|
||||
e.getMessage());
|
||||
assertEquals(
|
||||
"circular reference in pattern [NAME3][!!!%{NAME1}!!!] back to pattern [NAME1] via patterns [NAME1=>NAME2]",
|
||||
e.getMessage()
|
||||
);
|
||||
|
||||
e = expectThrows(IllegalArgumentException.class, () -> {
|
||||
Map<String, String> bank = new TreeMap<>();
|
||||
|
@ -354,8 +361,7 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
String pattern = "%{NAME1}";
|
||||
new Grok(bank, pattern, false, logger::warn);
|
||||
});
|
||||
assertEquals("circular reference in pattern [NAME2][!!!%{NAME2}!!!]",
|
||||
e.getMessage());
|
||||
assertEquals("circular reference in pattern [NAME2][!!!%{NAME2}!!!]", e.getMessage());
|
||||
|
||||
e = expectThrows(IllegalArgumentException.class, () -> {
|
||||
Map<String, String> bank = new TreeMap<>();
|
||||
|
@ -365,10 +371,12 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
bank.put("NAME4", "!!!%{NAME5}!!!");
|
||||
bank.put("NAME5", "!!!%{NAME1}!!!");
|
||||
String pattern = "%{NAME1}";
|
||||
new Grok(bank, pattern, false, logger::warn );
|
||||
new Grok(bank, pattern, false, logger::warn);
|
||||
});
|
||||
assertEquals("circular reference in pattern [NAME5][!!!%{NAME1}!!!] back to pattern [NAME1] " +
|
||||
"via patterns [NAME1=>NAME2=>NAME3=>NAME4]", e.getMessage());
|
||||
assertEquals(
|
||||
"circular reference in pattern [NAME5][!!!%{NAME1}!!!] back to pattern [NAME1] " + "via patterns [NAME1=>NAME2=>NAME3=>NAME4]",
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
public void testMalformedPattern() {
|
||||
|
@ -453,7 +461,7 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
|
||||
double[] rating = new double[1];
|
||||
GrokCaptureExtracter ratingExtracter = namedConfig(g, "rating").nativeExtracter(new ThrowingNativeExtracterMap() {
|
||||
public GrokCaptureExtracter forDouble(java.util.function.Function<DoubleConsumer,GrokCaptureExtracter> buildExtracter) {
|
||||
public GrokCaptureExtracter forDouble(java.util.function.Function<DoubleConsumer, GrokCaptureExtracter> buildExtracter) {
|
||||
return buildExtracter.apply(d -> rating[0] = d);
|
||||
}
|
||||
});
|
||||
|
@ -491,9 +499,9 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testApacheLog() {
|
||||
String logLine = "31.184.238.164 - - [24/Jul/2014:05:35:37 +0530] \"GET /logs/access.log HTTP/1.0\" 200 69849 " +
|
||||
"\"http://8rursodiol.enjin.com\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36\" \"www.dlwindianrailways.com\"";
|
||||
String logLine = "31.184.238.164 - - [24/Jul/2014:05:35:37 +0530] \"GET /logs/access.log HTTP/1.0\" 200 69849 "
|
||||
+ "\"http://8rursodiol.enjin.com\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
+ "Chrome/30.0.1599.12785 YaBrowser/13.12.1599.12785 Safari/537.36\" \"www.dlwindianrailways.com\"";
|
||||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, "%{COMBINEDAPACHELOG}", logger::warn);
|
||||
assertCaptureConfig(
|
||||
grok,
|
||||
|
@ -525,15 +533,21 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
assertEquals("69849", matches.get("bytes"));
|
||||
assertEquals("\"http://8rursodiol.enjin.com\"", matches.get("referrer"));
|
||||
assertEquals(null, matches.get("port"));
|
||||
assertEquals("\"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.12785 " +
|
||||
"YaBrowser/13.12.1599.12785 Safari/537.36\"", matches.get("agent"));
|
||||
assertEquals(
|
||||
"\"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.12785 "
|
||||
+ "YaBrowser/13.12.1599.12785 Safari/537.36\"",
|
||||
matches.get("agent")
|
||||
);
|
||||
}
|
||||
|
||||
public void testComplete() {
|
||||
Map<String, String> bank = new HashMap<>();
|
||||
bank.put("MONTHDAY", "(?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9])");
|
||||
bank.put("MONTH", "\\b(?:Jan(?:uary|uar)?|Feb(?:ruary|ruar)?|M(?:a|ä)?r(?:ch|z)?|Apr(?:il)?|Ma(?:y|i)?|Jun(?:e|i)" +
|
||||
"?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|O(?:c|k)?t(?:ober)?|Nov(?:ember)?|De(?:c|z)(?:ember)?)\\b");
|
||||
bank.put(
|
||||
"MONTH",
|
||||
"\\b(?:Jan(?:uary|uar)?|Feb(?:ruary|ruar)?|M(?:a|ä)?r(?:ch|z)?|Apr(?:il)?|Ma(?:y|i)?|Jun(?:e|i)"
|
||||
+ "?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|O(?:c|k)?t(?:ober)?|Nov(?:ember)?|De(?:c|z)(?:ember)?)\\b"
|
||||
);
|
||||
bank.put("MINUTE", "(?:[0-5][0-9])");
|
||||
bank.put("YEAR", "(?>\\d\\d){1,2}");
|
||||
bank.put("HOUR", "(?:2[0123]|[01]?[0-9])");
|
||||
|
@ -544,19 +558,25 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
bank.put("WORD", "\\b\\w+\\b");
|
||||
bank.put("BASE10NUM", "(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\\.[0-9]+)?)|(?:\\.[0-9]+)))");
|
||||
bank.put("NUMBER", "(?:%{BASE10NUM})");
|
||||
bank.put("IPV6", "((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]" +
|
||||
"\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4})" +
|
||||
"{1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:)" +
|
||||
"{4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\" +
|
||||
"d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]" +
|
||||
"\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4})" +
|
||||
"{1,5})" +
|
||||
"|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))" +
|
||||
"|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" +
|
||||
"(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}" +
|
||||
":((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?");
|
||||
bank.put("IPV4", "(?<![0-9])(?:(?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.]" +
|
||||
"(?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(?![0-9])");
|
||||
bank.put(
|
||||
"IPV6",
|
||||
"((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]"
|
||||
+ "\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4})"
|
||||
+ "{1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:)"
|
||||
+ "{4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\"
|
||||
+ "d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]"
|
||||
+ "\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4})"
|
||||
+ "{1,5})"
|
||||
+ "|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))"
|
||||
+ "|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)"
|
||||
+ "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}"
|
||||
+ ":((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?"
|
||||
);
|
||||
bank.put(
|
||||
"IPV4",
|
||||
"(?<![0-9])(?:(?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.]"
|
||||
+ "(?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(?![0-9])"
|
||||
);
|
||||
bank.put("IP", "(?:%{IPV6}|%{IPV4})");
|
||||
bank.put("HOSTNAME", "\\b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\\.?|\\b)");
|
||||
bank.put("IPORHOST", "(?:%{IP}|%{HOSTNAME})");
|
||||
|
@ -564,12 +584,12 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
bank.put("DATA", ".*?");
|
||||
bank.put("QS", "(?>(?<!\\\\)(?>\"(?>\\\\.|[^\\\\\"]+)+\"|\"\"|(?>'(?>\\\\.|[^\\\\']+)+')|''|(?>`(?>\\\\.|[^\\\\`]+)+`)|``))");
|
||||
|
||||
String text = "83.149.9.216 - - [19/Jul/2015:08:13:42 +0000] \"GET /presentations/logstash-monitorama-2013/images/" +
|
||||
"kibana-dashboard3.png HTTP/1.1\" 200 171717 \"http://semicomplete.com/presentations/logstash-monitorama-2013/\" " +
|
||||
"\"Mozilla" +
|
||||
"/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36\"";
|
||||
String pattern = "%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \\[%{HTTPDATE:timestamp}\\] \"%{WORD:verb} %{DATA:request} " +
|
||||
"HTTP/%{NUMBER:httpversion}\" %{NUMBER:response:int} (?:-|%{NUMBER:bytes:int}) %{QS:referrer} %{QS:agent}";
|
||||
String text = "83.149.9.216 - - [19/Jul/2015:08:13:42 +0000] \"GET /presentations/logstash-monitorama-2013/images/"
|
||||
+ "kibana-dashboard3.png HTTP/1.1\" 200 171717 \"http://semicomplete.com/presentations/logstash-monitorama-2013/\" "
|
||||
+ "\"Mozilla"
|
||||
+ "/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36\"";
|
||||
String pattern = "%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \\[%{HTTPDATE:timestamp}\\] \"%{WORD:verb} %{DATA:request} "
|
||||
+ "HTTP/%{NUMBER:httpversion}\" %{NUMBER:response:int} (?:-|%{NUMBER:bytes:int}) %{QS:referrer} %{QS:agent}";
|
||||
|
||||
Grok grok = new Grok(bank, pattern, logger::warn);
|
||||
assertCaptureConfig(
|
||||
|
@ -600,8 +620,11 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
expected.put("response", 200);
|
||||
expected.put("bytes", 171717);
|
||||
expected.put("referrer", "\"http://semicomplete.com/presentations/logstash-monitorama-2013/\"");
|
||||
expected.put("agent", "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/32.0.1700.77 Safari/537.36\"");
|
||||
expected.put(
|
||||
"agent",
|
||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
+ "Chrome/32.0.1700.77 Safari/537.36\""
|
||||
);
|
||||
|
||||
Map<String, Object> actual = grok.captures(text);
|
||||
|
||||
|
@ -629,10 +652,10 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
public void testExponentialExpressions() {
|
||||
AtomicBoolean run = new AtomicBoolean(true); // to avoid a lingering thread when test has completed
|
||||
|
||||
String grokPattern = "Bonsuche mit folgender Anfrage: Belegart->\\[%{WORD:param2},(?<param5>(\\s*%{NOTSPACE})*)\\] " +
|
||||
"Zustand->ABGESCHLOSSEN Kassennummer->%{WORD:param9} Bonnummer->%{WORD:param10} Datum->%{DATESTAMP_OTHER:param11}";
|
||||
String logLine = "Bonsuche mit folgender Anfrage: Belegart->[EINGESCHRAENKTER_VERKAUF, VERKAUF, NACHERFASSUNG] " +
|
||||
"Zustand->ABGESCHLOSSEN Kassennummer->2 Bonnummer->6362 Datum->Mon Jan 08 00:00:00 UTC 2018";
|
||||
String grokPattern = "Bonsuche mit folgender Anfrage: Belegart->\\[%{WORD:param2},(?<param5>(\\s*%{NOTSPACE})*)\\] "
|
||||
+ "Zustand->ABGESCHLOSSEN Kassennummer->%{WORD:param9} Bonnummer->%{WORD:param10} Datum->%{DATESTAMP_OTHER:param11}";
|
||||
String logLine = "Bonsuche mit folgender Anfrage: Belegart->[EINGESCHRAENKTER_VERKAUF, VERKAUF, NACHERFASSUNG] "
|
||||
+ "Zustand->ABGESCHLOSSEN Kassennummer->2 Bonnummer->6362 Datum->Mon Jan 08 00:00:00 UTC 2018";
|
||||
BiConsumer<Long, Runnable> scheduler = (delay, command) -> {
|
||||
try {
|
||||
Thread.sleep(delay);
|
||||
|
@ -646,8 +669,12 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
});
|
||||
t.start();
|
||||
};
|
||||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, grokPattern, MatcherWatchdog.newInstance(10, 200, System::currentTimeMillis, scheduler),
|
||||
logger::warn);
|
||||
Grok grok = new Grok(
|
||||
Grok.BUILTIN_PATTERNS,
|
||||
grokPattern,
|
||||
MatcherWatchdog.newInstance(10, 200, System::currentTimeMillis, scheduler),
|
||||
logger::warn
|
||||
);
|
||||
Exception e = expectThrows(RuntimeException.class, () -> grok.captures(logLine));
|
||||
run.set(false);
|
||||
assertThat(e.getMessage(), equalTo("grok pattern matching was interrupted after [200] ms"));
|
||||
|
@ -702,11 +729,11 @@ public class GrokTests extends OpenSearchTestCase {
|
|||
assertThat(grok.match("Test Class.java"), is(true));
|
||||
}
|
||||
|
||||
public void testLogCallBack(){
|
||||
public void testLogCallBack() {
|
||||
AtomicReference<String> message = new AtomicReference<>();
|
||||
Grok grok = new Grok(Grok.BUILTIN_PATTERNS, ".*\\[.*%{SPACE}*\\].*", message::set);
|
||||
grok.match("[foo]");
|
||||
//this message comes from Joni, so updates to Joni may change the expectation
|
||||
// this message comes from Joni, so updates to Joni may change the expectation
|
||||
assertThat(message.get(), containsString("regular expression has redundant nested repeat operator"));
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,8 @@ public class MatcherWatchdogTests extends OpenSearchTestCase {
|
|||
watchdog.register(matcher);
|
||||
verify(matcher, timeout(9999).atLeastOnce()).interrupt();
|
||||
interrupted.set(true);
|
||||
while (run.get()) {} // wait here so that the size of the registry can be asserted
|
||||
while (run.get()) {
|
||||
} // wait here so that the size of the registry can be asserted
|
||||
watchdog.unregister(matcher);
|
||||
});
|
||||
thread.start();
|
||||
|
@ -86,16 +87,18 @@ public class MatcherWatchdogTests extends OpenSearchTestCase {
|
|||
assertThat(registry.size(), is(1));
|
||||
});
|
||||
run.set(false);
|
||||
assertBusy(() -> {
|
||||
assertThat(registry.size(), is(0));
|
||||
});
|
||||
assertBusy(() -> { assertThat(registry.size(), is(0)); });
|
||||
}
|
||||
|
||||
public void testIdleIfNothingRegistered() throws Exception {
|
||||
long interval = 1L;
|
||||
ScheduledExecutorService threadPool = mock(ScheduledExecutorService.class);
|
||||
MatcherWatchdog watchdog = MatcherWatchdog.newInstance(interval, Long.MAX_VALUE, System::currentTimeMillis,
|
||||
(delay, command) -> threadPool.schedule(command, delay, TimeUnit.MILLISECONDS));
|
||||
MatcherWatchdog watchdog = MatcherWatchdog.newInstance(
|
||||
interval,
|
||||
Long.MAX_VALUE,
|
||||
System::currentTimeMillis,
|
||||
(delay, command) -> threadPool.schedule(command, delay, TimeUnit.MILLISECONDS)
|
||||
);
|
||||
// Periodic action is not scheduled because no thread is registered
|
||||
verifyZeroInteractions(threadPool);
|
||||
CompletableFuture<Runnable> commandFuture = new CompletableFuture<>();
|
||||
|
@ -103,9 +106,7 @@ public class MatcherWatchdogTests extends OpenSearchTestCase {
|
|||
doAnswer(invocationOnMock -> {
|
||||
commandFuture.complete((Runnable) invocationOnMock.getArguments()[0]);
|
||||
return null;
|
||||
}).when(threadPool).schedule(
|
||||
any(Runnable.class), eq(interval), eq(TimeUnit.MILLISECONDS)
|
||||
);
|
||||
}).when(threadPool).schedule(any(Runnable.class), eq(interval), eq(TimeUnit.MILLISECONDS));
|
||||
Matcher matcher = mock(Matcher.class);
|
||||
watchdog.register(matcher);
|
||||
// Registering the first thread should have caused the command to get scheduled again
|
||||
|
|
|
@ -37,8 +37,14 @@ import java.util.function.Consumer;
|
|||
|
||||
public class BytesChannelContext extends SocketChannelContext {
|
||||
|
||||
public BytesChannelContext(NioSocketChannel channel, NioSelector selector, Config.Socket socketConfig,
|
||||
Consumer<Exception> exceptionHandler, NioChannelHandler handler, InboundChannelBuffer channelBuffer) {
|
||||
public BytesChannelContext(
|
||||
NioSocketChannel channel,
|
||||
NioSelector selector,
|
||||
Config.Socket socketConfig,
|
||||
Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler handler,
|
||||
InboundChannelBuffer channelBuffer
|
||||
) {
|
||||
super(channel, selector, socketConfig, exceptionHandler, handler, channelBuffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,11 @@ public abstract class BytesWriteHandler implements NioChannelHandler {
|
|||
private static final List<FlushOperation> EMPTY_LIST = Collections.emptyList();
|
||||
|
||||
public WriteOperation createWriteOperation(SocketChannelContext context, Object message, BiConsumer<Void, Exception> listener) {
|
||||
assert message instanceof ByteBuffer[] : "This channel only supports messages that are of type: " + ByteBuffer[].class
|
||||
+ ". Found type: " + message.getClass() + ".";
|
||||
assert message instanceof ByteBuffer[] : "This channel only supports messages that are of type: "
|
||||
+ ByteBuffer[].class
|
||||
+ ". Found type: "
|
||||
+ message.getClass()
|
||||
+ ".";
|
||||
return new FlushReadyWrite(context, (ByteBuffer[]) message, listener);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,18 +56,43 @@ public abstract class ChannelFactory<ServerSocket extends NioServerSocketChannel
|
|||
/**
|
||||
* This will create a {@link ChannelFactory}.
|
||||
*/
|
||||
protected ChannelFactory(boolean tcpNoDelay, boolean tcpKeepAlive, int tcpKeepIdle, int tcpKeepInterval, int tcpKeepCount,
|
||||
boolean tcpReuseAddress, int tcpSendBufferSize, int tcpReceiveBufferSize) {
|
||||
this(tcpNoDelay, tcpKeepAlive, tcpKeepIdle, tcpKeepInterval, tcpKeepCount, tcpReuseAddress, tcpSendBufferSize, tcpReceiveBufferSize,
|
||||
new RawChannelFactory());
|
||||
protected ChannelFactory(
|
||||
boolean tcpNoDelay,
|
||||
boolean tcpKeepAlive,
|
||||
int tcpKeepIdle,
|
||||
int tcpKeepInterval,
|
||||
int tcpKeepCount,
|
||||
boolean tcpReuseAddress,
|
||||
int tcpSendBufferSize,
|
||||
int tcpReceiveBufferSize
|
||||
) {
|
||||
this(
|
||||
tcpNoDelay,
|
||||
tcpKeepAlive,
|
||||
tcpKeepIdle,
|
||||
tcpKeepInterval,
|
||||
tcpKeepCount,
|
||||
tcpReuseAddress,
|
||||
tcpSendBufferSize,
|
||||
tcpReceiveBufferSize,
|
||||
new RawChannelFactory()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will create a {@link ChannelFactory} using the raw channel factory passed to the constructor.
|
||||
*/
|
||||
protected ChannelFactory(boolean tcpNoDelay, boolean tcpKeepAlive, int tcpKeepIdle, int tcpKeepInterval, int tcpKeepCount,
|
||||
boolean tcpReuseAddress, int tcpSendBufferSize, int tcpReceiveBufferSize,
|
||||
RawChannelFactory rawChannelFactory) {
|
||||
protected ChannelFactory(
|
||||
boolean tcpNoDelay,
|
||||
boolean tcpKeepAlive,
|
||||
int tcpKeepIdle,
|
||||
int tcpKeepInterval,
|
||||
int tcpKeepCount,
|
||||
boolean tcpReuseAddress,
|
||||
int tcpSendBufferSize,
|
||||
int tcpReceiveBufferSize,
|
||||
RawChannelFactory rawChannelFactory
|
||||
) {
|
||||
this.tcpNoDelay = tcpNoDelay;
|
||||
this.tcpKeepAlive = tcpKeepAlive;
|
||||
this.tcpKeepIdle = tcpKeepIdle;
|
||||
|
@ -203,8 +228,18 @@ public abstract class ChannelFactory<ServerSocket extends NioServerSocketChannel
|
|||
}
|
||||
|
||||
private Config.Socket createSocketConfig(InetSocketAddress remoteAddress, boolean isAccepted) {
|
||||
return new Config.Socket(tcpNoDelay, tcpKeepAlive, tcpKeepIdle, tcpKeepInterval, tcpKeepCount, tcpReuseAddress, tcpSendBufferSize,
|
||||
tcpReceiveBufferSize, remoteAddress, isAccepted);
|
||||
return new Config.Socket(
|
||||
tcpNoDelay,
|
||||
tcpKeepAlive,
|
||||
tcpKeepIdle,
|
||||
tcpKeepInterval,
|
||||
tcpKeepCount,
|
||||
tcpReuseAddress,
|
||||
tcpSendBufferSize,
|
||||
tcpReceiveBufferSize,
|
||||
remoteAddress,
|
||||
isAccepted
|
||||
);
|
||||
}
|
||||
|
||||
public static class RawChannelFactory {
|
||||
|
|
|
@ -58,9 +58,18 @@ public abstract class Config {
|
|||
private final InetSocketAddress remoteAddress;
|
||||
private final boolean isAccepted;
|
||||
|
||||
public Socket(boolean tcpNoDelay, boolean tcpKeepAlive, int tcpKeepIdle, int tcpKeepInterval, int tcpKeepCount,
|
||||
boolean tcpReuseAddress, int tcpSendBufferSize, int tcpReceiveBufferSize,
|
||||
InetSocketAddress remoteAddress, boolean isAccepted) {
|
||||
public Socket(
|
||||
boolean tcpNoDelay,
|
||||
boolean tcpKeepAlive,
|
||||
int tcpKeepIdle,
|
||||
int tcpKeepInterval,
|
||||
int tcpKeepCount,
|
||||
boolean tcpReuseAddress,
|
||||
int tcpSendBufferSize,
|
||||
int tcpReceiveBufferSize,
|
||||
InetSocketAddress remoteAddress,
|
||||
boolean isAccepted
|
||||
) {
|
||||
super(tcpReuseAddress);
|
||||
this.tcpNoDelay = tcpNoDelay;
|
||||
this.tcpKeepAlive = tcpKeepAlive;
|
||||
|
|
|
@ -64,15 +64,23 @@ public class FlushOperation {
|
|||
}
|
||||
|
||||
public boolean isFullyFlushed() {
|
||||
assert length >= internalIndex : "Should never have an index that is greater than the length [length=" + length + ", index="
|
||||
+ internalIndex + "]";
|
||||
assert length >= internalIndex : "Should never have an index that is greater than the length [length="
|
||||
+ length
|
||||
+ ", index="
|
||||
+ internalIndex
|
||||
+ "]";
|
||||
return internalIndex == length;
|
||||
}
|
||||
|
||||
public void incrementIndex(int delta) {
|
||||
internalIndex += delta;
|
||||
assert length >= internalIndex : "Should never increment index past length [length=" + length + ", post-increment index="
|
||||
+ internalIndex + ", delta=" + delta + "]";
|
||||
assert length >= internalIndex : "Should never increment index past length [length="
|
||||
+ length
|
||||
+ ", post-increment index="
|
||||
+ internalIndex
|
||||
+ ", delta="
|
||||
+ delta
|
||||
+ "]";
|
||||
}
|
||||
|
||||
public ByteBuffer[] getBuffersToWrite() {
|
||||
|
|
|
@ -135,8 +135,9 @@ public final class InboundChannelBuffer implements AutoCloseable {
|
|||
*/
|
||||
public ByteBuffer[] sliceBuffersTo(long to) {
|
||||
if (to > capacity) {
|
||||
throw new IndexOutOfBoundsException("can't slice a channel buffer with capacity [" + capacity +
|
||||
"], with slice parameters to [" + to + "]");
|
||||
throw new IndexOutOfBoundsException(
|
||||
"can't slice a channel buffer with capacity [" + capacity + "], with slice parameters to [" + to + "]"
|
||||
);
|
||||
} else if (to == 0) {
|
||||
return EMPTY_BYTE_BUFFER_ARRAY;
|
||||
}
|
||||
|
@ -174,8 +175,9 @@ public final class InboundChannelBuffer implements AutoCloseable {
|
|||
*/
|
||||
public Page[] sliceAndRetainPagesTo(long to) {
|
||||
if (to > capacity) {
|
||||
throw new IndexOutOfBoundsException("can't slice a channel buffer with capacity [" + capacity +
|
||||
"], with slice parameters to [" + to + "]");
|
||||
throw new IndexOutOfBoundsException(
|
||||
"can't slice a channel buffer with capacity [" + capacity + "], with slice parameters to [" + to + "]"
|
||||
);
|
||||
} else if (to == 0) {
|
||||
return EMPTY_BYTE_PAGE_ARRAY;
|
||||
}
|
||||
|
@ -213,8 +215,9 @@ public final class InboundChannelBuffer implements AutoCloseable {
|
|||
*/
|
||||
public ByteBuffer[] sliceBuffersFrom(long from) {
|
||||
if (from > capacity) {
|
||||
throw new IndexOutOfBoundsException("can't slice a channel buffer with capacity [" + capacity +
|
||||
"], with slice parameters from [" + from + "]");
|
||||
throw new IndexOutOfBoundsException(
|
||||
"can't slice a channel buffer with capacity [" + capacity + "], with slice parameters from [" + from + "]"
|
||||
);
|
||||
} else if (from == capacity) {
|
||||
return EMPTY_BYTE_BUFFER_ARRAY;
|
||||
}
|
||||
|
@ -242,8 +245,17 @@ public final class InboundChannelBuffer implements AutoCloseable {
|
|||
|
||||
long newIndex = delta + internalIndex;
|
||||
if (newIndex > capacity) {
|
||||
throw new IllegalArgumentException("Cannot increment an index [" + internalIndex + "] with a delta [" + delta +
|
||||
"] that will result in a new index [" + newIndex + "] that is greater than the capacity [" + capacity + "].");
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot increment an index ["
|
||||
+ internalIndex
|
||||
+ "] with a delta ["
|
||||
+ delta
|
||||
+ "] that will result in a new index ["
|
||||
+ newIndex
|
||||
+ "] that is greater than the capacity ["
|
||||
+ capacity
|
||||
+ "]."
|
||||
);
|
||||
}
|
||||
internalIndex = newIndex;
|
||||
}
|
||||
|
|
|
@ -128,8 +128,12 @@ public class NioSelector implements Closeable {
|
|||
}
|
||||
|
||||
public void assertOnSelectorThread() {
|
||||
assert isOnCurrentThread() : "Must be on selector thread [" + thread.get().getName() + "} to perform this operation. " +
|
||||
"Currently on thread [" + Thread.currentThread().getName() + "].";
|
||||
assert isOnCurrentThread() : "Must be on selector thread ["
|
||||
+ thread.get().getName()
|
||||
+ "} to perform this operation. "
|
||||
+ "Currently on thread ["
|
||||
+ Thread.currentThread().getName()
|
||||
+ "].";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,10 +190,10 @@ public class NioSelector implements Closeable {
|
|||
try {
|
||||
processKey(sk);
|
||||
} catch (CancelledKeyException cke) {
|
||||
eventHandler.genericChannelException((ChannelContext<?>) sk.attachment(), cke);
|
||||
eventHandler.genericChannelException((ChannelContext<?>) sk.attachment(), cke);
|
||||
}
|
||||
} else {
|
||||
eventHandler.genericChannelException((ChannelContext<?>) sk.attachment(), new CancelledKeyException());
|
||||
eventHandler.genericChannelException((ChannelContext<?>) sk.attachment(), new CancelledKeyException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,8 +214,9 @@ public class NioSelector implements Closeable {
|
|||
cleanupPendingWrites();
|
||||
channelsToClose.addAll(channelsToRegister);
|
||||
channelsToRegister.clear();
|
||||
channelsToClose.addAll(selector.keys().stream()
|
||||
.map(sk -> (ChannelContext<?>) sk.attachment()).filter(Objects::nonNull).collect(Collectors.toList()));
|
||||
channelsToClose.addAll(
|
||||
selector.keys().stream().map(sk -> (ChannelContext<?>) sk.attachment()).filter(Objects::nonNull).collect(Collectors.toList())
|
||||
);
|
||||
closePendingChannels();
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ import java.util.stream.Stream;
|
|||
*/
|
||||
public class NioSelectorGroup implements NioGroup {
|
||||
|
||||
|
||||
private final List<NioSelector> dedicatedAcceptors;
|
||||
private final RoundRobinSupplier<NioSelector> acceptorSupplier;
|
||||
|
||||
|
@ -75,8 +74,11 @@ public class NioSelectorGroup implements NioGroup {
|
|||
* @param eventHandlerFunction function for creating event handlers
|
||||
* @throws IOException occurs if there is a problem while opening a java.nio.Selector
|
||||
*/
|
||||
public NioSelectorGroup(ThreadFactory threadFactory, int selectorCount,
|
||||
Function<Supplier<NioSelector>, EventHandler> eventHandlerFunction) throws IOException {
|
||||
public NioSelectorGroup(
|
||||
ThreadFactory threadFactory,
|
||||
int selectorCount,
|
||||
Function<Supplier<NioSelector>, EventHandler> eventHandlerFunction
|
||||
) throws IOException {
|
||||
this(null, 0, threadFactory, selectorCount, eventHandlerFunction);
|
||||
}
|
||||
|
||||
|
@ -92,8 +94,13 @@ public class NioSelectorGroup implements NioGroup {
|
|||
* @param eventHandlerFunction function for creating event handlers
|
||||
* @throws IOException occurs if there is a problem while opening a java.nio.Selector
|
||||
*/
|
||||
public NioSelectorGroup(ThreadFactory acceptorThreadFactory, int dedicatedAcceptorCount, ThreadFactory selectorThreadFactory,
|
||||
int selectorCount, Function<Supplier<NioSelector>, EventHandler> eventHandlerFunction) throws IOException {
|
||||
public NioSelectorGroup(
|
||||
ThreadFactory acceptorThreadFactory,
|
||||
int dedicatedAcceptorCount,
|
||||
ThreadFactory selectorThreadFactory,
|
||||
int selectorCount,
|
||||
Function<Supplier<NioSelector>, EventHandler> eventHandlerFunction
|
||||
) throws IOException {
|
||||
dedicatedAcceptors = new ArrayList<>(dedicatedAcceptorCount);
|
||||
selectors = new ArrayList<>(selectorCount);
|
||||
|
||||
|
|
|
@ -84,9 +84,7 @@ public class NioServerSocketChannel extends NioChannel {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NioServerSocketChannel{" +
|
||||
"localAddress=" + getLocalAddress() +
|
||||
'}';
|
||||
return "NioServerSocketChannel{" + "localAddress=" + getLocalAddress() + '}';
|
||||
}
|
||||
|
||||
private void attemptToSetLocalAddress() {
|
||||
|
|
|
@ -88,9 +88,6 @@ public class NioSocketChannel extends NioChannel {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NioSocketChannel{" +
|
||||
"localAddress=" + getLocalAddress() +
|
||||
", remoteAddress=" + getRemoteAddress() +
|
||||
'}';
|
||||
return "NioSocketChannel{" + "localAddress=" + getLocalAddress() + ", remoteAddress=" + getRemoteAddress() + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,6 @@ public final class SelectionKeyUtils {
|
|||
selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_ACCEPT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for an interest in writes for this selection key.
|
||||
*
|
||||
|
|
|
@ -58,9 +58,14 @@ public class ServerChannelContext extends ChannelContext<ServerSocketChannel> {
|
|||
private final ChannelFactory<?, ?> channelFactory;
|
||||
private final CompletableContext<Void> bindContext = new CompletableContext<>();
|
||||
|
||||
public ServerChannelContext(NioServerSocketChannel channel, ChannelFactory<?, ?> channelFactory, NioSelector selector,
|
||||
Config.ServerSocket config, Consumer<NioSocketChannel> acceptor,
|
||||
Consumer<Exception> exceptionHandler) {
|
||||
public ServerChannelContext(
|
||||
NioServerSocketChannel channel,
|
||||
ChannelFactory<?, ?> channelFactory,
|
||||
NioSelector selector,
|
||||
Config.ServerSocket config,
|
||||
Consumer<NioSocketChannel> acceptor,
|
||||
Consumer<Exception> exceptionHandler
|
||||
) {
|
||||
super(channel.getRawChannel(), exceptionHandler);
|
||||
this.channel = channel;
|
||||
this.channelFactory = channelFactory;
|
||||
|
@ -77,8 +82,7 @@ public class ServerChannelContext extends ChannelContext<ServerSocketChannel> {
|
|||
acceptor.accept(nioChannel);
|
||||
}
|
||||
} finally {
|
||||
if (acceptedChannel != null)
|
||||
acceptedChannel.close();
|
||||
if (acceptedChannel != null) acceptedChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,9 +77,14 @@ public abstract class SocketChannelContext extends ChannelContext<SocketChannel>
|
|||
private boolean socketOptionsSet;
|
||||
private Exception connectException;
|
||||
|
||||
protected SocketChannelContext(NioSocketChannel channel, NioSelector selector, Config.Socket socketConfig,
|
||||
Consumer<Exception> exceptionHandler, NioChannelHandler channelHandler,
|
||||
InboundChannelBuffer channelBuffer) {
|
||||
protected SocketChannelContext(
|
||||
NioSocketChannel channel,
|
||||
NioSelector selector,
|
||||
Config.Socket socketConfig,
|
||||
Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler channelHandler,
|
||||
InboundChannelBuffer channelBuffer
|
||||
) {
|
||||
super(channel.getRawChannel(), exceptionHandler);
|
||||
this.selector = selector;
|
||||
this.channel = channel;
|
||||
|
|
|
@ -130,7 +130,6 @@ public class BytesChannelContextTests extends OpenSearchTestCase {
|
|||
return bytes.length;
|
||||
});
|
||||
|
||||
|
||||
when(readConsumer.apply(channelBuffer)).thenReturn(0);
|
||||
|
||||
assertEquals(messageLength, context.read());
|
||||
|
@ -175,7 +174,7 @@ public class BytesChannelContextTests extends OpenSearchTestCase {
|
|||
public void testQueuedWriteIsFlushedInFlushCall() throws Exception {
|
||||
assertFalse(context.readyForFlush());
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(10) };
|
||||
|
||||
FlushReadyWrite flushOperation = mock(FlushReadyWrite.class);
|
||||
context.queueWriteOperation(flushOperation);
|
||||
|
@ -201,7 +200,7 @@ public class BytesChannelContextTests extends OpenSearchTestCase {
|
|||
assertTrue(context.readyForFlush());
|
||||
|
||||
when(flushOperation.isFullyFlushed()).thenReturn(false);
|
||||
when(flushOperation.getBuffersToWrite(anyInt())).thenReturn(new ByteBuffer[] {ByteBuffer.allocate(3)});
|
||||
when(flushOperation.getBuffersToWrite(anyInt())).thenReturn(new ByteBuffer[] { ByteBuffer.allocate(3) });
|
||||
context.flushChannel();
|
||||
|
||||
verify(listener, times(0)).accept(null, null);
|
||||
|
@ -215,8 +214,8 @@ public class BytesChannelContextTests extends OpenSearchTestCase {
|
|||
BiConsumer<Void, Exception> listener2 = mock(BiConsumer.class);
|
||||
FlushReadyWrite flushOperation1 = mock(FlushReadyWrite.class);
|
||||
FlushReadyWrite flushOperation2 = mock(FlushReadyWrite.class);
|
||||
when(flushOperation1.getBuffersToWrite(anyInt())).thenReturn(new ByteBuffer[] {ByteBuffer.allocate(3)});
|
||||
when(flushOperation2.getBuffersToWrite(anyInt())).thenReturn(new ByteBuffer[] {ByteBuffer.allocate(3)});
|
||||
when(flushOperation1.getBuffersToWrite(anyInt())).thenReturn(new ByteBuffer[] { ByteBuffer.allocate(3) });
|
||||
when(flushOperation2.getBuffersToWrite(anyInt())).thenReturn(new ByteBuffer[] { ByteBuffer.allocate(3) });
|
||||
when(flushOperation1.getListener()).thenReturn(listener);
|
||||
when(flushOperation2.getListener()).thenReturn(listener2);
|
||||
|
||||
|
@ -244,7 +243,7 @@ public class BytesChannelContextTests extends OpenSearchTestCase {
|
|||
public void testWhenIOExceptionThrownListenerIsCalled() throws IOException {
|
||||
assertFalse(context.readyForFlush());
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(10) };
|
||||
FlushReadyWrite flushOperation = mock(FlushReadyWrite.class);
|
||||
context.queueWriteOperation(flushOperation);
|
||||
|
||||
|
@ -261,7 +260,7 @@ public class BytesChannelContextTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testWriteIOExceptionMeansChannelReadyToClose() throws IOException {
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(10) };
|
||||
FlushReadyWrite flushOperation = mock(FlushReadyWrite.class);
|
||||
context.queueWriteOperation(flushOperation);
|
||||
|
||||
|
|
|
@ -152,8 +152,11 @@ public class ChannelFactoryTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public NioServerSocketChannel createServerChannel(NioSelector selector, ServerSocketChannel channel,
|
||||
Config.ServerSocket socketConfig) {
|
||||
public NioServerSocketChannel createServerChannel(
|
||||
NioSelector selector,
|
||||
ServerSocketChannel channel,
|
||||
Config.ServerSocket socketConfig
|
||||
) {
|
||||
return new NioServerSocketChannel(channel);
|
||||
}
|
||||
|
||||
|
|
|
@ -234,7 +234,6 @@ public class EventHandlerTests extends OpenSearchTestCase {
|
|||
NioSocketChannel channel = mock(NioSocketChannel.class);
|
||||
when(channel.getContext()).thenReturn(context);
|
||||
|
||||
|
||||
assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, key.interestOps());
|
||||
handler.postHandling(context);
|
||||
assertEquals(SelectionKey.OP_READ, key.interestOps());
|
||||
|
@ -254,9 +253,12 @@ public class EventHandlerTests extends OpenSearchTestCase {
|
|||
|
||||
private class DoNotRegisterSocketContext extends BytesChannelContext {
|
||||
|
||||
|
||||
DoNotRegisterSocketContext(NioSocketChannel channel, NioSelector selector, Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler handler) {
|
||||
DoNotRegisterSocketContext(
|
||||
NioSocketChannel channel,
|
||||
NioSelector selector,
|
||||
Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler handler
|
||||
) {
|
||||
super(channel, selector, getSocketConfig(), exceptionHandler, handler, InboundChannelBuffer.allocatingInstance());
|
||||
}
|
||||
|
||||
|
@ -270,7 +272,6 @@ public class EventHandlerTests extends OpenSearchTestCase {
|
|||
|
||||
private class DoNotRegisterServerContext extends ServerChannelContext {
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DoNotRegisterServerContext(NioServerSocketChannel channel, NioSelector selector, Consumer<NioSocketChannel> acceptor) {
|
||||
super(channel, channelFactory, selector, getServerSocketConfig(), acceptor, mock(Consumer.class));
|
||||
|
@ -289,7 +290,17 @@ public class EventHandlerTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
private static Config.Socket getSocketConfig() {
|
||||
return new Config.Socket(randomBoolean(), randomBoolean(), -1, -1, -1, randomBoolean(), -1, -1, mock(InetSocketAddress.class),
|
||||
randomBoolean());
|
||||
return new Config.Socket(
|
||||
randomBoolean(),
|
||||
randomBoolean(),
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
randomBoolean(),
|
||||
-1,
|
||||
-1,
|
||||
mock(InetSocketAddress.class),
|
||||
randomBoolean()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class FlushOperationTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testFullyFlushedMarker() {
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(10) };
|
||||
FlushOperation writeOp = new FlushOperation(buffers, listener);
|
||||
|
||||
writeOp.incrementIndex(10);
|
||||
|
@ -61,7 +61,7 @@ public class FlushOperationTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testPartiallyFlushedMarker() {
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(10) };
|
||||
FlushOperation writeOp = new FlushOperation(buffers, listener);
|
||||
|
||||
writeOp.incrementIndex(5);
|
||||
|
@ -70,7 +70,7 @@ public class FlushOperationTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
public void testMultipleFlushesWithCompositeBuffer() throws IOException {
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(10), ByteBuffer.allocate(15), ByteBuffer.allocate(3)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(10), ByteBuffer.allocate(15), ByteBuffer.allocate(3) };
|
||||
FlushOperation writeOp = new FlushOperation(buffers, listener);
|
||||
|
||||
writeOp.incrementIndex(5);
|
||||
|
|
|
@ -51,8 +51,13 @@ public class NioSelectorGroupTests extends OpenSearchTestCase {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
nioGroup = new NioSelectorGroup(daemonThreadFactory(Settings.EMPTY, "acceptor"), 1,
|
||||
daemonThreadFactory(Settings.EMPTY, "selector"), 1, (s) -> new EventHandler(mock(Consumer.class), s));
|
||||
nioGroup = new NioSelectorGroup(
|
||||
daemonThreadFactory(Settings.EMPTY, "acceptor"),
|
||||
1,
|
||||
daemonThreadFactory(Settings.EMPTY, "selector"),
|
||||
1,
|
||||
(s) -> new EventHandler(mock(Consumer.class), s)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,11 +76,15 @@ public class NioSelectorGroupTests extends OpenSearchTestCase {
|
|||
public void testCannotOperateAfterClose() throws IOException {
|
||||
nioGroup.close();
|
||||
|
||||
IllegalStateException ise = expectThrows(IllegalStateException.class,
|
||||
() -> nioGroup.bindServerChannel(mock(InetSocketAddress.class), mock(ChannelFactory.class)));
|
||||
IllegalStateException ise = expectThrows(
|
||||
IllegalStateException.class,
|
||||
() -> nioGroup.bindServerChannel(mock(InetSocketAddress.class), mock(ChannelFactory.class))
|
||||
);
|
||||
assertEquals("NioGroup is closed.", ise.getMessage());
|
||||
ise = expectThrows(IllegalStateException.class,
|
||||
() -> nioGroup.openChannel(mock(InetSocketAddress.class), mock(ChannelFactory.class)));
|
||||
ise = expectThrows(
|
||||
IllegalStateException.class,
|
||||
() -> nioGroup.openChannel(mock(InetSocketAddress.class), mock(ChannelFactory.class))
|
||||
);
|
||||
assertEquals("NioGroup is closed.", ise.getMessage());
|
||||
}
|
||||
|
||||
|
@ -87,9 +96,13 @@ public class NioSelectorGroupTests extends OpenSearchTestCase {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void testExceptionAtStartIsHandled() throws IOException {
|
||||
RuntimeException ex = new RuntimeException();
|
||||
CheckedRunnable<IOException> ctor = () -> new NioSelectorGroup(r -> {throw ex;}, 1,
|
||||
CheckedRunnable<IOException> ctor = () -> new NioSelectorGroup(
|
||||
r -> { throw ex; },
|
||||
1,
|
||||
daemonThreadFactory(Settings.EMPTY, "selector"),
|
||||
1, (s) -> new EventHandler(mock(Consumer.class), s));
|
||||
1,
|
||||
(s) -> new EventHandler(mock(Consumer.class), s)
|
||||
);
|
||||
RuntimeException runtimeException = expectThrows(RuntimeException.class, ctor::run);
|
||||
assertSame(ex, runtimeException);
|
||||
// ctor starts threads. So we are testing that a failure to construct will stop threads. Our thread
|
||||
|
|
|
@ -72,7 +72,7 @@ public class NioSelectorTests extends OpenSearchTestCase {
|
|||
private SocketChannelContext channelContext;
|
||||
private ServerChannelContext serverChannelContext;
|
||||
private BiConsumer<Void, Exception> listener;
|
||||
private ByteBuffer[] buffers = {ByteBuffer.allocate(1)};
|
||||
private ByteBuffer[] buffers = { ByteBuffer.allocate(1) };
|
||||
private Selector rawSelector;
|
||||
|
||||
@Before
|
||||
|
@ -107,7 +107,7 @@ public class NioSelectorTests extends OpenSearchTestCase {
|
|||
}).when(eventHandler).handleTask(any());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void testQueueChannelForClosed() throws IOException {
|
||||
NioChannel channel = mock(NioChannel.class);
|
||||
ChannelContext context = mock(ChannelContext.class);
|
||||
|
@ -121,7 +121,7 @@ public class NioSelectorTests extends OpenSearchTestCase {
|
|||
verify(eventHandler).handleClose(context);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void testCloseException() throws IOException, InterruptedException {
|
||||
IOException ioException = new IOException();
|
||||
NioChannel channel = mock(NioChannel.class);
|
||||
|
@ -152,9 +152,7 @@ public class NioSelectorTests extends OpenSearchTestCase {
|
|||
public void testTaskExceptionsAreHandled() {
|
||||
RuntimeException taskException = new RuntimeException();
|
||||
long nanoTime = System.nanoTime() - 1;
|
||||
Runnable task = () -> {
|
||||
throw taskException;
|
||||
};
|
||||
Runnable task = () -> { throw taskException; };
|
||||
selector.getTaskScheduler().scheduleAtRelativeTime(task, nanoTime);
|
||||
|
||||
doAnswer((a) -> {
|
||||
|
@ -168,8 +166,7 @@ public class NioSelectorTests extends OpenSearchTestCase {
|
|||
|
||||
public void testDefaultSelectorTimeoutIsUsedIfNoTaskSooner() throws IOException {
|
||||
long delay = new TimeValue(15, TimeUnit.MINUTES).nanos();
|
||||
selector.getTaskScheduler().scheduleAtRelativeTime(() -> {
|
||||
}, System.nanoTime() + delay);
|
||||
selector.getTaskScheduler().scheduleAtRelativeTime(() -> {}, System.nanoTime() + delay);
|
||||
|
||||
selector.singleLoop();
|
||||
verify(rawSelector).select(300);
|
||||
|
@ -181,8 +178,7 @@ public class NioSelectorTests extends OpenSearchTestCase {
|
|||
assertBusy(() -> {
|
||||
ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class);
|
||||
long delay = new TimeValue(50, TimeUnit.MILLISECONDS).nanos();
|
||||
selector.getTaskScheduler().scheduleAtRelativeTime(() -> {
|
||||
}, System.nanoTime() + delay);
|
||||
selector.getTaskScheduler().scheduleAtRelativeTime(() -> {}, System.nanoTime() + delay);
|
||||
selector.singleLoop();
|
||||
verify(rawSelector).select(captor.capture());
|
||||
assertTrue(captor.getValue() > 0);
|
||||
|
|
|
@ -136,8 +136,18 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
boolean tcpReuseAddress = randomBoolean();
|
||||
int tcpSendBufferSize = randomIntBetween(1000, 2000);
|
||||
int tcpReceiveBufferSize = randomIntBetween(1000, 2000);
|
||||
config = new Config.Socket(tcpNoDelay, tcpKeepAlive, tcpKeepIdle, tcpKeepInterval, tcpKeepCount, tcpReuseAddress, tcpSendBufferSize,
|
||||
tcpReceiveBufferSize, address, isAccepted);
|
||||
config = new Config.Socket(
|
||||
tcpNoDelay,
|
||||
tcpKeepAlive,
|
||||
tcpKeepIdle,
|
||||
tcpKeepInterval,
|
||||
tcpKeepCount,
|
||||
tcpReuseAddress,
|
||||
tcpSendBufferSize,
|
||||
tcpReceiveBufferSize,
|
||||
address,
|
||||
isAccepted
|
||||
);
|
||||
InboundChannelBuffer buffer = InboundChannelBuffer.allocatingInstance();
|
||||
TestSocketChannelContext context = new TestSocketChannelContext(channel, selector, exceptionHandler, handler, buffer, config);
|
||||
context.register();
|
||||
|
@ -205,8 +215,18 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
boolean tcpReuseAddress = randomBoolean();
|
||||
int tcpSendBufferSize = randomIntBetween(1000, 2000);
|
||||
int tcpReceiveBufferSize = randomIntBetween(1000, 2000);
|
||||
config = new Config.Socket(tcpNoDelay, tcpKeepAlive, tcpKeepIdle, tcpKeepInterval, tcpKeepCount, tcpReuseAddress, tcpSendBufferSize,
|
||||
tcpReceiveBufferSize, address, false);
|
||||
config = new Config.Socket(
|
||||
tcpNoDelay,
|
||||
tcpKeepAlive,
|
||||
tcpKeepIdle,
|
||||
tcpKeepInterval,
|
||||
tcpKeepCount,
|
||||
tcpReuseAddress,
|
||||
tcpSendBufferSize,
|
||||
tcpReceiveBufferSize,
|
||||
address,
|
||||
false
|
||||
);
|
||||
InboundChannelBuffer buffer = InboundChannelBuffer.allocatingInstance();
|
||||
TestSocketChannelContext context = new TestSocketChannelContext(channel, selector, exceptionHandler, handler, buffer, config);
|
||||
doThrow(new SocketException()).doNothing().when(rawSocket).setReuseAddress(tcpReuseAddress);
|
||||
|
@ -229,7 +249,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
public void testWriteFailsIfClosing() {
|
||||
context.closeChannel();
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.wrap(createMessage(10))};
|
||||
ByteBuffer[] buffers = { ByteBuffer.wrap(createMessage(10)) };
|
||||
context.sendMessage(buffers, listener);
|
||||
|
||||
verify(listener).accept(isNull(Void.class), any(ClosedChannelException.class));
|
||||
|
@ -240,7 +260,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
|
||||
when(selector.isOnCurrentThread()).thenReturn(false);
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.wrap(createMessage(10))};
|
||||
ByteBuffer[] buffers = { ByteBuffer.wrap(createMessage(10)) };
|
||||
WriteOperation writeOperation = mock(WriteOperation.class);
|
||||
when(handler.createWriteOperation(context, buffers, listener)).thenReturn(writeOperation);
|
||||
context.sendMessage(buffers, listener);
|
||||
|
@ -254,7 +274,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
public void testSendMessageFromSameThreadIsQueuedInChannel() {
|
||||
ArgumentCaptor<WriteOperation> writeOpCaptor = ArgumentCaptor.forClass(WriteOperation.class);
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.wrap(createMessage(10))};
|
||||
ByteBuffer[] buffers = { ByteBuffer.wrap(createMessage(10)) };
|
||||
WriteOperation writeOperation = mock(WriteOperation.class);
|
||||
when(handler.createWriteOperation(context, buffers, listener)).thenReturn(writeOperation);
|
||||
context.sendMessage(buffers, listener);
|
||||
|
@ -268,7 +288,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
public void testWriteIsQueuedInChannel() {
|
||||
assertFalse(context.readyForFlush());
|
||||
|
||||
ByteBuffer[] buffer = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffer = { ByteBuffer.allocate(10) };
|
||||
FlushReadyWrite writeOperation = new FlushReadyWrite(context, buffer, listener);
|
||||
when(handler.writeToBytes(writeOperation)).thenReturn(Collections.singletonList(writeOperation));
|
||||
context.queueWriteOperation(writeOperation);
|
||||
|
@ -284,7 +304,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
assertTrue(context.readyForFlush());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "varargs"})
|
||||
@SuppressWarnings({ "unchecked", "varargs" })
|
||||
public void testFlushOpsClearedOnClose() throws Exception {
|
||||
try (SocketChannel realChannel = SocketChannel.open()) {
|
||||
when(channel.getRawChannel()).thenReturn(realChannel);
|
||||
|
@ -293,11 +313,12 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
|
||||
assertFalse(context.readyForFlush());
|
||||
|
||||
ByteBuffer[] buffer = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffer = { ByteBuffer.allocate(10) };
|
||||
WriteOperation writeOperation = mock(WriteOperation.class);
|
||||
BiConsumer<Void, Exception> listener2 = mock(BiConsumer.class);
|
||||
when(handler.writeToBytes(writeOperation)).thenReturn(Arrays.asList(new FlushOperation(buffer, listener),
|
||||
new FlushOperation(buffer, listener2)));
|
||||
when(handler.writeToBytes(writeOperation)).thenReturn(
|
||||
Arrays.asList(new FlushOperation(buffer, listener), new FlushOperation(buffer, listener2))
|
||||
);
|
||||
context.queueWriteOperation(writeOperation);
|
||||
|
||||
assertTrue(context.readyForFlush());
|
||||
|
@ -312,21 +333,21 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "varargs"})
|
||||
@SuppressWarnings({ "unchecked", "varargs" })
|
||||
public void testWillPollForFlushOpsToClose() throws Exception {
|
||||
try (SocketChannel realChannel = SocketChannel.open()) {
|
||||
when(channel.getRawChannel()).thenReturn(realChannel);
|
||||
InboundChannelBuffer channelBuffer = InboundChannelBuffer.allocatingInstance();
|
||||
context = new TestSocketChannelContext(channel, selector, exceptionHandler, handler, channelBuffer);
|
||||
|
||||
|
||||
ByteBuffer[] buffer = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffer = { ByteBuffer.allocate(10) };
|
||||
BiConsumer<Void, Exception> listener2 = mock(BiConsumer.class);
|
||||
|
||||
assertFalse(context.readyForFlush());
|
||||
when(channel.isOpen()).thenReturn(true);
|
||||
when(handler.pollFlushOperations()).thenReturn(Arrays.asList(new FlushOperation(buffer, listener),
|
||||
new FlushOperation(buffer, listener2)));
|
||||
when(handler.pollFlushOperations()).thenReturn(
|
||||
Arrays.asList(new FlushOperation(buffer, listener), new FlushOperation(buffer, listener2))
|
||||
);
|
||||
context.closeFromSelector();
|
||||
|
||||
verify(selector, times(1)).executeFailedListener(same(listener), any(ClosedChannelException.class));
|
||||
|
@ -341,8 +362,14 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
when(channel.getRawChannel()).thenReturn(realChannel);
|
||||
when(channel.isOpen()).thenReturn(true);
|
||||
InboundChannelBuffer buffer = InboundChannelBuffer.allocatingInstance();
|
||||
BytesChannelContext context = new BytesChannelContext(channel, selector, mock(Config.Socket.class), exceptionHandler, handler,
|
||||
buffer);
|
||||
BytesChannelContext context = new BytesChannelContext(
|
||||
channel,
|
||||
selector,
|
||||
mock(Config.Socket.class),
|
||||
exceptionHandler,
|
||||
handler,
|
||||
buffer
|
||||
);
|
||||
context.closeFromSelector();
|
||||
verify(handler).close();
|
||||
}
|
||||
|
@ -371,7 +398,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
assertEquals(ioBuffer.capacity(), channelBuffer.getIndex());
|
||||
}
|
||||
|
||||
public void testReadToChannelBufferHandlesIOException() throws IOException {
|
||||
public void testReadToChannelBufferHandlesIOException() throws IOException {
|
||||
when(rawChannel.read(any(ByteBuffer.class))).thenThrow(new IOException());
|
||||
|
||||
InboundChannelBuffer channelBuffer = InboundChannelBuffer.allocatingInstance();
|
||||
|
@ -392,7 +419,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
public void testFlushBuffersHandlesZeroFlush() throws IOException {
|
||||
when(rawChannel.write(any(ByteBuffer.class))).thenAnswer(consumeBufferAnswer(0));
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(1023), ByteBuffer.allocate(1023)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(1023), ByteBuffer.allocate(1023) };
|
||||
FlushOperation flushOperation = new FlushOperation(buffers, listener);
|
||||
context.flushToChannel(flushOperation);
|
||||
assertEquals(2, flushOperation.getBuffersToWrite().length);
|
||||
|
@ -409,7 +436,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
}
|
||||
});
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(1023), ByteBuffer.allocate(1023)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(1023), ByteBuffer.allocate(1023) };
|
||||
FlushOperation flushOperation = new FlushOperation(buffers, listener);
|
||||
context.flushToChannel(flushOperation);
|
||||
assertEquals(1, flushOperation.getBuffersToWrite().length);
|
||||
|
@ -426,7 +453,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
}
|
||||
});
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(1023), ByteBuffer.allocate(1023)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(1023), ByteBuffer.allocate(1023) };
|
||||
FlushOperation flushOperation = new FlushOperation(buffers, listener);
|
||||
context.flushToChannel(flushOperation);
|
||||
assertTrue(flushOperation.isFullyFlushed());
|
||||
|
@ -435,7 +462,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
public void testFlushBuffersHandlesIOException() throws IOException {
|
||||
when(rawChannel.write(any(ByteBuffer.class))).thenThrow(new IOException());
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(10), ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(10), ByteBuffer.allocate(10) };
|
||||
FlushOperation flushOperation = new FlushOperation(buffers, listener);
|
||||
expectThrows(IOException.class, () -> context.flushToChannel(flushOperation));
|
||||
assertTrue(context.closeNow());
|
||||
|
@ -451,7 +478,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
}
|
||||
});
|
||||
|
||||
ByteBuffer[] buffers = {ByteBuffer.allocate(1023), ByteBuffer.allocate(1023)};
|
||||
ByteBuffer[] buffers = { ByteBuffer.allocate(1023), ByteBuffer.allocate(1023) };
|
||||
FlushOperation flushOperation = new FlushOperation(buffers, listener);
|
||||
expectThrows(IOException.class, () -> context.flushToChannel(flushOperation));
|
||||
assertTrue(context.closeNow());
|
||||
|
@ -460,19 +487,40 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
}
|
||||
|
||||
private static Config.Socket getSocketConfig() {
|
||||
return new Config.Socket(randomBoolean(), randomBoolean(), -1, -1, -1, randomBoolean(), -1, -1, mock(InetSocketAddress.class),
|
||||
randomBoolean());
|
||||
return new Config.Socket(
|
||||
randomBoolean(),
|
||||
randomBoolean(),
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
randomBoolean(),
|
||||
-1,
|
||||
-1,
|
||||
mock(InetSocketAddress.class),
|
||||
randomBoolean()
|
||||
);
|
||||
}
|
||||
|
||||
private static class TestSocketChannelContext extends SocketChannelContext {
|
||||
|
||||
private TestSocketChannelContext(NioSocketChannel channel, NioSelector selector, Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler readWriteHandler, InboundChannelBuffer channelBuffer) {
|
||||
private TestSocketChannelContext(
|
||||
NioSocketChannel channel,
|
||||
NioSelector selector,
|
||||
Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler readWriteHandler,
|
||||
InboundChannelBuffer channelBuffer
|
||||
) {
|
||||
this(channel, selector, exceptionHandler, readWriteHandler, channelBuffer, getSocketConfig());
|
||||
}
|
||||
|
||||
private TestSocketChannelContext(NioSocketChannel channel, NioSelector selector, Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler readWriteHandler, InboundChannelBuffer channelBuffer, Config.Socket config) {
|
||||
private TestSocketChannelContext(
|
||||
NioSocketChannel channel,
|
||||
NioSelector selector,
|
||||
Consumer<Exception> exceptionHandler,
|
||||
NioChannelHandler readWriteHandler,
|
||||
InboundChannelBuffer channelBuffer,
|
||||
Config.Socket config
|
||||
) {
|
||||
super(channel, selector, config, exceptionHandler, readWriteHandler, channelBuffer);
|
||||
}
|
||||
|
||||
|
@ -484,7 +532,7 @@ public class SocketChannelContextTests extends OpenSearchTestCase {
|
|||
|
||||
@Override
|
||||
public void flushChannel() throws IOException {
|
||||
ByteBuffer[] byteBuffers = {ByteBuffer.allocate(10)};
|
||||
ByteBuffer[] byteBuffers = { ByteBuffer.allocate(10) };
|
||||
flushToChannel(new FlushOperation(byteBuffers, (v, e) -> {}));
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,8 @@ public class ExtendedPluginsClassLoader extends ClassLoader {
|
|||
* Return a new classloader across the parent and extended loaders.
|
||||
*/
|
||||
public static ExtendedPluginsClassLoader create(ClassLoader parent, List<ClassLoader> extendedLoaders) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<ExtendedPluginsClassLoader>)
|
||||
() -> new ExtendedPluginsClassLoader(parent, extendedLoaders));
|
||||
return AccessController.doPrivileged(
|
||||
(PrivilegedAction<ExtendedPluginsClassLoader>) () -> new ExtendedPluginsClassLoader(parent, extendedLoaders)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,10 +106,10 @@ public class SecureSM extends SecurityManager {
|
|||
* <li><code>org.eclipse.internal.junit.runner.</code></li>
|
||||
* <li><code>com.intellij.rt.execution.junit.</code></li>
|
||||
* </ul>
|
||||
*
|
||||
* For testing purposes, the security manager grants network permissions "connect, accept"
|
||||
*
|
||||
* For testing purposes, the security manager grants network permissions "connect, accept"
|
||||
* to following classes, granted they only access local network interfaces.
|
||||
*
|
||||
*
|
||||
* <ul>
|
||||
* <li><code>sun.net.httpserver.ServerImpl</code></li>
|
||||
* <li><code>java.net.ServerSocket"</code></li>
|
||||
|
@ -121,31 +121,26 @@ public class SecureSM extends SecurityManager {
|
|||
public static SecureSM createTestSecureSM(final Set<String> trustedHosts) {
|
||||
return new SecureSM(TEST_RUNNER_PACKAGES) {
|
||||
// Trust these callers inside the test suite only
|
||||
final String[] TRUSTED_CALLERS = new String[] {
|
||||
"sun.net.httpserver.ServerImpl",
|
||||
"java.net.ServerSocket",
|
||||
"java.net.Socket"
|
||||
};
|
||||
|
||||
final String[] TRUSTED_CALLERS = new String[] { "sun.net.httpserver.ServerImpl", "java.net.ServerSocket", "java.net.Socket" };
|
||||
|
||||
@Override
|
||||
public void checkConnect(String host, int port) {
|
||||
// Allow to connect from selected trusted classes to local addresses only
|
||||
// Allow to connect from selected trusted classes to local addresses only
|
||||
if (!hasTrustedCallerChain() || !trustedHosts.contains(host)) {
|
||||
super.checkConnect(host, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void checkAccept(String host, int port) {
|
||||
// Allow to accept connections from selected trusted classes to local addresses only
|
||||
// Allow to accept connections from selected trusted classes to local addresses only
|
||||
if (!hasTrustedCallerChain() || !trustedHosts.contains(host)) {
|
||||
super.checkAccept(host, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean hasTrustedCallerChain() {
|
||||
return Arrays
|
||||
.stream(getClassContext())
|
||||
return Arrays.stream(getClassContext())
|
||||
.anyMatch(c -> Arrays.stream(TRUSTED_CALLERS).anyMatch(t -> c.getName().startsWith(t)));
|
||||
}
|
||||
};
|
||||
|
@ -161,8 +156,7 @@ public class SecureSM extends SecurityManager {
|
|||
// intellij test runner (before IDEA version 2019.3)
|
||||
"com\\.intellij\\.rt\\.execution\\.junit\\..*",
|
||||
// intellij test runner (since IDEA version 2019.3)
|
||||
"com\\.intellij\\.rt\\.junit\\..*"
|
||||
};
|
||||
"com\\.intellij\\.rt\\.junit\\..*" };
|
||||
|
||||
// java.security.debug support
|
||||
private static final boolean DEBUG = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||
|
@ -270,15 +264,12 @@ public class SecureSM extends SecurityManager {
|
|||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
final String systemClassName = System.class.getName(),
|
||||
runtimeClassName = Runtime.class.getName();
|
||||
final String systemClassName = System.class.getName(), runtimeClassName = Runtime.class.getName();
|
||||
String exitMethodHit = null;
|
||||
for (final StackTraceElement se : Thread.currentThread().getStackTrace()) {
|
||||
final String className = se.getClassName(), methodName = se.getMethodName();
|
||||
if (
|
||||
("exit".equals(methodName) || "halt".equals(methodName)) &&
|
||||
(systemClassName.equals(className) || runtimeClassName.equals(className))
|
||||
) {
|
||||
if (("exit".equals(methodName) || "halt".equals(methodName))
|
||||
&& (systemClassName.equals(className) || runtimeClassName.equals(className))) {
|
||||
exitMethodHit = className + '#' + methodName + '(' + status + ')';
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -74,8 +74,8 @@ public class SecureSMTests extends TestCase {
|
|||
assertTrue(SecureSM.classCanExit("com.carrotsearch.ant.tasks.junit4.slave.JvmExit", SecureSM.TEST_RUNNER_PACKAGES));
|
||||
assertTrue(SecureSM.classCanExit("org.eclipse.jdt.internal.junit.runner.RemoteTestRunner", SecureSM.TEST_RUNNER_PACKAGES));
|
||||
assertTrue(SecureSM.classCanExit("com.intellij.rt.execution.junit.JUnitStarter", SecureSM.TEST_RUNNER_PACKAGES));
|
||||
assertTrue(SecureSM.classCanExit("org.opensearch.Foo", new String[]{"org.opensearch.Foo"}));
|
||||
assertFalse(SecureSM.classCanExit("org.opensearch.Foo", new String[]{"org.opensearch.Bar"}));
|
||||
assertTrue(SecureSM.classCanExit("org.opensearch.Foo", new String[] { "org.opensearch.Foo" }));
|
||||
assertFalse(SecureSM.classCanExit("org.opensearch.Foo", new String[] { "org.opensearch.Bar" }));
|
||||
}
|
||||
|
||||
public void testCreateThread() throws Exception {
|
||||
|
|
|
@ -44,7 +44,8 @@ public class ThreadPermissionTests extends TestCase {
|
|||
public void testEquals() {
|
||||
assertEquals(new ThreadPermission("modifyArbitraryThread"), new ThreadPermission("modifyArbitraryThread"));
|
||||
assertFalse(new ThreadPermission("modifyArbitraryThread").equals(new AllPermission()));
|
||||
assertFalse(new ThreadPermission("modifyArbitraryThread").equals(new ThreadPermission("modifyArbitraryThreadGroup"))); }
|
||||
assertFalse(new ThreadPermission("modifyArbitraryThread").equals(new ThreadPermission("modifyArbitraryThreadGroup")));
|
||||
}
|
||||
|
||||
public void testImplies() {
|
||||
assertTrue(new ThreadPermission("modifyArbitraryThread").implies(new ThreadPermission("modifyArbitraryThread")));
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
package org.opensearch.common.ssl;
|
||||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -64,7 +63,6 @@ final class DerParser {
|
|||
private static final int UNIVERSAL_STRING = 0x1C;
|
||||
private static final int BMP_STRING = 0x1E;
|
||||
|
||||
|
||||
private InputStream derInputStream;
|
||||
private int maxAsnObjectLength;
|
||||
|
||||
|
@ -82,14 +80,16 @@ final class DerParser {
|
|||
// getLength() can return any 32 bit integer, so ensure that a corrupted encoding won't
|
||||
// force us into allocating a very large array
|
||||
if (length > maxAsnObjectLength) {
|
||||
throw new IOException("Invalid DER: size of ASN.1 object to be parsed appears to be larger than the size of the key file " +
|
||||
"itself.");
|
||||
throw new IOException(
|
||||
"Invalid DER: size of ASN.1 object to be parsed appears to be larger than the size of the key file " + "itself."
|
||||
);
|
||||
}
|
||||
byte[] value = new byte[length];
|
||||
int n = derInputStream.read(value);
|
||||
if (n < length) {
|
||||
throw new IOException("Invalid DER: stream too short, missing value. " +
|
||||
"Could only read " + n + " out of " + length + " bytes");
|
||||
throw new IOException(
|
||||
"Invalid DER: stream too short, missing value. " + "Could only read " + n + " out of " + length + " bytes"
|
||||
);
|
||||
}
|
||||
return new Asn1Object(tag, length, value);
|
||||
|
||||
|
@ -117,29 +117,23 @@ final class DerParser {
|
|||
private int getLength() throws IOException {
|
||||
|
||||
int i = derInputStream.read();
|
||||
if (i == -1)
|
||||
throw new IOException("Invalid DER: length missing");
|
||||
if (i == -1) throw new IOException("Invalid DER: length missing");
|
||||
|
||||
// A single byte short length
|
||||
if ((i & ~0x7F) == 0)
|
||||
return i;
|
||||
if ((i & ~0x7F) == 0) return i;
|
||||
|
||||
int num = i & 0x7F;
|
||||
|
||||
// We can't handle length longer than 4 bytes
|
||||
if (i >= 0xFF || num > 4)
|
||||
throw new IOException("Invalid DER: length field too big ("
|
||||
+ i + ")"); //$NON-NLS-1$
|
||||
if (i >= 0xFF || num > 4) throw new IOException("Invalid DER: length field too big (" + i + ")"); //$NON-NLS-2$
|
||||
|
||||
byte[] bytes = new byte[num];
|
||||
int n = derInputStream.read(bytes);
|
||||
if (n < num)
|
||||
throw new IOException("Invalid DER: length too short");
|
||||
if (n < num) throw new IOException("Invalid DER: length too short");
|
||||
|
||||
return new BigInteger(1, bytes).intValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An ASN.1 TLV. The object is not parsed. It can
|
||||
* only handle integers.
|
||||
|
@ -207,8 +201,7 @@ final class DerParser {
|
|||
* @return A parser for the construct.
|
||||
*/
|
||||
public DerParser getParser() throws IOException {
|
||||
if (!isConstructed())
|
||||
throw new IOException("Invalid DER: can't parse primitive entity"); //$NON-NLS-1$
|
||||
if (!isConstructed()) throw new IOException("Invalid DER: can't parse primitive entity"); //$NON-NLS-1$
|
||||
|
||||
return new DerParser(value);
|
||||
}
|
||||
|
@ -219,8 +212,7 @@ final class DerParser {
|
|||
* @return BigInteger
|
||||
*/
|
||||
public BigInteger getInteger() throws IOException {
|
||||
if (type != DerParser.INTEGER)
|
||||
throw new IOException("Invalid DER: object is not integer"); //$NON-NLS-1$
|
||||
if (type != DerParser.INTEGER) throw new IOException("Invalid DER: object is not integer"); //$NON-NLS-1$
|
||||
|
||||
return new BigInteger(value);
|
||||
}
|
||||
|
@ -295,6 +287,7 @@ final class DerParser {
|
|||
}
|
||||
|
||||
private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
|
||||
|
||||
private static String toHexString(byte[] bytes) {
|
||||
Objects.requireNonNull(bytes);
|
||||
StringBuilder sb = new StringBuilder(2 * bytes.length);
|
||||
|
|
|
@ -52,7 +52,6 @@ import static org.opensearch.common.ssl.SslDiagnostics.getTrustDiagnosticFailure
|
|||
|
||||
public final class DiagnosticTrustManager extends X509ExtendedTrustManager {
|
||||
|
||||
|
||||
/**
|
||||
* This interface exists because the ssl-config library does not depend on log4j, however the whole purpose of this class is to log
|
||||
* diagnostic messages, so it must be provided with a function by which it can do that.
|
||||
|
@ -62,7 +61,6 @@ public final class DiagnosticTrustManager extends X509ExtendedTrustManager {
|
|||
void warning(String message, GeneralSecurityException cause);
|
||||
}
|
||||
|
||||
|
||||
private final X509ExtendedTrustManager delegate;
|
||||
private final Supplier<String> contextName;
|
||||
private final DiagnosticLogger logger;
|
||||
|
@ -78,13 +76,18 @@ public final class DiagnosticTrustManager extends X509ExtendedTrustManager {
|
|||
this.contextName = contextName;
|
||||
this.logger = logger;
|
||||
this.issuers = Stream.of(delegate.getAcceptedIssuers())
|
||||
.collect(Collectors.toMap(cert -> cert.getSubjectX500Principal().getName(), Collections::singletonList,
|
||||
(List<X509Certificate> a, List<X509Certificate> b) -> {
|
||||
final ArrayList<X509Certificate> list = new ArrayList<>(a.size() + b.size());
|
||||
list.addAll(a);
|
||||
list.addAll(b);
|
||||
return list;
|
||||
}));
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
cert -> cert.getSubjectX500Principal().getName(),
|
||||
Collections::singletonList,
|
||||
(List<X509Certificate> a, List<X509Certificate> b) -> {
|
||||
final ArrayList<X509Certificate> list = new ArrayList<>(a.size() + b.size());
|
||||
list.addAll(a);
|
||||
list.addAll(b);
|
||||
return list;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -83,8 +83,9 @@ final class KeyStoreUtil {
|
|||
*/
|
||||
static KeyStore readKeyStore(Path path, String type, char[] password) throws GeneralSecurityException {
|
||||
if (Files.notExists(path)) {
|
||||
throw new SslConfigException("cannot read a [" + type + "] keystore from [" + path.toAbsolutePath()
|
||||
+ "] because the file does not exist");
|
||||
throw new SslConfigException(
|
||||
"cannot read a [" + type + "] keystore from [" + path.toAbsolutePath() + "] because the file does not exist"
|
||||
);
|
||||
}
|
||||
try {
|
||||
KeyStore keyStore = KeyStore.getInstance(type);
|
||||
|
@ -93,8 +94,10 @@ final class KeyStoreUtil {
|
|||
}
|
||||
return keyStore;
|
||||
} catch (IOException e) {
|
||||
throw new SslConfigException("cannot read a [" + type + "] keystore from [" + path.toAbsolutePath() + "] - " + e.getMessage(),
|
||||
e);
|
||||
throw new SslConfigException(
|
||||
"cannot read a [" + type + "] keystore from [" + path.toAbsolutePath() + "] - " + e.getMessage(),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,15 +154,16 @@ final class KeyStoreUtil {
|
|||
return (X509ExtendedKeyManager) keyManager;
|
||||
}
|
||||
}
|
||||
throw new SslConfigException("failed to find a X509ExtendedKeyManager in the key manager factory for [" + algorithm
|
||||
+ "] and keystore [" + keyStore + "]");
|
||||
throw new SslConfigException(
|
||||
"failed to find a X509ExtendedKeyManager in the key manager factory for [" + algorithm + "] and keystore [" + keyStore + "]"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link X509ExtendedTrustManager} based on the trust material in the provided {@link KeyStore}
|
||||
*/
|
||||
static X509ExtendedTrustManager createTrustManager(@Nullable KeyStore trustStore, String algorithm)
|
||||
throws NoSuchAlgorithmException, KeyStoreException {
|
||||
static X509ExtendedTrustManager createTrustManager(@Nullable KeyStore trustStore, String algorithm) throws NoSuchAlgorithmException,
|
||||
KeyStoreException {
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
|
||||
tmf.init(trustStore);
|
||||
TrustManager[] trustManagers = tmf.getTrustManagers();
|
||||
|
@ -168,9 +172,13 @@ final class KeyStoreUtil {
|
|||
return (X509ExtendedTrustManager) trustManager;
|
||||
}
|
||||
}
|
||||
throw new SslConfigException("failed to find a X509ExtendedTrustManager in the trust manager factory for [" + algorithm
|
||||
+ "] and truststore [" + trustStore + "]");
|
||||
throw new SslConfigException(
|
||||
"failed to find a X509ExtendedTrustManager in the trust manager factory for ["
|
||||
+ algorithm
|
||||
+ "] and truststore ["
|
||||
+ trustStore
|
||||
+ "]"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ public final class PemKeyConfig implements SslKeyConfig {
|
|||
} catch (FileNotFoundException | NoSuchFileException e) {
|
||||
throw new SslConfigException("the configured ssl certificate file [" + certificate.toAbsolutePath() + "] does not exist", e);
|
||||
} catch (IOException e) {
|
||||
throw new SslConfigException("the configured ssl certificate file [" + certificate .toAbsolutePath()+ "] cannot be read", e);
|
||||
throw new SslConfigException("the configured ssl certificate file [" + certificate.toAbsolutePath() + "] cannot be read", e);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new SslConfigException("cannot load ssl certificate from [" + certificate.toAbsolutePath() + "]", e);
|
||||
}
|
||||
|
@ -121,9 +121,9 @@ public final class PemKeyConfig implements SslKeyConfig {
|
|||
return false;
|
||||
}
|
||||
final PemKeyConfig that = (PemKeyConfig) o;
|
||||
return Objects.equals(this.certificate, that.certificate) &&
|
||||
Objects.equals(this.key, that.key) &&
|
||||
Arrays.equals(this.keyPassword, that.keyPassword);
|
||||
return Objects.equals(this.certificate, that.certificate)
|
||||
&& Objects.equals(this.key, that.key)
|
||||
&& Arrays.equals(this.keyPassword, that.keyPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -95,11 +95,15 @@ public final class PemTrustConfig implements SslTrustConfig {
|
|||
try {
|
||||
return PemUtils.readCertificates(this.certificateAuthorities);
|
||||
} catch (FileNotFoundException | NoSuchFileException e) {
|
||||
throw new SslConfigException("cannot configure trust using PEM certificates [" + caPathsAsString()
|
||||
+ "] because one or more files do not exist", e);
|
||||
throw new SslConfigException(
|
||||
"cannot configure trust using PEM certificates [" + caPathsAsString() + "] because one or more files do not exist",
|
||||
e
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new SslConfigException("cannot configure trust using PEM certificates [" + caPathsAsString()
|
||||
+ "] because one or more files cannot be read", e);
|
||||
throw new SslConfigException(
|
||||
"cannot configure trust using PEM certificates [" + caPathsAsString() + "] because one or more files cannot be read",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,10 +130,7 @@ public final class PemTrustConfig implements SslTrustConfig {
|
|||
}
|
||||
|
||||
private String caPathsAsString() {
|
||||
return certificateAuthorities.stream()
|
||||
.map(Path::toAbsolutePath)
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(","));
|
||||
return certificateAuthorities.stream().map(Path::toAbsolutePath).map(Object::toString).collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -81,8 +81,8 @@ final class PemUtils {
|
|||
private static final String PKCS1_FOOTER = "-----END RSA PRIVATE KEY-----";
|
||||
private static final String OPENSSL_DSA_HEADER = "-----BEGIN DSA PRIVATE KEY-----";
|
||||
private static final String OPENSSL_DSA_FOOTER = "-----END DSA PRIVATE KEY-----";
|
||||
private static final String OPENSSL_DSA_PARAMS_HEADER ="-----BEGIN DSA PARAMETERS-----";
|
||||
private static final String OPENSSL_DSA_PARAMS_FOOTER ="-----END DSA PARAMETERS-----";
|
||||
private static final String OPENSSL_DSA_PARAMS_HEADER = "-----BEGIN DSA PARAMETERS-----";
|
||||
private static final String OPENSSL_DSA_PARAMS_FOOTER = "-----END DSA PARAMETERS-----";
|
||||
private static final String PKCS8_HEADER = "-----BEGIN PRIVATE KEY-----";
|
||||
private static final String PKCS8_FOOTER = "-----END PRIVATE KEY-----";
|
||||
private static final String PKCS8_ENCRYPTED_HEADER = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
|
||||
|
@ -133,8 +133,9 @@ final class PemUtils {
|
|||
} else if (OPENSSL_EC_PARAMS_HEADER.equals(line.trim())) {
|
||||
return parseOpenSslEC(removeECHeaders(bReader), passwordSupplier);
|
||||
} else {
|
||||
throw new SslConfigException("error parsing Private Key [" + keyPath.toAbsolutePath()
|
||||
+ "], file does not contain a supported key format");
|
||||
throw new SslConfigException(
|
||||
"error parsing Private Key [" + keyPath.toAbsolutePath() + "], file does not contain a supported key format"
|
||||
);
|
||||
}
|
||||
} catch (FileNotFoundException | NoSuchFileException e) {
|
||||
throw new SslConfigException("private key file [" + keyPath.toAbsolutePath() + "] does not exist", e);
|
||||
|
@ -344,8 +345,7 @@ final class PemUtils {
|
|||
* @throws IOException if the file can't be read
|
||||
* @throws GeneralSecurityException if the private key can't be generated from the {@link PKCS8EncodedKeySpec}
|
||||
*/
|
||||
private static PrivateKey parsePKCS8Encrypted(BufferedReader bReader, char[] keyPassword) throws IOException,
|
||||
GeneralSecurityException {
|
||||
private static PrivateKey parsePKCS8Encrypted(BufferedReader bReader, char[] keyPassword) throws IOException, GeneralSecurityException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = bReader.readLine();
|
||||
while (line != null) {
|
||||
|
@ -386,10 +386,10 @@ final class PemUtils {
|
|||
byte[] keyBytes = Base64.getDecoder().decode(keyContents);
|
||||
String procType = pemHeaders.get("Proc-Type");
|
||||
if ("4,ENCRYPTED".equals(procType)) {
|
||||
//We only handle PEM encryption
|
||||
// We only handle PEM encryption
|
||||
String encryptionParameters = pemHeaders.get("DEK-Info");
|
||||
if (null == encryptionParameters) {
|
||||
//malformed pem
|
||||
// malformed pem
|
||||
throw new IOException("Malformed PEM File, DEK-Info header is missing");
|
||||
}
|
||||
char[] password = passwordSupplier.get();
|
||||
|
@ -415,8 +415,7 @@ final class PemUtils {
|
|||
* for the cipher
|
||||
* @throws IOException if the DEK-Info PEM header is invalid
|
||||
*/
|
||||
private static Cipher getCipherFromParameters(String dekHeaderValue, char[] password) throws
|
||||
GeneralSecurityException, IOException {
|
||||
private static Cipher getCipherFromParameters(String dekHeaderValue, char[] password) throws GeneralSecurityException, IOException {
|
||||
final String padding = "PKCS5Padding";
|
||||
final SecretKey encryptionKey;
|
||||
final String[] valueTokens = dekHeaderValue.split(",");
|
||||
|
@ -501,8 +500,9 @@ final class PemUtils {
|
|||
}
|
||||
return data;
|
||||
} else {
|
||||
throw new IllegalStateException("Hexadecimal string [" + hexString +
|
||||
"] has odd length and cannot be converted to a byte array");
|
||||
throw new IllegalStateException(
|
||||
"Hexadecimal string [" + hexString + "] has odd length and cannot be converted to a byte array"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,8 +513,7 @@ final class PemUtils {
|
|||
* @return {@link ECPrivateKeySpec}
|
||||
* @throws IOException if the DER encoded key can't be parsed
|
||||
*/
|
||||
private static ECPrivateKeySpec parseEcDer(byte[] keyBytes) throws IOException,
|
||||
GeneralSecurityException {
|
||||
private static ECPrivateKeySpec parseEcDer(byte[] keyBytes) throws IOException, GeneralSecurityException {
|
||||
DerParser parser = new DerParser(keyBytes);
|
||||
DerParser.Asn1Object sequence = parser.readAsn1Object();
|
||||
parser = sequence.getParser();
|
||||
|
@ -598,8 +597,9 @@ final class PemUtils {
|
|||
case "1.2.840.10045.2.1":
|
||||
return "EC";
|
||||
}
|
||||
throw new GeneralSecurityException("Error parsing key algorithm identifier. Algorithm with OID [" + oidString +
|
||||
"] is not żsupported");
|
||||
throw new GeneralSecurityException(
|
||||
"Error parsing key algorithm identifier. Algorithm with OID [" + oidString + "] is not żsupported"
|
||||
);
|
||||
}
|
||||
|
||||
static List<Certificate> readCertificates(Collection<Path> certPaths) throws CertificateException, IOException {
|
||||
|
@ -651,8 +651,9 @@ final class PemUtils {
|
|||
case "1.3.132.0.39":
|
||||
return "sect571r1";
|
||||
}
|
||||
throw new GeneralSecurityException("Error parsing EC named curve identifier. Named curve with OID: " + oidString
|
||||
+ " is not supported");
|
||||
throw new GeneralSecurityException(
|
||||
"Error parsing EC named curve identifier. Named curve with OID: " + oidString + " is not supported"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -106,8 +106,9 @@ public enum SslClientAuthenticationMode {
|
|||
final SslClientAuthenticationMode mode = LOOKUP.get(value.toLowerCase(Locale.ROOT));
|
||||
if (mode == null) {
|
||||
final String allowedValues = LOOKUP.keySet().stream().collect(Collectors.joining(","));
|
||||
throw new SslConfigException("could not resolve ssl client authentication, unknown value ["
|
||||
+ value + "], recognised values are [" + allowedValues + "]");
|
||||
throw new SslConfigException(
|
||||
"could not resolve ssl client authentication, unknown value [" + value + "], recognised values are [" + allowedValues + "]"
|
||||
);
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
|
|
@ -87,8 +87,14 @@ public class SslConfiguration {
|
|||
private final List<String> ciphers;
|
||||
private final List<String> supportedProtocols;
|
||||
|
||||
public SslConfiguration(SslTrustConfig trustConfig, SslKeyConfig keyConfig, SslVerificationMode verificationMode,
|
||||
SslClientAuthenticationMode clientAuth, List<String> ciphers, List<String> supportedProtocols) {
|
||||
public SslConfiguration(
|
||||
SslTrustConfig trustConfig,
|
||||
SslKeyConfig keyConfig,
|
||||
SslVerificationMode verificationMode,
|
||||
SslClientAuthenticationMode clientAuth,
|
||||
List<String> ciphers,
|
||||
List<String> supportedProtocols
|
||||
) {
|
||||
if (ciphers == null || ciphers.isEmpty()) {
|
||||
throw new SslConfigException("cannot configure SSL/TLS without any supported cipher suites");
|
||||
}
|
||||
|
@ -169,20 +175,28 @@ public class SslConfiguration {
|
|||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
throw new SslConfigException("no supported SSL/TLS protocol was found in the configured supported protocols: "
|
||||
+ supportedProtocols);
|
||||
throw new SslConfigException(
|
||||
"no supported SSL/TLS protocol was found in the configured supported protocols: " + supportedProtocols
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + '{' +
|
||||
"trustConfig=" + trustConfig +
|
||||
", keyConfig=" + keyConfig +
|
||||
", verificationMode=" + verificationMode +
|
||||
", clientAuth=" + clientAuth +
|
||||
", ciphers=" + ciphers +
|
||||
", supportedProtocols=" + supportedProtocols +
|
||||
'}';
|
||||
return getClass().getSimpleName()
|
||||
+ '{'
|
||||
+ "trustConfig="
|
||||
+ trustConfig
|
||||
+ ", keyConfig="
|
||||
+ keyConfig
|
||||
+ ", verificationMode="
|
||||
+ verificationMode
|
||||
+ ", clientAuth="
|
||||
+ clientAuth
|
||||
+ ", ciphers="
|
||||
+ ciphers
|
||||
+ ", supportedProtocols="
|
||||
+ supportedProtocols
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -190,12 +204,12 @@ public class SslConfiguration {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final SslConfiguration that = (SslConfiguration) o;
|
||||
return Objects.equals(this.trustConfig, that.trustConfig) &&
|
||||
Objects.equals(this.keyConfig, that.keyConfig) &&
|
||||
this.verificationMode == that.verificationMode &&
|
||||
this.clientAuth == that.clientAuth &&
|
||||
Objects.equals(this.ciphers, that.ciphers) &&
|
||||
Objects.equals(this.supportedProtocols, that.supportedProtocols);
|
||||
return Objects.equals(this.trustConfig, that.trustConfig)
|
||||
&& Objects.equals(this.keyConfig, that.keyConfig)
|
||||
&& this.verificationMode == that.verificationMode
|
||||
&& this.clientAuth == that.clientAuth
|
||||
&& Objects.equals(this.ciphers, that.ciphers)
|
||||
&& Objects.equals(this.supportedProtocols, that.supportedProtocols);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -162,10 +162,20 @@ public class SslConfigurationKeys {
|
|||
*/
|
||||
public static List<String> getStringKeys() {
|
||||
return Arrays.asList(
|
||||
VERIFICATION_MODE, CLIENT_AUTH,
|
||||
TRUSTSTORE_PATH, TRUSTSTORE_LEGACY_PASSWORD, TRUSTSTORE_TYPE, TRUSTSTORE_TYPE,
|
||||
KEYSTORE_PATH, KEYSTORE_LEGACY_PASSWORD, KEYSTORE_LEGACY_KEY_PASSWORD, KEYSTORE_TYPE, KEYSTORE_ALGORITHM,
|
||||
CERTIFICATE, KEY, KEY_LEGACY_PASSPHRASE
|
||||
VERIFICATION_MODE,
|
||||
CLIENT_AUTH,
|
||||
TRUSTSTORE_PATH,
|
||||
TRUSTSTORE_LEGACY_PASSWORD,
|
||||
TRUSTSTORE_TYPE,
|
||||
TRUSTSTORE_TYPE,
|
||||
KEYSTORE_PATH,
|
||||
KEYSTORE_LEGACY_PASSWORD,
|
||||
KEYSTORE_LEGACY_KEY_PASSWORD,
|
||||
KEYSTORE_TYPE,
|
||||
KEYSTORE_ALGORITHM,
|
||||
CERTIFICATE,
|
||||
KEY,
|
||||
KEY_LEGACY_PASSPHRASE
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,8 +86,10 @@ import static org.opensearch.common.ssl.SslConfigurationKeys.VERIFICATION_MODE;
|
|||
public abstract class SslConfigurationLoader {
|
||||
|
||||
static final List<String> DEFAULT_PROTOCOLS = Collections.unmodifiableList(
|
||||
ORDERED_PROTOCOL_ALGORITHM_MAP.containsKey("TLSv1.3") ?
|
||||
Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1"));
|
||||
ORDERED_PROTOCOL_ALGORITHM_MAP.containsKey("TLSv1.3")
|
||||
? Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1")
|
||||
: Arrays.asList("TLSv1.2", "TLSv1.1")
|
||||
);
|
||||
static final List<String> DEFAULT_CIPHERS = loadDefaultCiphers();
|
||||
private static final char[] EMPTY_PASSWORD = new char[0];
|
||||
|
||||
|
@ -235,8 +237,9 @@ public abstract class SslConfigurationLoader {
|
|||
final Path trustStorePath = resolveSetting(TRUSTSTORE_PATH, basePath::resolve, null);
|
||||
|
||||
if (certificateAuthorities != null && trustStorePath != null) {
|
||||
throw new SslConfigException("cannot specify both [" + settingPrefix + CERTIFICATE_AUTHORITIES + "] and [" +
|
||||
settingPrefix + TRUSTSTORE_PATH + "]");
|
||||
throw new SslConfigException(
|
||||
"cannot specify both [" + settingPrefix + CERTIFICATE_AUTHORITIES + "] and [" + settingPrefix + TRUSTSTORE_PATH + "]"
|
||||
);
|
||||
}
|
||||
if (verificationMode.isCertificateVerificationEnabled() == false) {
|
||||
return TrustEverythingConfig.TRUST_EVERYTHING;
|
||||
|
@ -259,18 +262,21 @@ public abstract class SslConfigurationLoader {
|
|||
final Path keyStorePath = resolveSetting(KEYSTORE_PATH, basePath::resolve, null);
|
||||
|
||||
if (certificatePath != null && keyStorePath != null) {
|
||||
throw new SslConfigException("cannot specify both [" + settingPrefix + CERTIFICATE + "] and [" +
|
||||
settingPrefix + KEYSTORE_PATH + "]");
|
||||
throw new SslConfigException(
|
||||
"cannot specify both [" + settingPrefix + CERTIFICATE + "] and [" + settingPrefix + KEYSTORE_PATH + "]"
|
||||
);
|
||||
}
|
||||
|
||||
if (certificatePath != null || keyPath != null) {
|
||||
if (keyPath == null) {
|
||||
throw new SslConfigException("cannot specify [" + settingPrefix + CERTIFICATE + "] without also setting [" +
|
||||
settingPrefix + KEY + "]");
|
||||
throw new SslConfigException(
|
||||
"cannot specify [" + settingPrefix + CERTIFICATE + "] without also setting [" + settingPrefix + KEY + "]"
|
||||
);
|
||||
}
|
||||
if (certificatePath == null) {
|
||||
throw new SslConfigException("cannot specify [" + settingPrefix + KEYSTORE_PATH + "] without also setting [" +
|
||||
settingPrefix + CERTIFICATE + "]");
|
||||
throw new SslConfigException(
|
||||
"cannot specify [" + settingPrefix + KEYSTORE_PATH + "] without also setting [" + settingPrefix + CERTIFICATE + "]"
|
||||
);
|
||||
}
|
||||
final char[] password = resolvePasswordSetting(KEY_SECURE_PASSPHRASE, KEY_LEGACY_PASSPHRASE);
|
||||
return new PemKeyConfig(certificatePath, keyPath, password);
|
||||
|
@ -301,8 +307,9 @@ public abstract class SslConfigurationLoader {
|
|||
}
|
||||
} else {
|
||||
if (legacyPassword != null) {
|
||||
throw new SslConfigException("cannot specify both [" + settingPrefix + secureSettingKey + "] and ["
|
||||
+ settingPrefix + legacySettingKey + "]");
|
||||
throw new SslConfigException(
|
||||
"cannot specify both [" + settingPrefix + secureSettingKey + "] and [" + settingPrefix + legacySettingKey + "]"
|
||||
);
|
||||
} else {
|
||||
return securePassword;
|
||||
}
|
||||
|
@ -365,8 +372,14 @@ public abstract class SslConfigurationLoader {
|
|||
}
|
||||
if (useGCM) { // PFS, AEAD, hardware support
|
||||
if (has256BitAES) {
|
||||
ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"));
|
||||
ciphers.addAll(
|
||||
Arrays.asList(
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"));
|
||||
}
|
||||
|
@ -374,13 +387,27 @@ public abstract class SslConfigurationLoader {
|
|||
|
||||
// PFS, hardware support
|
||||
if (has256BitAES) {
|
||||
ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"));
|
||||
ciphers.addAll(
|
||||
Arrays.asList(
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"));
|
||||
ciphers.addAll(
|
||||
Arrays.asList(
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// AEAD, hardware support
|
||||
|
@ -394,8 +421,14 @@ public abstract class SslConfigurationLoader {
|
|||
|
||||
// hardware support
|
||||
if (has256BitAES) {
|
||||
ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA"));
|
||||
ciphers.addAll(
|
||||
Arrays.asList(
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA"));
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue