Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit a61c4b5

Browse files
committed
testproxy: Remove manual dependency resolution from ResultSetSerializer
We now require the clients to provide FileDescriptorSet with files in dependency order Change-Id: I240cfe8f4d499ba7053dfab1f119972de1810fce
1 parent e329165 commit a61c4b5

1 file changed

Lines changed: 28 additions & 59 deletions

File tree

test-proxy/src/main/java/com/google/cloud/bigtable/testproxy/ResultSetSerializer.java

Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class ResultSetSerializer {
5555

5656
// This is a helper enum to satisfy the type constraints of {@link StructReader#getProtoEnum}.
5757
private static class DummyEnum implements ProtocolMessageEnum {
58+
5859
private final int value;
5960
private final EnumDescriptor descriptor;
6061

@@ -110,76 +111,44 @@ private void populateDescriptorMapsRecursively(Descriptor descriptor) {
110111
* useful for handling PROTO or ENUM types that require schema lookup.
111112
*
112113
* @param descriptorSet A set containing one or more .proto file definitions and all their
113-
* non-standard dependencies.
114+
* non-standard dependencies. All .proto file must be provided in dependency order.
114115
* @throws IllegalArgumentException if the descriptorSet contains unresolvable dependencies.
115116
*/
116117
public ResultSetSerializer(FileDescriptorSet descriptorSet) throws IllegalArgumentException {
117118
this.messageDescriptorMap = new HashMap<>();
118119
this.enumDescriptorMap = new HashMap<>();
119-
120-
// Java's dynamic descriptor loading requires manual dependency resolution.
121-
// We must build a DAG and build files only after their dependencies are built.
122-
java.util.Map<String, FileDescriptorProto> pendingProtos = new HashMap<>();
123120
java.util.Map<String, FileDescriptor> builtDescriptors = new HashMap<>();
124-
for (FileDescriptorProto fileDescriptorProto : descriptorSet.getFileList()) {
125-
pendingProtos.put(fileDescriptorProto.getName(), fileDescriptorProto);
126-
}
127-
128-
// Keep looping as long as we are making progress.
129-
int filesBuiltThisPass;
130-
do {
131-
filesBuiltThisPass = 0;
132-
// Use a copy of the values, to avoid modifying the pendingProtos map while iterating it.
133-
List<FileDescriptorProto> protosToBuild = new ArrayList<>(pendingProtos.values());
134-
135-
for (FileDescriptorProto proto : protosToBuild) {
136-
boolean allDependenciesMet = true;
137-
List<FileDescriptor> dependencies = new ArrayList<>();
138121

139-
for (String dependencyName : proto.getDependencyList()) {
140-
FileDescriptor dependency = builtDescriptors.get(dependencyName);
141-
if (dependency != null) {
142-
// Dependency is already built, add it.
143-
dependencies.add(dependency);
144-
} else if (pendingProtos.containsKey(dependencyName)) {
145-
// Dependency is not yet built, we must wait.
146-
allDependenciesMet = false;
147-
break;
148-
} else {
149-
// Dependency is not in our set. We assume it's a well-known type (e.g.,
150-
// google/protobuf/timestamp.proto) that buildFrom() can find and link automatically.
151-
}
122+
for (FileDescriptorProto fileDescriptorProto : descriptorSet.getFileList()) {
123+
// Collect dependencies. This code require files inside the descriptor set to be sorted
124+
// according to the dependency order.
125+
List<FileDescriptor> dependencies = new ArrayList<>();
126+
for (String dependencyName : fileDescriptorProto.getDependencyList()) {
127+
FileDescriptor dependency = builtDescriptors.get(dependencyName);
128+
if (dependency != null) {
129+
// Dependency is already built, add it.
130+
dependencies.add(dependency);
152131
}
132+
// Dependency is not in our set. We assume it's a well-known type (e.g.,
133+
// google/protobuf/timestamp.proto) that buildFrom() can find and link automatically.
134+
}
153135

154-
if (allDependenciesMet) {
155-
try {
156-
// All dependencies are met, we can build this file.
157-
FileDescriptor fileDescriptor =
158-
FileDescriptor.buildFrom(proto, dependencies.toArray(new FileDescriptor[0]));
159-
160-
builtDescriptors.put(fileDescriptor.getName(), fileDescriptor);
161-
pendingProtos.remove(proto.getName());
162-
filesBuiltThisPass++;
163-
164-
// Now, populate both message and enum maps with all messages/enums in this file.
165-
for (EnumDescriptor enumDescriptor : fileDescriptor.getEnumTypes()) {
166-
enumDescriptorMap.put(enumDescriptor.getFullName(), enumDescriptor);
167-
}
168-
for (Descriptor messageDescriptor : fileDescriptor.getMessageTypes()) {
169-
populateDescriptorMapsRecursively(messageDescriptor);
170-
}
171-
} catch (DescriptorValidationException e) {
172-
throw new IllegalArgumentException(
173-
"Failed to build descriptor for " + proto.getName(), e);
174-
}
136+
try {
137+
FileDescriptor fileDescriptor =
138+
FileDescriptor.buildFrom(
139+
fileDescriptorProto, dependencies.toArray(new FileDescriptor[0]));
140+
builtDescriptors.put(fileDescriptor.getName(), fileDescriptor);
141+
// Now, populate both message and enum maps with all messages/enums in this file.
142+
for (EnumDescriptor enumDescriptor : fileDescriptor.getEnumTypes()) {
143+
enumDescriptorMap.put(enumDescriptor.getFullName(), enumDescriptor);
144+
}
145+
for (Descriptor messageDescriptor : fileDescriptor.getMessageTypes()) {
146+
populateDescriptorMapsRecursively(messageDescriptor);
175147
}
148+
} catch (DescriptorValidationException e) {
149+
throw new IllegalArgumentException(
150+
"Failed to build descriptor for " + fileDescriptorProto.getName(), e);
176151
}
177-
} while (filesBuiltThisPass > 0);
178-
179-
// Throw if we finished looping but still have pending protos.
180-
if (!pendingProtos.isEmpty()) {
181-
throw new IllegalArgumentException(
182-
"Unresolvable or circular dependencies found for: " + pendingProtos.keySet());
183152
}
184153
}
185154

0 commit comments

Comments
 (0)