Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit b62ad64

Browse files
Bogdan Drutusongy23
authored andcommitted
Avoid doing string formatting when calling checkArgument. (#1394)
(cherry picked from commit eabc800)
1 parent 6d98748 commit b62ad64

File tree

11 files changed

+447
-30
lines changed

11 files changed

+447
-30
lines changed

api/src/main/java/io/opencensus/internal/Utils.java

Lines changed: 106 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package io.opencensus.internal;
1818

19-
import javax.annotation.Nullable;
19+
import java.util.List;
2020

2121
/*>>>
2222
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -32,11 +32,38 @@ private Utils() {}
3232
* {@code Preconditions.checkArgument(boolean, Object)} from Guava.
3333
*
3434
* @param isValid whether the argument check passed.
35-
* @param message the message to use for the exception.
35+
* @param errorMessage the message to use for the exception. Will be converted to a string using
36+
* {@link String#valueOf(Object)}.
3637
*/
37-
public static void checkArgument(boolean isValid, String message) {
38+
public static void checkArgument(
39+
boolean isValid, @javax.annotation.Nullable Object errorMessage) {
3840
if (!isValid) {
39-
throw new IllegalArgumentException(message);
41+
throw new IllegalArgumentException(String.valueOf(errorMessage));
42+
}
43+
}
44+
45+
/**
46+
* Throws an {@link IllegalArgumentException} if the argument is false. This method is similar to
47+
* {@code Preconditions.checkArgument(boolean, Object)} from Guava.
48+
*
49+
* @param expression a boolean expression
50+
* @param errorMessageTemplate a template for the exception message should the check fail. The
51+
* message is formed by replacing each {@code %s} placeholder in the template with an
52+
* argument. These are matched by position - the first {@code %s} gets {@code
53+
* errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message in
54+
* square braces. Unmatched placeholders will be left as-is.
55+
* @param errorMessageArgs the arguments to be substituted into the message template. Arguments
56+
* are converted to strings using {@link String#valueOf(Object)}.
57+
* @throws IllegalArgumentException if {@code expression} is false
58+
* @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
59+
* {@code errorMessageArgs} is null (don't let this happen)
60+
*/
61+
public static void checkArgument(
62+
boolean expression,
63+
String errorMessageTemplate,
64+
@javax.annotation.Nullable Object... errorMessageArgs) {
65+
if (!expression) {
66+
throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
4067
}
4168
}
4269

@@ -45,11 +72,12 @@ public static void checkArgument(boolean isValid, String message) {
4572
* {@code Preconditions.checkState(boolean, Object)} from Guava.
4673
*
4774
* @param isValid whether the state check passed.
48-
* @param message the message to use for the exception.
75+
* @param errorMessage the message to use for the exception. Will be converted to a string using
76+
* {@link String#valueOf(Object)}.
4977
*/
50-
public static void checkState(boolean isValid, String message) {
78+
public static void checkState(boolean isValid, @javax.annotation.Nullable Object errorMessage) {
5179
if (!isValid) {
52-
throw new IllegalStateException(message);
80+
throw new IllegalStateException(String.valueOf(errorMessage));
5381
}
5482
}
5583

@@ -76,21 +104,88 @@ public static void checkIndex(int index, int size) {
76104
* Preconditions.checkNotNull(Object, Object)} from Guava.
77105
*
78106
* @param arg the argument to check for null.
79-
* @param message the message to use for the exception.
107+
* @param errorMessage the message to use for the exception. Will be converted to a string using
108+
* {@link String#valueOf(Object)}.
80109
* @return the argument, if it passes the null check.
81110
*/
82-
public static <T /*>>> extends @NonNull Object*/> T checkNotNull(T arg, String message) {
111+
public static <T /*>>> extends @NonNull Object*/> T checkNotNull(
112+
T arg, @javax.annotation.Nullable Object errorMessage) {
83113
if (arg == null) {
84-
throw new NullPointerException(message);
114+
throw new NullPointerException(String.valueOf(errorMessage));
85115
}
86116
return arg;
87117
}
88118

119+
/**
120+
* Throws a {@link NullPointerException} if any of the list elements is null.
121+
*
122+
* @param list the argument list to check for null.
123+
* @param errorMessage the message to use for the exception. Will be converted to a string using
124+
* {@link String#valueOf(Object)}.
125+
*/
126+
public static <T /*>>> extends @NonNull Object*/> void checkListElementNotNull(
127+
List<T> list, @javax.annotation.Nullable Object errorMessage) {
128+
for (T element : list) {
129+
if (element == null) {
130+
throw new NullPointerException(String.valueOf(errorMessage));
131+
}
132+
}
133+
}
134+
89135
/**
90136
* Compares two Objects for equality. This functionality is provided by {@code
91137
* Objects.equal(Object, Object)} in Java 7.
92138
*/
93-
public static boolean equalsObjects(@Nullable Object x, @Nullable Object y) {
139+
public static boolean equalsObjects(
140+
@javax.annotation.Nullable Object x, @javax.annotation.Nullable Object y) {
94141
return x == null ? y == null : x.equals(y);
95142
}
143+
144+
/**
145+
* Substitutes each {@code %s} in {@code template} with an argument. These are matched by
146+
* position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than
147+
* placeholders, the unmatched arguments will be appended to the end of the formatted message in
148+
* square braces.
149+
*
150+
* <p>Copied from {@code Preconditions.format(String, Object...)} from Guava
151+
*
152+
* @param template a non-null string containing 0 or more {@code %s} placeholders.
153+
* @param args the arguments to be substituted into the message template. Arguments are converted
154+
* to strings using {@link String#valueOf(Object)}. Arguments can be null.
155+
*/
156+
// Note that this is somewhat-improperly used from Verify.java as well.
157+
private static String format(String template, @javax.annotation.Nullable Object... args) {
158+
// If no arguments return the template.
159+
if (args == null) {
160+
return template;
161+
}
162+
163+
// start substituting the arguments into the '%s' placeholders
164+
StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
165+
int templateStart = 0;
166+
int i = 0;
167+
while (i < args.length) {
168+
int placeholderStart = template.indexOf("%s", templateStart);
169+
if (placeholderStart == -1) {
170+
break;
171+
}
172+
builder.append(template, templateStart, placeholderStart);
173+
builder.append(args[i++]);
174+
templateStart = placeholderStart + 2;
175+
}
176+
builder.append(template, templateStart, template.length());
177+
178+
// if we run out of placeholders, append the extra args in square braces
179+
if (i < args.length) {
180+
builder.append(" [");
181+
builder.append(args[i++]);
182+
while (i < args.length) {
183+
builder.append(", ");
184+
builder.append(args[i++]);
185+
}
186+
builder.append(']');
187+
}
188+
189+
return builder.toString();
190+
}
96191
}

api/src/main/java/io/opencensus/stats/Measure.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@
3030
*/
3131
@Immutable
3232
public abstract class Measure {
33-
3433
@DefaultVisibilityForTesting static final int NAME_MAX_LENGTH = 255;
34+
private static final String ERROR_MESSAGE_INVALID_NAME =
35+
"Name should be a ASCII string with a length no greater than "
36+
+ NAME_MAX_LENGTH
37+
+ " characters.";
3538

3639
/**
3740
* Applies the given match function to the underlying data type.
@@ -105,9 +108,7 @@ public abstract static class MeasureDouble extends Measure {
105108
public static MeasureDouble create(String name, String description, String unit) {
106109
Utils.checkArgument(
107110
StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH,
108-
"Name should be a ASCII string with a length no greater than "
109-
+ NAME_MAX_LENGTH
110-
+ " characters.");
111+
ERROR_MESSAGE_INVALID_NAME);
111112
return new AutoValue_Measure_MeasureDouble(name, description, unit);
112113
}
113114

@@ -152,9 +153,7 @@ public abstract static class MeasureLong extends Measure {
152153
public static MeasureLong create(String name, String description, String unit) {
153154
Utils.checkArgument(
154155
StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH,
155-
"Name should be a ASCII string with a length no greater than "
156-
+ NAME_MAX_LENGTH
157-
+ " characters.");
156+
ERROR_MESSAGE_INVALID_NAME);
158157
return new AutoValue_Measure_MeasureLong(name, description, unit);
159158
}
160159

api/src/main/java/io/opencensus/tags/TagKey.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public abstract class TagKey {
6060
* @since 0.8
6161
*/
6262
public static TagKey create(String name) {
63-
Utils.checkArgument(isValid(name), "Invalid TagKey name: " + name);
63+
Utils.checkArgument(isValid(name), "Invalid TagKey name: %s", name);
6464
return new AutoValue_TagKey(name);
6565
}
6666

api/src/main/java/io/opencensus/tags/TagValue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public abstract class TagValue {
5555
* @since 0.8
5656
*/
5757
public static TagValue create(String value) {
58-
Utils.checkArgument(isValid(value), "Invalid TagValue: " + value);
58+
Utils.checkArgument(isValid(value), "Invalid TagValue: %s", value);
5959
return new AutoValue_TagValue(value);
6060
}
6161

api/src/main/java/io/opencensus/trace/SpanId.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public final class SpanId implements Comparable<SpanId> {
3838
*/
3939
public static final int SIZE = 8;
4040

41+
private static final int HEX_SIZE = 2 * SIZE;
42+
4143
/**
4244
* The invalid {@code SpanId}. All bytes are 0.
4345
*
@@ -70,8 +72,7 @@ private SpanId(byte[] bytes) {
7072
public static SpanId fromBytes(byte[] buffer) {
7173
Utils.checkNotNull(buffer, "buffer");
7274
Utils.checkArgument(
73-
buffer.length == SIZE,
74-
String.format("Invalid size: expected %s, got %s", SIZE, buffer.length));
75+
buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length);
7576
byte[] bytesCopied = Arrays.copyOf(buffer, SIZE);
7677
return new SpanId(bytesCopied);
7778
}
@@ -107,8 +108,7 @@ public static SpanId fromBytes(byte[] src, int srcOffset) {
107108
*/
108109
public static SpanId fromLowerBase16(CharSequence src) {
109110
Utils.checkArgument(
110-
src.length() == 2 * SIZE,
111-
String.format("Invalid size: expected %s, got %s", 2 * SIZE, src.length()));
111+
src.length() == HEX_SIZE, "Invalid size: expected %s, got %s", HEX_SIZE, src.length());
112112
byte[] bytes = BaseEncoding.base16().lowerCase().decode(src);
113113
return new SpanId(bytes);
114114
}

api/src/main/java/io/opencensus/trace/TraceId.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public final class TraceId implements Comparable<TraceId> {
3939
*/
4040
public static final int SIZE = 16;
4141

42+
private static final int HEX_SIZE = 32;
43+
4244
/**
4345
* The invalid {@code TraceId}. All bytes are '\0'.
4446
*
@@ -71,8 +73,7 @@ private TraceId(byte[] bytes) {
7173
public static TraceId fromBytes(byte[] buffer) {
7274
Utils.checkNotNull(buffer, "buffer");
7375
Utils.checkArgument(
74-
buffer.length == SIZE,
75-
String.format("Invalid size: expected %s, got %s", SIZE, buffer.length));
76+
buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length);
7677
byte[] bytesCopied = Arrays.copyOf(buffer, SIZE);
7778
return new TraceId(bytesCopied);
7879
}
@@ -108,8 +109,7 @@ public static TraceId fromBytes(byte[] src, int srcOffset) {
108109
*/
109110
public static TraceId fromLowerBase16(CharSequence src) {
110111
Utils.checkArgument(
111-
src.length() == 2 * SIZE,
112-
String.format("Invalid size: expected %s, got %s", 2 * SIZE, src.length()));
112+
src.length() == HEX_SIZE, "Invalid size: expected %s, got %s", HEX_SIZE, src.length());
113113
byte[] bytes = BaseEncoding.base16().lowerCase().decode(src);
114114
return new TraceId(bytes);
115115
}

api/src/main/java/io/opencensus/trace/TraceOptions.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ private TraceOptions(byte options) {
7676
public static TraceOptions fromBytes(byte[] buffer) {
7777
Utils.checkNotNull(buffer, "buffer");
7878
Utils.checkArgument(
79-
buffer.length == SIZE,
80-
String.format("Invalid size: expected %s, got %s", SIZE, buffer.length));
79+
buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length);
8180
return new TraceOptions(buffer[0]);
8281
}
8382

0 commit comments

Comments
 (0)