diff --git a/build.gradle b/build.gradle
index 94823e0ce5b1a..dce2adf5ee0bd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -196,6 +196,7 @@ subprojects {
"org.elasticsearch:elasticsearch-cli:${version}": ':server:cli',
"org.elasticsearch:elasticsearch-core:${version}": ':libs:elasticsearch-core',
"org.elasticsearch:elasticsearch-nio:${version}": ':libs:elasticsearch-nio',
+ "org.elasticsearch:elasticsearch-x-content:${version}": ':libs:x-content',
"org.elasticsearch:elasticsearch-secure-sm:${version}": ':libs:secure-sm',
"org.elasticsearch.client:elasticsearch-rest-client:${version}": ':client:rest',
"org.elasticsearch.client:elasticsearch-rest-client-sniffer:${version}": ':client:sniffer',
diff --git a/buildSrc/src/main/resources/checkstyle_suppressions.xml b/buildSrc/src/main/resources/checkstyle_suppressions.xml
index b1ef76c9d6a0e..11f19f683e557 100644
--- a/buildSrc/src/main/resources/checkstyle_suppressions.xml
+++ b/buildSrc/src/main/resources/checkstyle_suppressions.xml
@@ -248,9 +248,7 @@
-
-
diff --git a/server/src/main/java/org/elasticsearch/common/Booleans.java b/libs/elasticsearch-core/src/main/java/org/elasticsearch/common/Booleans.java
similarity index 94%
rename from server/src/main/java/org/elasticsearch/common/Booleans.java
rename to libs/elasticsearch-core/src/main/java/org/elasticsearch/common/Booleans.java
index 025174c477d64..7447f0111f7e2 100644
--- a/server/src/main/java/org/elasticsearch/common/Booleans.java
+++ b/libs/elasticsearch-core/src/main/java/org/elasticsearch/common/Booleans.java
@@ -73,6 +73,19 @@ public static boolean parseBoolean(String value) {
throw new IllegalArgumentException("Failed to parse value [" + value + "] as only [true] or [false] are allowed.");
}
+ private static boolean hasText(CharSequence str) {
+ if (str == null || str.length() == 0) {
+ return false;
+ }
+ int strLen = str.length();
+ for (int i = 0; i < strLen; i++) {
+ if (!Character.isWhitespace(str.charAt(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
*
* @param value text to parse.
@@ -80,14 +93,14 @@ public static boolean parseBoolean(String value) {
* @return see {@link #parseBoolean(String)}
*/
public static boolean parseBoolean(String value, boolean defaultValue) {
- if (Strings.hasText(value)) {
+ if (hasText(value)) {
return parseBoolean(value);
}
return defaultValue;
}
public static Boolean parseBoolean(String value, Boolean defaultValue) {
- if (Strings.hasText(value)) {
+ if (hasText(value)) {
return parseBoolean(value);
}
return defaultValue;
diff --git a/server/src/main/java/org/elasticsearch/common/CheckedFunction.java b/libs/elasticsearch-core/src/main/java/org/elasticsearch/common/CheckedFunction.java
similarity index 100%
rename from server/src/main/java/org/elasticsearch/common/CheckedFunction.java
rename to libs/elasticsearch-core/src/main/java/org/elasticsearch/common/CheckedFunction.java
diff --git a/libs/elasticsearch-core/src/main/java/org/elasticsearch/common/Glob.java b/libs/elasticsearch-core/src/main/java/org/elasticsearch/common/Glob.java
new file mode 100644
index 0000000000000..f0baf75bd4db1
--- /dev/null
+++ b/libs/elasticsearch-core/src/main/java/org/elasticsearch/common/Glob.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.common;
+
+/**
+ * Utility class for glob-like matching
+ */
+public class Glob {
+
+ /**
+ * Match a String against the given pattern, supporting the following simple
+ * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an
+ * arbitrary number of pattern parts), as well as direct equality.
+ *
+ * @param pattern the pattern to match against
+ * @param str the String to match
+ * @return whether the String matches the given pattern
+ */
+ public static boolean globMatch(String pattern, String str) {
+ if (pattern == null || str == null) {
+ return false;
+ }
+ int firstIndex = pattern.indexOf('*');
+ if (firstIndex == -1) {
+ return pattern.equals(str);
+ }
+ if (firstIndex == 0) {
+ if (pattern.length() == 1) {
+ return true;
+ }
+ int nextIndex = pattern.indexOf('*', firstIndex + 1);
+ if (nextIndex == -1) {
+ return str.endsWith(pattern.substring(1));
+ } else if (nextIndex == 1) {
+ // Double wildcard "**" - skipping the first "*"
+ return globMatch(pattern.substring(1), str);
+ }
+ String part = pattern.substring(1, nextIndex);
+ int partIndex = str.indexOf(part);
+ while (partIndex != -1) {
+ if (globMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) {
+ return true;
+ }
+ partIndex = str.indexOf(part, partIndex + 1);
+ }
+ return false;
+ }
+ return (str.length() >= firstIndex &&
+ pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
+ globMatch(pattern.substring(firstIndex), str.substring(firstIndex)));
+ }
+
+}
diff --git a/libs/x-content/build.gradle b/libs/x-content/build.gradle
new file mode 100644
index 0000000000000..c8b37108ff93c
--- /dev/null
+++ b/libs/x-content/build.gradle
@@ -0,0 +1,85 @@
+import org.elasticsearch.gradle.precommit.PrecommitTasks
+
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+apply plugin: 'elasticsearch.build'
+apply plugin: 'nebula.maven-base-publish'
+apply plugin: 'nebula.maven-scm'
+
+archivesBaseName = 'elasticsearch-x-content'
+
+publishing {
+ publications {
+ nebula {
+ artifactId = archivesBaseName
+ }
+ }
+}
+
+dependencies {
+ compile "org.elasticsearch:elasticsearch-core:${version}"
+
+ compile "org.yaml:snakeyaml:${versions.snakeyaml}"
+ compile "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
+ compile "com.fasterxml.jackson.dataformat:jackson-dataformat-smile:${versions.jackson}"
+ compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${versions.jackson}"
+ compile "com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:${versions.jackson}"
+
+ testCompile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
+ testCompile "junit:junit:${versions.junit}"
+ testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}"
+
+ if (isEclipse == false || project.path == ":libs:x-content-tests") {
+ testCompile("org.elasticsearch.test:framework:${version}") {
+ exclude group: 'org.elasticsearch', module: 'elasticsearch-x-content'
+ }
+ }
+
+}
+
+forbiddenApisMain {
+ // x-content does not depend on server
+ // TODO: Need to decide how we want to handle for forbidden signatures with the changes to core
+ signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt')]
+}
+
+if (isEclipse) {
+ // in eclipse the project is under a fake root, we need to change around the source sets
+ sourceSets {
+ if (project.path == ":libs:x-content") {
+ main.java.srcDirs = ['java']
+ main.resources.srcDirs = ['resources']
+ } else {
+ test.java.srcDirs = ['java']
+ test.resources.srcDirs = ['resources']
+ }
+ }
+}
+
+thirdPartyAudit.excludes = [
+ // from com.fasterxml.jackson.dataformat.yaml.YAMLMapper (jackson-dataformat-yaml)
+ 'com.fasterxml.jackson.databind.ObjectMapper',
+]
+
+dependencyLicenses {
+ mapping from: /jackson-.*/, to: 'jackson'
+}
+
+jarHell.enabled = false
diff --git a/server/licenses/jackson-LICENSE b/libs/x-content/licenses/jackson-LICENSE
similarity index 100%
rename from server/licenses/jackson-LICENSE
rename to libs/x-content/licenses/jackson-LICENSE
diff --git a/server/licenses/jackson-NOTICE b/libs/x-content/licenses/jackson-NOTICE
similarity index 100%
rename from server/licenses/jackson-NOTICE
rename to libs/x-content/licenses/jackson-NOTICE
diff --git a/server/licenses/jackson-core-2.8.10.jar.sha1 b/libs/x-content/licenses/jackson-core-2.8.10.jar.sha1
similarity index 100%
rename from server/licenses/jackson-core-2.8.10.jar.sha1
rename to libs/x-content/licenses/jackson-core-2.8.10.jar.sha1
diff --git a/server/licenses/jackson-dataformat-cbor-2.8.10.jar.sha1 b/libs/x-content/licenses/jackson-dataformat-cbor-2.8.10.jar.sha1
similarity index 100%
rename from server/licenses/jackson-dataformat-cbor-2.8.10.jar.sha1
rename to libs/x-content/licenses/jackson-dataformat-cbor-2.8.10.jar.sha1
diff --git a/server/licenses/jackson-dataformat-smile-2.8.10.jar.sha1 b/libs/x-content/licenses/jackson-dataformat-smile-2.8.10.jar.sha1
similarity index 100%
rename from server/licenses/jackson-dataformat-smile-2.8.10.jar.sha1
rename to libs/x-content/licenses/jackson-dataformat-smile-2.8.10.jar.sha1
diff --git a/server/licenses/jackson-dataformat-yaml-2.8.10.jar.sha1 b/libs/x-content/licenses/jackson-dataformat-yaml-2.8.10.jar.sha1
similarity index 100%
rename from server/licenses/jackson-dataformat-yaml-2.8.10.jar.sha1
rename to libs/x-content/licenses/jackson-dataformat-yaml-2.8.10.jar.sha1
diff --git a/server/licenses/snakeyaml-1.17.jar.sha1 b/libs/x-content/licenses/snakeyaml-1.17.jar.sha1
similarity index 100%
rename from server/licenses/snakeyaml-1.17.jar.sha1
rename to libs/x-content/licenses/snakeyaml-1.17.jar.sha1
diff --git a/server/licenses/snakeyaml-LICENSE.txt b/libs/x-content/licenses/snakeyaml-LICENSE.txt
similarity index 100%
rename from server/licenses/snakeyaml-LICENSE.txt
rename to libs/x-content/licenses/snakeyaml-LICENSE.txt
diff --git a/server/licenses/snakeyaml-NOTICE.txt b/libs/x-content/licenses/snakeyaml-NOTICE.txt
similarity index 100%
rename from server/licenses/snakeyaml-NOTICE.txt
rename to libs/x-content/licenses/snakeyaml-NOTICE.txt
diff --git a/server/src/main/java/org/elasticsearch/common/ParseField.java b/libs/x-content/src/main/java/org/elasticsearch/common/ParseField.java
similarity index 98%
rename from server/src/main/java/org/elasticsearch/common/ParseField.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/ParseField.java
index 2c68ea7711bb2..084d82372c0ce 100644
--- a/server/src/main/java/org/elasticsearch/common/ParseField.java
+++ b/libs/x-content/src/main/java/org/elasticsearch/common/ParseField.java
@@ -35,6 +35,8 @@ public class ParseField {
private String allReplacedWith = null;
private final String[] allNames;
+ private static final String[] EMPTY = new String[0];
+
/**
* @param name
* the primary name for this field. This will be returned by
@@ -46,7 +48,7 @@ public class ParseField {
public ParseField(String name, String... deprecatedNames) {
this.name = name;
if (deprecatedNames == null || deprecatedNames.length == 0) {
- this.deprecatedNames = Strings.EMPTY_ARRAY;
+ this.deprecatedNames = EMPTY;
} else {
final HashSet set = new HashSet<>();
Collections.addAll(set, deprecatedNames);
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/ContextParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ContextParser.java
similarity index 100%
rename from server/src/main/java/org/elasticsearch/common/xcontent/ContextParser.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ContextParser.java
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java
similarity index 100%
rename from server/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/DeprecationHandler.java
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/NamedObjectNotFoundException.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/NamedObjectNotFoundException.java
similarity index 100%
rename from server/src/main/java/org/elasticsearch/common/xcontent/NamedObjectNotFoundException.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/NamedObjectNotFoundException.java
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/NamedXContentRegistry.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/NamedXContentRegistry.java
similarity index 100%
rename from server/src/main/java/org/elasticsearch/common/xcontent/NamedXContentRegistry.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/NamedXContentRegistry.java
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/ToXContent.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ToXContent.java
similarity index 98%
rename from server/src/main/java/org/elasticsearch/common/xcontent/ToXContent.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ToXContent.java
index f74bdec17a9f6..74542bb809f71 100644
--- a/server/src/main/java/org/elasticsearch/common/xcontent/ToXContent.java
+++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ToXContent.java
@@ -19,6 +19,8 @@
package org.elasticsearch.common.xcontent;
+import org.elasticsearch.common.Booleans;
+
import java.io.IOException;
import java.util.Map;
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/ToXContentFragment.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ToXContentFragment.java
similarity index 100%
rename from server/src/main/java/org/elasticsearch/common/xcontent/ToXContentFragment.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ToXContentFragment.java
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/ToXContentObject.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ToXContentObject.java
similarity index 100%
rename from server/src/main/java/org/elasticsearch/common/xcontent/ToXContentObject.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ToXContentObject.java
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/XContent.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContent.java
similarity index 99%
rename from server/src/main/java/org/elasticsearch/common/xcontent/XContent.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContent.java
index 6f6ee4ffdda54..1eaaac104f29d 100644
--- a/server/src/main/java/org/elasticsearch/common/xcontent/XContent.java
+++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContent.java
@@ -19,6 +19,8 @@
package org.elasticsearch.common.xcontent;
+import org.elasticsearch.common.Booleans;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
similarity index 95%
rename from server/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
rename to libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
index 86b56f29e69be..eae5e48a557f3 100644
--- a/server/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
+++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
@@ -19,8 +19,6 @@
package org.elasticsearch.common.xcontent;
-import org.elasticsearch.common.util.CollectionUtils;
-
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.Flushable;
@@ -35,6 +33,7 @@
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
@@ -740,7 +739,9 @@ private void unknownValue(Object value, boolean ensureNoSelfReferences) throws I
//Path implements Iterable and causes endless recursion and a StackOverFlow if treated as an Iterable here
value((Path) value);
} else if (value instanceof Map) {
- map((Map) value, ensureNoSelfReferences);
+ @SuppressWarnings("unchecked")
+ final Map valueMap = (Map) value;
+ map(valueMap, ensureNoSelfReferences);
} else if (value instanceof Iterable) {
value((Iterable>) value, ensureNoSelfReferences);
} else if (value instanceof Object[]) {
@@ -799,7 +800,7 @@ private XContentBuilder map(Map values, boolean ensureNoSelfReference
// checks that the map does not contain references to itself because
// iterating over map entries will cause a stackoverflow error
if (ensureNoSelfReferences) {
- CollectionUtils.ensureNoSelfReferences(values);
+ ensureNoSelfReferences(values);
}
startObject();
@@ -828,7 +829,7 @@ private XContentBuilder value(Iterable> values, boolean ensureNoSelfReferences
// checks that the iterable does not contain references to itself because
// iterating over entries will cause a stackoverflow error
if (ensureNoSelfReferences) {
- CollectionUtils.ensureNoSelfReferences(values);
+ ensureNoSelfReferences(values);
}
startArray();
for (Object value : values) {
@@ -937,4 +938,39 @@ static void ensureNotNull(Object value, String message) {
throw new IllegalArgumentException(message);
}
}
+
+ private static void ensureNoSelfReferences(Object value) {
+ Iterable> it = convert(value);
+ if (it != null) {
+ ensureNoSelfReferences(it, value, Collections.newSetFromMap(new IdentityHashMap<>()));
+ }
+ }
+
+ private static Iterable> convert(Object value) {
+ if (value == null) {
+ return null;
+ }
+ if (value instanceof Map) {
+ return ((Map,?>) value).values();
+ } else if ((value instanceof Iterable) && (value instanceof Path == false)) {
+ return (Iterable>) value;
+ } else if (value instanceof Object[]) {
+ return Arrays.asList((Object[]) value);
+ } else {
+ return null;
+ }
+ }
+
+ private static void ensureNoSelfReferences(final Iterable> value, Object originalReference, final Set