From c281826702536a5247391c4190de14603860a5a4 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Tue, 15 Sep 2015 18:26:41 -0400 Subject: [PATCH] Remove and forbid use of com.google.common.primitives.Ints This commit removes and now forbids all uses of com.google.common.primitives.Ints across the codebase. This is one of many steps in the eventual removal of Guava as a dependency. Relates #13224 --- .../common/util/BloomFilter.java | 4 +- .../common/util/MultiDataPathUpgrader.java | 20 ++--- .../common/util/primitives/Integers.java | 90 +++++++++++++++++++ .../elasticsearch/env/NodeEnvironment.java | 28 ++---- .../common/util/primitives/IntegerTests.java | 53 +++++++++++ .../ClusterDiscoveryConfiguration.java | 4 +- .../resources/forbidden/all-signatures.txt | 1 + 7 files changed, 158 insertions(+), 42 deletions(-) create mode 100644 core/src/main/java/org/elasticsearch/common/util/primitives/Integers.java create mode 100644 core/src/test/java/org/elasticsearch/common/util/primitives/IntegerTests.java diff --git a/core/src/main/java/org/elasticsearch/common/util/BloomFilter.java b/core/src/main/java/org/elasticsearch/common/util/BloomFilter.java index 0f72d6d62b1..561fff5ab7e 100644 --- a/core/src/main/java/org/elasticsearch/common/util/BloomFilter.java +++ b/core/src/main/java/org/elasticsearch/common/util/BloomFilter.java @@ -18,7 +18,6 @@ */ package org.elasticsearch.common.util; -import com.google.common.primitives.Ints; import org.apache.lucene.store.DataInput; import org.apache.lucene.store.DataOutput; import org.apache.lucene.store.IndexInput; @@ -30,6 +29,7 @@ import org.elasticsearch.common.hash.MurmurHash3; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.unit.SizeValue; +import org.elasticsearch.common.util.primitives.Integers; import java.io.IOException; import java.util.Arrays; @@ -325,7 +325,7 @@ public class BloomFilter { private static int size(long bits) { long quotient = bits / 64; long remainder = bits - quotient * 64; - return Ints.checkedCast(remainder == 0 ? quotient : 1 + quotient); + return Integers.checkedCast(remainder == 0 ? quotient : 1 + quotient); } // Used by serialization diff --git a/core/src/main/java/org/elasticsearch/common/util/MultiDataPathUpgrader.java b/core/src/main/java/org/elasticsearch/common/util/MultiDataPathUpgrader.java index 761a1ee5cd0..50b1e56e074 100644 --- a/core/src/main/java/org/elasticsearch/common/util/MultiDataPathUpgrader.java +++ b/core/src/main/java/org/elasticsearch/common/util/MultiDataPathUpgrader.java @@ -18,8 +18,6 @@ */ package org.elasticsearch.common.util; -import java.nio.charset.StandardCharsets; -import com.google.common.primitives.Ints; import org.apache.lucene.index.CheckIndex; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.store.Directory; @@ -33,6 +31,7 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.unit.ByteSizeValue; +import org.elasticsearch.common.util.primitives.Integers; import org.elasticsearch.env.NodeEnvironment; import org.elasticsearch.env.ShardLock; import org.elasticsearch.gateway.MetaDataStateFormat; @@ -43,19 +42,10 @@ import org.elasticsearch.index.shard.ShardStateMetaData; import java.io.IOException; import java.io.PrintStream; -import java.nio.file.DirectoryStream; -import java.nio.file.FileStore; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** */ @@ -370,7 +360,7 @@ public class MultiDataPathUpgrader { String currentIndex = indexPath.getFileName().toString(); for (Path shardPath : stream) { if (Files.isDirectory(shardPath)) { - Integer shardId = Ints.tryParse(shardPath.getFileName().toString()); + Integer shardId = Integers.tryParse(shardPath.getFileName().toString()); if (shardId != null) { ShardId id = new ShardId(currentIndex, shardId); shardIds.add(id); diff --git a/core/src/main/java/org/elasticsearch/common/util/primitives/Integers.java b/core/src/main/java/org/elasticsearch/common/util/primitives/Integers.java new file mode 100644 index 00000000000..db315f23cf5 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/common/util/primitives/Integers.java @@ -0,0 +1,90 @@ +/* + * 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.util.primitives; + +import org.elasticsearch.common.Strings; + +import java.util.*; + +public class Integers { + /** + * Tries to parse the given String to an int + * + * @param value the String to try to parse to an int + * @return the parsed value as an int or null if the String can not be parsed to an int + */ + public static Integer tryParse(String value) { + if (Strings.isNullOrEmpty(value)) { + return null; + } else { + boolean negative = value.charAt(0) == '-'; + int index = negative ? 1 : 0; + if (index == value.length()) { + return null; + } else { + int digit = digit(value.charAt(index++)); + if (digit != -1) { + // so we can accumulate to Integer.MIN_VALUE + int accumulator = -digit; + for (int cap = Integer.MIN_VALUE / 10; index < value.length(); accumulator -= digit) { + digit = digit(value.charAt(index++)); + if (digit == -1 || accumulator < cap) { + // non-digit or will overflow + return null; + } + accumulator *= 10; + if (accumulator < Integer.MIN_VALUE + digit) { + // will overflow + return null; + } + } + if (negative) { + return Integer.valueOf(accumulator); + } else if (accumulator == Integer.MIN_VALUE) { + // overflow + return null; + } else { + return Integer.valueOf(-accumulator); + } + } else { + // non-digit encountered + return null; + } + } + } + } + + private static int digit(char c) { + return c >= '0' && c <= '9' ? c - '0' : -1; + } + + public static int[] toArray(Collection ints) { + Objects.requireNonNull(ints); + return ints.stream().mapToInt(s -> s).toArray(); + } + + public static int checkedCast(long value) { + int cast = (int)value; + if ((long)cast != value) { + throw new IllegalArgumentException(Long.toString(value)); + } + return cast; + } +} diff --git a/core/src/main/java/org/elasticsearch/env/NodeEnvironment.java b/core/src/main/java/org/elasticsearch/env/NodeEnvironment.java index 06562f82db5..b17052c996b 100644 --- a/core/src/main/java/org/elasticsearch/env/NodeEnvironment.java +++ b/core/src/main/java/org/elasticsearch/env/NodeEnvironment.java @@ -20,15 +20,9 @@ package org.elasticsearch.env; import com.google.common.collect.ImmutableSet; -import com.google.common.primitives.Ints; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.SegmentInfos; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.FSDirectory; -import org.apache.lucene.store.Lock; -import org.apache.lucene.store.LockObtainFailedException; -import org.apache.lucene.store.NativeFSLockFactory; -import org.apache.lucene.store.SimpleFSDirectory; +import org.apache.lucene.store.*; import org.apache.lucene.util.IOUtils; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.cluster.metadata.IndexMetaData; @@ -39,6 +33,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.FileSystemUtils; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.primitives.Integers; import org.elasticsearch.index.Index; import org.elasticsearch.index.settings.IndexSettings; import org.elasticsearch.index.shard.ShardId; @@ -48,21 +43,8 @@ import org.elasticsearch.monitor.fs.FsProbe; import java.io.Closeable; import java.io.IOException; -import java.nio.file.AtomicMoveNotSupportedException; -import java.nio.file.DirectoryStream; -import java.nio.file.FileStore; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.nio.file.*; +import java.util.*; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -712,7 +694,7 @@ public class NodeEnvironment extends AbstractComponent implements Closeable { String currentIndex = indexPath.getFileName().toString(); for (Path shardPath : stream) { if (Files.isDirectory(shardPath)) { - Integer shardId = Ints.tryParse(shardPath.getFileName().toString()); + Integer shardId = Integers.tryParse(shardPath.getFileName().toString()); if (shardId != null) { ShardId id = new ShardId(currentIndex, shardId); shardIds.add(id); diff --git a/core/src/test/java/org/elasticsearch/common/util/primitives/IntegerTests.java b/core/src/test/java/org/elasticsearch/common/util/primitives/IntegerTests.java new file mode 100644 index 00000000000..9a7f18ac7ab --- /dev/null +++ b/core/src/test/java/org/elasticsearch/common/util/primitives/IntegerTests.java @@ -0,0 +1,53 @@ +/* + * 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.util.primitives; + +import org.elasticsearch.test.ESTestCase; + +public class IntegerTests extends ESTestCase { + public void testTryParse() { + assertTryParse(0, "0"); + assertTryParse(0, "-0"); + assertTryParse(1, "1"); + assertTryParse(-1, "-1"); + assertTryParse(12345, "12345"); + assertTryParse(-12345, "-12345"); + for (int i = 0; i < 1 << 20; i++) { + int value = randomInt(); + assertTryParse(value, Integer.toString(value)); + } + assertTryParse(Integer.MAX_VALUE, Integer.toString(Integer.MAX_VALUE)); + assertTryParse(Integer.MIN_VALUE, Integer.toString(Integer.MIN_VALUE)); + assertNull(Integers.tryParse(null)); + assertNull(Integers.tryParse("")); + assertNull(Integers.tryParse("-")); + assertNull(Integers.tryParse("9999999999999999")); + assertNull(Integers.tryParse(Long.toString(((long) Integer.MAX_VALUE) + 1))); + assertNull(Integers.tryParse(Long.toString(((long) Integer.MAX_VALUE) * 10))); + assertNull(Integers.tryParse(Long.toString(((long) Integer.MIN_VALUE) - 1))); + assertNull(Integers.tryParse(Long.toString(((long) Integer.MIN_VALUE) * 10))); + assertNull(Integers.tryParse(Long.toString(Long.MAX_VALUE))); + assertNull(Integers.tryParse(Long.toString(Long.MIN_VALUE))); + } + + private static void assertTryParse(Integer expected, String value) { + assertEquals(expected, Integers.tryParse(value)); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/elasticsearch/test/discovery/ClusterDiscoveryConfiguration.java b/core/src/test/java/org/elasticsearch/test/discovery/ClusterDiscoveryConfiguration.java index bcd9384a88b..ad46047855b 100644 --- a/core/src/test/java/org/elasticsearch/test/discovery/ClusterDiscoveryConfiguration.java +++ b/core/src/test/java/org/elasticsearch/test/discovery/ClusterDiscoveryConfiguration.java @@ -19,11 +19,11 @@ package org.elasticsearch.test.discovery; import com.carrotsearch.randomizedtesting.RandomizedTest; -import com.google.common.primitives.Ints; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.network.NetworkUtils; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.primitives.Integers; import org.elasticsearch.test.InternalTestCluster; import org.elasticsearch.test.NodeConfigurationSource; @@ -82,7 +82,7 @@ public class ClusterDiscoveryConfiguration extends NodeConfigurationSource { while (ordinals.size() != numOfUnicastHosts) { ordinals.add(RandomizedTest.randomInt(numOfNodes - 1)); } - unicastHostOrdinals = Ints.toArray(ordinals); + unicastHostOrdinals = Integers.toArray(ordinals); } this.unicastHostPorts = unicastHostPorts(numOfNodes); assert unicastHostOrdinals.length <= unicastHostPorts.length; diff --git a/dev-tools/src/main/resources/forbidden/all-signatures.txt b/dev-tools/src/main/resources/forbidden/all-signatures.txt index 613ed07112d..8b976b55baa 100644 --- a/dev-tools/src/main/resources/forbidden/all-signatures.txt +++ b/dev-tools/src/main/resources/forbidden/all-signatures.txt @@ -125,6 +125,7 @@ com.google.common.collect.ArrayListMultimap com.google.common.collect.HashMultimap com.google.common.collect.FluentIterable com.google.common.io.Files +com.google.common.primitives.Ints @defaultMessage Do not violate java's access system java.lang.reflect.AccessibleObject#setAccessible(boolean)