Skip to content

Commit 65c65c2

Browse files
zhangskzcopybara-github
authored andcommitted
Breaking Change: Use Editions features in Java full runtimes.
This change breaks compatibility with old generated code from previous major versions per the Cross Version Runtime policy: https://protobuf.dev/support/cross-version-runtime-guarantee. This includes old gencode from <4.26.x, which does not resolve features. See https://protobuf.dev/news/2023-12-05/ PiperOrigin-RevId: 600487923
1 parent 040dde7 commit 65c65c2

22 files changed

+1263
-152
lines changed

BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,12 @@ alias(
420420
visibility = ["//:__subpackages__"],
421421
)
422422

423+
alias(
424+
name = "test_proto_editions_srcs",
425+
actual = "//src/google/protobuf:test_proto_editions_srcs", # filegroup
426+
visibility = ["//:__subpackages__"],
427+
)
428+
423429
alias(
424430
name = "test_protos",
425431
actual = "//src/google/protobuf:test_protos", # proto_library

conformance/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ java_binary(
255255
"//:protobuf_java_util",
256256
"//:test_messages_proto2_java_proto",
257257
"//:test_messages_proto3_java_proto",
258+
"//src/google/protobuf/editions:test_messages_proto2_editions_java_proto",
259+
"//src/google/protobuf/editions:test_messages_proto3_editions_java_proto",
258260
],
259261
)
260262

conformance/ConformanceJava.java

Lines changed: 70 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import com.google.protobuf.conformance.Conformance;
1616
import com.google.protobuf.util.JsonFormat;
1717
import com.google.protobuf.util.JsonFormat.TypeRegistry;
18+
import com.google.protobuf_test_messages.editions.proto2.TestMessagesProto2Editions;
19+
import com.google.protobuf_test_messages.editions.proto3.TestMessagesProto3Editions;
1820
import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
1921
import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
2022
import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
@@ -205,42 +207,63 @@ private <T extends AbstractMessage> T parseBinary(
205207
return messages.get(0);
206208
}
207209

210+
private Class<? extends AbstractMessage> createTestMessage(String messageType) {
211+
switch (messageType) {
212+
case "protobuf_test_messages.proto3.TestAllTypesProto3":
213+
return TestAllTypesProto3.class;
214+
case "protobuf_test_messages.proto2.TestAllTypesProto2":
215+
return TestAllTypesProto2.class;
216+
case "protobuf_test_messages.editions.proto3.TestAllTypesProto3":
217+
return TestMessagesProto3Editions.TestAllTypesProto3.class;
218+
case "protobuf_test_messages.editions.proto2.TestAllTypesProto2":
219+
return TestMessagesProto2Editions.TestAllTypesProto2.class;
220+
default:
221+
throw new IllegalArgumentException(
222+
"Protobuf request has unexpected payload type: " + messageType);
223+
}
224+
}
225+
226+
private Class<?> createTestFile(String messageType) {
227+
switch (messageType) {
228+
case "protobuf_test_messages.proto3.TestAllTypesProto3":
229+
return TestMessagesProto3.class;
230+
case "protobuf_test_messages.proto2.TestAllTypesProto2":
231+
return TestMessagesProto2.class;
232+
case "protobuf_test_messages.editions.proto3.TestAllTypesProto3":
233+
return TestMessagesProto3Editions.class;
234+
case "protobuf_test_messages.editions.proto2.TestAllTypesProto2":
235+
return TestMessagesProto2Editions.class;
236+
default:
237+
throw new IllegalArgumentException(
238+
"Protobuf request has unexpected payload type: " + messageType);
239+
}
240+
}
241+
242+
@SuppressWarnings("unchecked")
208243
private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
209244
AbstractMessage testMessage;
210245
String messageType = request.getMessageType();
211-
boolean isProto3 = messageType.equals("protobuf_test_messages.proto3.TestAllTypesProto3");
212-
boolean isProto2 = messageType.equals("protobuf_test_messages.proto2.TestAllTypesProto2");
213246

214247
switch (request.getPayloadCase()) {
215248
case PROTOBUF_PAYLOAD:
216249
{
217-
if (isProto3) {
218-
try {
219-
ExtensionRegistry extensions = ExtensionRegistry.newInstance();
220-
TestMessagesProto3.registerAllExtensions(extensions);
221-
testMessage =
222-
parseBinary(
223-
request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
224-
} catch (InvalidProtocolBufferException e) {
225-
return Conformance.ConformanceResponse.newBuilder()
226-
.setParseError(e.getMessage())
227-
.build();
228-
}
229-
} else if (isProto2) {
230-
try {
231-
ExtensionRegistry extensions = ExtensionRegistry.newInstance();
232-
TestMessagesProto2.registerAllExtensions(extensions);
233-
testMessage =
234-
parseBinary(
235-
request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
236-
} catch (InvalidProtocolBufferException e) {
237-
return Conformance.ConformanceResponse.newBuilder()
238-
.setParseError(e.getMessage())
239-
.build();
240-
}
241-
} else {
242-
throw new IllegalArgumentException(
243-
"Protobuf request has unexpected payload type: " + messageType);
250+
try {
251+
ExtensionRegistry extensions = ExtensionRegistry.newInstance();
252+
createTestFile(messageType)
253+
.getMethod("registerAllExtensions", ExtensionRegistry.class)
254+
.invoke(null, extensions);
255+
testMessage =
256+
parseBinary(
257+
request.getProtobufPayload(),
258+
(Parser<AbstractMessage>)
259+
createTestMessage(messageType).getMethod("parser").invoke(null),
260+
extensions);
261+
} catch (InvalidProtocolBufferException e) {
262+
return Conformance.ConformanceResponse.newBuilder()
263+
.setParseError(e.getMessage())
264+
.build();
265+
} catch (Exception e) {
266+
throw new RuntimeException(e);
244267
}
245268
break;
246269
}
@@ -252,54 +275,34 @@ private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest re
252275
== Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) {
253276
parser = parser.ignoringUnknownFields();
254277
}
255-
if (isProto3) {
256-
TestMessagesProto3.TestAllTypesProto3.Builder builder =
257-
TestMessagesProto3.TestAllTypesProto3.newBuilder();
258-
parser.merge(request.getJsonPayload(), builder);
259-
testMessage = builder.build();
260-
} else if (isProto2) {
261-
TestMessagesProto2.TestAllTypesProto2.Builder builder =
262-
TestMessagesProto2.TestAllTypesProto2.newBuilder();
263-
parser.merge(request.getJsonPayload(), builder);
264-
testMessage = builder.build();
265-
} else {
266-
throw new IllegalArgumentException(
267-
"Protobuf request has unexpected payload type: " + messageType);
268-
}
278+
AbstractMessage.Builder<?> builder =
279+
(AbstractMessage.Builder<?>)
280+
createTestMessage(messageType).getMethod("newBuilder").invoke(null);
281+
parser.merge(request.getJsonPayload(), builder);
282+
testMessage = (AbstractMessage) builder.build();
269283
} catch (InvalidProtocolBufferException e) {
270284
return Conformance.ConformanceResponse.newBuilder()
271285
.setParseError(e.getMessage())
272286
.build();
287+
} catch (Exception e) {
288+
throw new RuntimeException(e);
273289
}
274290
break;
275291
}
276292
case TEXT_PAYLOAD:
277293
{
278-
if (isProto3) {
279-
try {
280-
TestMessagesProto3.TestAllTypesProto3.Builder builder =
281-
TestMessagesProto3.TestAllTypesProto3.newBuilder();
282-
TextFormat.merge(request.getTextPayload(), builder);
283-
testMessage = builder.build();
284-
} catch (TextFormat.ParseException e) {
285-
return Conformance.ConformanceResponse.newBuilder()
286-
.setParseError(e.getMessage())
287-
.build();
288-
}
289-
} else if (isProto2) {
290-
try {
291-
TestMessagesProto2.TestAllTypesProto2.Builder builder =
292-
TestMessagesProto2.TestAllTypesProto2.newBuilder();
293-
TextFormat.merge(request.getTextPayload(), builder);
294-
testMessage = builder.build();
294+
try {
295+
AbstractMessage.Builder<?> builder =
296+
(AbstractMessage.Builder<?>)
297+
createTestMessage(messageType).getMethod("newBuilder").invoke(null);
298+
TextFormat.merge(request.getTextPayload(), builder);
299+
testMessage = (AbstractMessage) builder.build();
295300
} catch (TextFormat.ParseException e) {
296301
return Conformance.ConformanceResponse.newBuilder()
297302
.setParseError(e.getMessage())
298303
.build();
299-
}
300-
} else {
301-
throw new IllegalArgumentException(
302-
"Protobuf request has unexpected payload type: " + messageType);
304+
} catch (Exception e) {
305+
throw new RuntimeException(e);
303306
}
304307
break;
305308
}
@@ -378,6 +381,9 @@ public void run() throws Exception {
378381
typeRegistry =
379382
TypeRegistry.newBuilder()
380383
.add(TestMessagesProto3.TestAllTypesProto3.getDescriptor())
384+
.add(
385+
com.google.protobuf_test_messages.editions.proto3.TestMessagesProto3Editions
386+
.TestAllTypesProto3.getDescriptor())
381387
.build();
382388
while (doTestIo()) {
383389
this.testCount++;

conformance/failure_list_java.txt

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,75 @@ Required.Proto2.JsonInput.Int32FieldNegativeWithLeadingZero
7474
Required.Proto2.JsonInput.Int32FieldPlusSign
7575
Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
7676
Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
77-
Required.Proto2.JsonInput.StringFieldNotAString
77+
Required.Proto2.JsonInput.StringFieldNotAString
78+
Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput
79+
Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput
80+
Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput
81+
Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalFalse
82+
Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalTrue
83+
Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseFalse
84+
Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseTrue
85+
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse
86+
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue
87+
Recommended.Editions_Proto3.JsonInput.BoolMapFieldKeyNotQuoted
88+
Recommended.Editions_Proto3.JsonInput.DoubleFieldInfinityNotQuoted
89+
Recommended.Editions_Proto3.JsonInput.DoubleFieldNanNotQuoted
90+
Recommended.Editions_Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
91+
Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter
92+
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate
93+
Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted
94+
Recommended.Editions_Proto3.JsonInput.FloatFieldInfinityNotQuoted
95+
Recommended.Editions_Proto3.JsonInput.FloatFieldNanNotQuoted
96+
Recommended.Editions_Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
97+
Recommended.Editions_Proto3.JsonInput.Int32MapFieldKeyNotQuoted
98+
Recommended.Editions_Proto3.JsonInput.Int64MapFieldKeyNotQuoted
99+
Recommended.Editions_Proto3.JsonInput.JsonWithComments
100+
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth
101+
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey
102+
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue
103+
Recommended.Editions_Proto3.JsonInput.StringFieldSurrogateInWrongOrder
104+
Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedHighSurrogate
105+
Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedLowSurrogate
106+
Recommended.Editions_Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
107+
Recommended.Editions_Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
108+
Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator
109+
Required.Editions_Proto3.JsonInput.EnumFieldNotQuoted
110+
Required.Editions_Proto3.JsonInput.Int32FieldLeadingZero
111+
Required.Editions_Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
112+
Required.Editions_Proto3.JsonInput.Int32FieldPlusSign
113+
Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
114+
Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
115+
Required.Editions_Proto3.JsonInput.StringFieldNotAString
116+
Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalFalse
117+
Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalTrue
118+
Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseFalse
119+
Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseTrue
120+
Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse
121+
Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue
122+
Recommended.Editions_Proto2.JsonInput.BoolMapFieldKeyNotQuoted
123+
Recommended.Editions_Proto2.JsonInput.DoubleFieldInfinityNotQuoted
124+
Recommended.Editions_Proto2.JsonInput.DoubleFieldNanNotQuoted
125+
Recommended.Editions_Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted
126+
Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate
127+
Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted
128+
Recommended.Editions_Proto2.JsonInput.FloatFieldInfinityNotQuoted
129+
Recommended.Editions_Proto2.JsonInput.FloatFieldNanNotQuoted
130+
Recommended.Editions_Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted
131+
Recommended.Editions_Proto2.JsonInput.Int32MapFieldKeyNotQuoted
132+
Recommended.Editions_Proto2.JsonInput.Int64MapFieldKeyNotQuoted
133+
Recommended.Editions_Proto2.JsonInput.JsonWithComments
134+
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth
135+
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey
136+
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue
137+
Recommended.Editions_Proto2.JsonInput.StringFieldSurrogateInWrongOrder
138+
Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedHighSurrogate
139+
Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedLowSurrogate
140+
Recommended.Editions_Proto2.JsonInput.Uint32MapFieldKeyNotQuoted
141+
Recommended.Editions_Proto2.JsonInput.Uint64MapFieldKeyNotQuoted
142+
Required.Editions_Proto2.JsonInput.EnumFieldNotQuoted
143+
Required.Editions_Proto2.JsonInput.Int32FieldLeadingZero
144+
Required.Editions_Proto2.JsonInput.Int32FieldNegativeWithLeadingZero
145+
Required.Editions_Proto2.JsonInput.Int32FieldPlusSign
146+
Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
147+
Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
148+
Required.Editions_Proto2.JsonInput.StringFieldNotAString

conformance/text_format_failure_list_java.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
44
Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
55
Required.Proto3.TextFormatInput.AnyField.ProtobufOutput
66
Required.Proto3.TextFormatInput.AnyField.TextFormatOutput
7+
Recommended.Editions_Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput
8+
Recommended.Editions_Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput
9+
Recommended.Editions_Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
10+
Recommended.Editions_Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
11+
Required.Editions_Proto3.TextFormatInput.AnyField.ProtobufOutput
12+
Required.Editions_Proto3.TextFormatInput.AnyField.TextFormatOutput
713

814
Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex
915
Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal
16+
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex
17+
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal

java/core/BUILD.bazel

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION")
77
load("//build_defs:java_opts.bzl", "protobuf_java_export", "protobuf_java_library", "protobuf_versioned_java_library")
88
load("//conformance:defs.bzl", "conformance_test")
99
load("//java/internal:testing.bzl", "junit_tests")
10+
load("//src/google/protobuf/editions:defaults.bzl", "compile_edition_defaults", "embed_edition_defaults")
1011

1112
LITE_SRCS = [
1213
# Keep in sync with `//java/lite:pom.xml`.
@@ -168,13 +169,21 @@ protobuf_java_library(
168169
proto_library(
169170
name = "java_features_proto",
170171
srcs = ["src/main/java/com/google/protobuf/java_features.proto"],
172+
strip_import_prefix = "/java/core/src/main/java/com",
171173
visibility = ["//pkg:__pkg__"],
172174
deps = ["//:descriptor_proto"],
173175
)
174176

177+
filegroup(
178+
name = "java_features_proto_srcs",
179+
srcs = ["src/main/java/com/google/protobuf/java_features.proto"],
180+
visibility = ["//pkg:__pkg__"],
181+
)
182+
175183
internal_gen_well_known_protos_java(
176184
name = "gen_well_known_protos_java",
177185
deps = [
186+
":java_features_proto",
178187
"//:any_proto",
179188
"//:api_proto",
180189
"//:compiler_plugin_proto",
@@ -240,6 +249,7 @@ protobuf_java_export(
240249
maven_coordinates = "com.google.protobuf:protobuf-java:%s" % PROTOBUF_JAVA_VERSION,
241250
pom_template = "pom_template.xml",
242251
resources = [
252+
":java_features_proto_srcs",
243253
"//:well_known_type_protos",
244254
"//src/google/protobuf:descriptor_proto_srcs",
245255
],
@@ -266,6 +276,7 @@ proto_lang_toolchain(
266276
name = "toolchain",
267277
# keep this in sync w/ WELL_KNOWN_PROTO_MAP in //:BUILD
268278
blacklisted_protos = [
279+
":java_features_proto",
269280
"//:any_proto",
270281
"//:api_proto",
271282
"//:compiler_plugin_proto",
@@ -305,6 +316,14 @@ java_proto_library(
305316
deps = ["//src/google/protobuf:generic_test_protos"],
306317
)
307318

319+
java_proto_library(
320+
name = "generic_test_protos_editions_java_proto",
321+
visibility = [
322+
"//java:__subpackages__",
323+
],
324+
deps = ["//src/google/protobuf:generic_test_editions_protos"],
325+
)
326+
308327
java_proto_library(
309328
name = "lite_test_protos_java_proto",
310329
visibility = [
@@ -355,6 +374,7 @@ build_test(
355374
conformance_test(
356375
name = "conformance_test",
357376
failure_list = "//conformance:failure_list_java.txt",
377+
maximum_edition = "2023",
358378
testee = "//conformance:conformance_java",
359379
text_format_failure_list = "//conformance:text_format_failure_list_java.txt",
360380
)
@@ -374,6 +394,7 @@ junit_tests(
374394
data = ["//src/google/protobuf:testdata"],
375395
deps = [
376396
":core",
397+
":generic_test_protos_editions_java_proto",
377398
":generic_test_protos_java_proto",
378399
":java_test_protos_java_proto",
379400
":lite_test_protos_java_proto",
@@ -531,6 +552,7 @@ pkg_files(
531552
name = "dist_files",
532553
srcs = glob([
533554
"src/main/java/com/google/protobuf/*.java",
555+
"src/main/java/com/google/protobuf/*.proto",
534556
"src/test/java/**/*.java",
535557
"src/test/proto/**/*.proto",
536558
]) + [

java/core/generate-sources-build.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<exec executable="${protoc}">
55
<arg value="--java_out=${generated.sources.dir}"/>
66
<arg value="--proto_path=${protobuf.source.dir}"/>
7+
<arg value="--proto_path=${protobuf.java_source.dir}"/>
8+
<arg value="${protobuf.java_source.dir}/main/java/com/google/protobuf/java_features.proto"/>
79
<arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
810
<arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
911
<arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>

0 commit comments

Comments
 (0)