下面列出了com.google.protobuf.Descriptors.DescriptorValidationException#com.google.protobuf.DescriptorProtos.FileDescriptorProto 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Creates a resolver which searches the supplied {@link FileDescriptorSet}.
*/
public static ServiceResolver fromFileDescriptorSet(FileDescriptorSet descriptorSet) {
ImmutableMap<String, FileDescriptorProto> descriptorProtoIndex =
computeDescriptorProtoIndex(descriptorSet);
Map<String, FileDescriptor> descriptorCache = new HashMap<>();
ImmutableList.Builder<FileDescriptor> result = ImmutableList.builder();
for (FileDescriptorProto descriptorProto : descriptorSet.getFileList()) {
try {
result.add(descriptorFromProto(descriptorProto, descriptorProtoIndex, descriptorCache));
} catch (DescriptorValidationException e) {
logger.warn("Skipped descriptor " + descriptorProto.getName() + " due to error", e);
}
}
return new ServiceResolver(result.build());
}
/**
* Recursively constructs file descriptors for all dependencies of the supplied proto and returns
* a {@link FileDescriptor} for the supplied proto itself. For maximal efficiency, reuse the
* descriptorCache argument across calls.
*/
private static FileDescriptor descriptorFromProto(
FileDescriptorProto descriptorProto,
ImmutableMap<String, FileDescriptorProto> descriptorProtoIndex,
Map<String, FileDescriptor> descriptorCache) throws DescriptorValidationException {
// First, check the cache.
String descriptorName = descriptorProto.getName();
if (descriptorCache.containsKey(descriptorName)) {
return descriptorCache.get(descriptorName);
}
// Then, fetch all the required dependencies recursively.
ImmutableList.Builder<FileDescriptor> dependencies = ImmutableList.builder();
for (String dependencyName : descriptorProto.getDependencyList()) {
if (!descriptorProtoIndex.containsKey(dependencyName)) {
throw new IllegalArgumentException("Could not find dependency: " + dependencyName);
}
FileDescriptorProto dependencyProto = descriptorProtoIndex.get(dependencyName);
dependencies.add(descriptorFromProto(dependencyProto, descriptorProtoIndex, descriptorCache));
}
// Finally, construct the actual descriptor.
FileDescriptor[] empty = new FileDescriptor[0];
return FileDescriptor.buildFrom(descriptorProto, dependencies.build().toArray(empty));
}
private void processDependencies(FileDescriptorProto fileDescriptor) {
logger.debug("Processing deps of descriptor: " + fileDescriptor.getName());
fileDescriptor.getDependencyList().forEach(dep -> {
if (!resolvedDescriptors.containsKey(dep) && !requestedDescriptors.contains(dep)) {
requestedDescriptors.add(dep);
++outstandingRequests;
requestStream.onNext(requestForDescriptor(dep));
}
});
--outstandingRequests;
if (outstandingRequests == 0) {
logger.debug("Retrieved service definition for [{}] by reflection", serviceName);
resultFuture.set(FileDescriptorSet.newBuilder()
.addAllFile(resolvedDescriptors.values())
.build());
requestStream.onCompleted();
}
}
/** Creates a resolver which searches the supplied {@link FileDescriptorSet}. */
public static ServiceResolver fromFileDescriptorSet(FileDescriptorSet descriptorSet) {
ImmutableMap<String, FileDescriptorProto> descriptorProtoIndex =
computeDescriptorProtoIndex(descriptorSet);
Map<String, FileDescriptor> descriptorCache = new HashMap<>();
ImmutableList.Builder<FileDescriptor> result = ImmutableList.builder();
for (FileDescriptorProto descriptorProto : descriptorSet.getFileList()) {
try {
result.add(descriptorFromProto(descriptorProto, descriptorProtoIndex, descriptorCache));
} catch (DescriptorValidationException e) {
logger.warn("Skipped descriptor " + descriptorProto.getName() + " due to error", e);
continue;
}
}
return new ServiceResolver(result.build());
}
/**
* Recursively constructs file descriptors for all dependencies of the supplied proto and returns
* a {@link FileDescriptor} for the supplied proto itself. For maximal efficiency, reuse the
* descriptorCache argument across calls.
*/
private static FileDescriptor descriptorFromProto(
FileDescriptorProto descriptorProto,
ImmutableMap<String, FileDescriptorProto> descriptorProtoIndex,
Map<String, FileDescriptor> descriptorCache) throws DescriptorValidationException {
// First, check the cache.
String descritorName = descriptorProto.getName();
if (descriptorCache.containsKey(descritorName)) {
return descriptorCache.get(descritorName);
}
// Then, fetch all the required dependencies recursively.
ImmutableList.Builder<FileDescriptor> dependencies = ImmutableList.builder();
for (String dependencyName : descriptorProto.getDependencyList()) {
if (!descriptorProtoIndex.containsKey(dependencyName)) {
throw new IllegalArgumentException("Could not find dependency: " + dependencyName);
}
FileDescriptorProto dependencyProto = descriptorProtoIndex.get(dependencyName);
dependencies.add(descriptorFromProto(dependencyProto, descriptorProtoIndex, descriptorCache));
}
// Finally, construct the actual descriptor.
FileDescriptor[] empty = new FileDescriptor[0];
return FileDescriptor.buildFrom(descriptorProto, dependencies.build().toArray(empty));
}
private void processDependencies(FileDescriptorProto fileDescriptor) {
logger.debug("Processing deps of descriptor: " + fileDescriptor.getName());
fileDescriptor.getDependencyList().forEach(dep -> {
if (!resolvedDescriptors.containsKey(dep) && !requestedDescriptors.contains(dep)) {
requestedDescriptors.add(dep);
++outstandingRequests;
requestStream.onNext(requestForDescriptor(dep));
}
});
--outstandingRequests;
if (outstandingRequests == 0) {
logger.debug("Retrieved service definition for [{}] by reflection", serviceName);
resultFuture.set(FileDescriptorSet.newBuilder()
.addAllFile(resolvedDescriptors.values())
.build());
requestStream.onCompleted();
}
}
FileDescriptor(final FileDescriptorProto protoFile) {
this.protoFile = protoFile;
sanitizedProtoFileName = sanitizeFileName(protoFile.getName());
protoPackageName = protoFile.hasPackage() ? protoFile.getPackage() : null;
if (protoFile.hasOptions()) {
final FileOptions fileOptions = protoFile.getOptions();
deprecated = fileOptions.hasDeprecated() && fileOptions.getDeprecated();
multipleClassFiles = fileOptions.hasJavaMultipleFiles() && fileOptions.getJavaMultipleFiles();
javaPackageName = fileOptions.hasJavaPackage() ? fileOptions.getJavaPackage() : null;
outerClassName = fileOptions.hasJavaOuterClassname() ? fileOptions.getJavaOuterClassname() : null;
} else {
deprecated = false;
multipleClassFiles = false;
javaPackageName = null;
outerClassName = null;
}
serviceClassBuilders = new ArrayList<>(protoFile.getServiceCount());
}
/**
* Creates a resolver which searches the supplied {@link FileDescriptorSet}.
*/
public static ServiceResolver fromFileDescriptorSet(FileDescriptorSet descriptorSet) {
ImmutableMap<String, FileDescriptorProto> descriptorProtoIndex =
computeDescriptorProtoIndex(descriptorSet);
Map<String, FileDescriptor> descriptorCache = new HashMap<>();
ImmutableList.Builder<FileDescriptor> result = ImmutableList.builder();
for (FileDescriptorProto descriptorProto : descriptorSet.getFileList()) {
try {
result.add(descriptorFromProto(descriptorProto, descriptorProtoIndex, descriptorCache));
} catch (DescriptorValidationException e) {
logger.warn("Skipped descriptor " + descriptorProto.getName() + " due to error", e);
}
}
return new ServiceResolver(result.build());
}
/**
* Recursively constructs file descriptors for all dependencies of the supplied proto and returns
* a {@link FileDescriptor} for the supplied proto itself. For maximal efficiency, reuse the
* descriptorCache argument across calls.
*/
private static FileDescriptor descriptorFromProto(
FileDescriptorProto descriptorProto,
ImmutableMap<String, FileDescriptorProto> descriptorProtoIndex,
Map<String, FileDescriptor> descriptorCache) throws DescriptorValidationException {
// First, check the cache.
String descriptorName = descriptorProto.getName();
if (descriptorCache.containsKey(descriptorName)) {
return descriptorCache.get(descriptorName);
}
// Then, fetch all the required dependencies recursively.
ImmutableList.Builder<FileDescriptor> dependencies = ImmutableList.builder();
for (String dependencyName : descriptorProto.getDependencyList()) {
if (!descriptorProtoIndex.containsKey(dependencyName)) {
throw new IllegalArgumentException("Could not find dependency: " + dependencyName);
}
FileDescriptorProto dependencyProto = descriptorProtoIndex.get(dependencyName);
dependencies.add(descriptorFromProto(dependencyProto, descriptorProtoIndex, descriptorCache));
}
// Finally, construct the actual descriptor.
FileDescriptor[] empty = new FileDescriptor[0];
return FileDescriptor.buildFrom(descriptorProto, dependencies.build().toArray(empty));
}
private void processDependencies(FileDescriptorProto fileDescriptor) {
logger.debug("Processing deps of descriptor: " + fileDescriptor.getName());
fileDescriptor.getDependencyList().forEach(dep -> {
if (!resolvedDescriptors.containsKey(dep) && !requestedDescriptors.contains(dep)) {
requestedDescriptors.add(dep);
++outstandingRequests;
requestStream.onNext(requestForDescriptor(dep));
}
});
--outstandingRequests;
if (outstandingRequests == 0) {
logger.debug("Retrieved service definition for [{}] by reflection", serviceName);
resultFuture.set(FileDescriptorSet.newBuilder()
.addAllFile(resolvedDescriptors.values())
.build());
requestStream.onCompleted();
}
}
private List<ServiceContext> findServices(List<FileDescriptorProto> protos, ProtoTypeMap typeMap) {
List<ServiceContext> contexts = new ArrayList<>();
for (FileDescriptorProto fileProto : protos) {
for (int serviceNumber = 0; serviceNumber < fileProto.getServiceCount(); serviceNumber++) {
ServiceContext serviceContext = buildServiceContext(
fileProto.getService(serviceNumber),
typeMap,
fileProto.getSourceCodeInfo().getLocationList(),
serviceNumber
);
serviceContext.setProtoName(fileProto.getName());
serviceContext.setPackageName(extractPackageName(fileProto));
contexts.add(serviceContext);
}
}
return contexts;
}
private List<ServiceContext> findServices(List<FileDescriptorProto> protos, ProtoTypeMap typeMap) {
List<ServiceContext> contexts = new ArrayList<>();
protos.forEach(fileProto -> {
for (int serviceNumber = 0; serviceNumber < fileProto.getServiceCount(); serviceNumber++) {
ServiceContext serviceContext = buildServiceContext(
fileProto.getService(serviceNumber),
typeMap,
fileProto.getSourceCodeInfo().getLocationList(),
serviceNumber
);
serviceContext.protoName = fileProto.getName();
serviceContext.packageName = extractPackageName(fileProto);
contexts.add(serviceContext);
}
});
return contexts;
}
public void generateFile(String protoPath) {
try {
if (pojoTypes == null) {
pojoTypes = Maps.newHashMap();
}
} finally {
if (!new File(protoPath).exists()) {
logger.warn("protoPath:" + protoPath
+ " not exist, it may be in the third party jars, so it can't be generate");
return;
}
FileDescriptorSet fileDescriptorSet = commondProtoc.invoke(protoPath);
for (FileDescriptorProto fdp : fileDescriptorSet.getFileList()) {
Pair<String, String> packageClassName = this.packageClassName(fdp.getOptions());
if (packageClassName == null) {
continue;
}
ProtocolStringList dependencyList = fdp.getDependencyList();
for (Iterator<String> it = dependencyList.iterator(); it.hasNext();) {
String dependencyPath = discoveryRoot + "/" + it.next();
generateFile(dependencyPath);
}
doPrint(fdp, packageClassName.getLeft(), packageClassName.getRight());
}
}
}
private FileDescriptorProto generateFile(String name, FileContents contents) {
FileDescriptorProto.Builder fileBuilder = FileDescriptorProto.newBuilder();
fileBuilder.setName(name);
if (!Strings.isNullOrEmpty(contents.packageName)) {
fileBuilder.setPackage(contents.packageName);
}
for (Api api : contents.apis) {
fileBuilder.addService(generateApi(api));
}
for (Type type : contents.types.values()) {
fileBuilder.addMessageType(generateType(type, contents));
}
for (Enum e : contents.enums) {
fileBuilder.addEnumType(generateEnum(e));
}
if (imports.containsKey(name)) {
for (String imported : imports.get(name)) {
fileBuilder.addDependency(imported);
}
}
return fileBuilder.build();
}
private void add(FileDescriptorProto file) {
currentFile = file;
fullNameSegments.push(file.getPackage());
locationMap = buildLocationMap(file);
pathSegments.push(FileDescriptorProto.EXTENSION_FIELD_NUMBER);
add(file.getExtensionList());
pathSegments.pop();
pathSegments.push(FileDescriptorProto.MESSAGE_TYPE_FIELD_NUMBER);
for (int i = 0; i < file.getMessageTypeCount(); i++) {
pathSegments.push(i);
add(file.getMessageType(i));
pathSegments.pop();
}
pathSegments.pop();
fullNameSegments.pop();
}
private static Syntax getProtoSyntax(FileDescriptorProto proto) {
if (!proto.hasSyntax()) {
// TODO(user): This can be removed once protoc outputs proto2 when proto2 is being used.
// According to [email protected] it would break a lot of tests, so it is currently not done.
return Syntax.SYNTAX_PROTO2;
}
switch (proto.getSyntax()) {
case "proto2":
return Syntax.SYNTAX_PROTO2;
case "proto3":
return Syntax.SYNTAX_PROTO3;
default:
throw new IllegalArgumentException(
"Illegal proto syntax for file " + proto.getName() + ": " + proto.getSyntax());
}
}
/**
* Construct a {@code FileDescriptor}.
*
* @param proto The protocol message form of the FileDescriptor.
* @param dependencies {@code FileDescriptor}s corresponding to all of
* the file's dependencies.
* @param allowUnknownDependencies If true, non-exist dependenncies will be
* ignored and undefined message types will be replaced with a
* placeholder type.
* @throws DescriptorValidationException {@code proto} is not a valid
* descriptor. This can occur for a number of reasons, e.g.
* because a field has an undefined type or because two messages
* were defined with the same name.
*/
public static FileDescriptor buildFrom(
final FileDescriptorProto proto, final FileDescriptor[] dependencies,
final boolean allowUnknownDependencies)
throws DescriptorValidationException {
// Building descriptors involves two steps: translating and linking.
// In the translation step (implemented by FileDescriptor's
// constructor), we build an object tree mirroring the
// FileDescriptorProto's tree and put all of the descriptors into the
// DescriptorPool's lookup tables. In the linking step, we look up all
// type references in the DescriptorPool, so that, for example, a
// FieldDescriptor for an embedded message contains a pointer directly
// to the Descriptor for that message's type. We also detect undefined
// types in the linking step.
final DescriptorPool pool = new DescriptorPool(
dependencies, allowUnknownDependencies);
final FileDescriptor result = new FileDescriptor(
proto, dependencies, pool, allowUnknownDependencies);
result.crossLink();
return result;
}
/**
* Create a placeholder FileDescriptor for a message Descriptor.
*/
FileDescriptor(String packageName, Descriptor message)
throws DescriptorValidationException {
this.pool = new DescriptorPool(new FileDescriptor[0], true);
this.proto = FileDescriptorProto.newBuilder()
.setName(message.getFullName() + ".placeholder.proto")
.setPackage(packageName).addMessageType(message.toProto()).build();
this.dependencies = new FileDescriptor[0];
this.publicDependencies = new FileDescriptor[0];
messageTypes = new Descriptor[] {message};
enumTypes = new EnumDescriptor[0];
services = new ServiceDescriptor[0];
extensions = new FieldDescriptor[0];
pool.addPackage(packageName, this);
pool.addSymbol(message);
}
/**
* Replace our {@link FileDescriptorProto} with the given one, which is
* identical except that it might contain extensions that weren't present
* in the original. This method is needed for bootstrapping when a file
* defines custom options. The options may be defined in the file itself,
* so we can't actually parse them until we've constructed the descriptors,
* but to construct the descriptors we have to have parsed the descriptor
* protos. So, we have to parse the descriptor protos a second time after
* constructing the descriptors.
*/
private void setProto(final FileDescriptorProto proto) {
this.proto = proto;
for (int i = 0; i < messageTypes.length; i++) {
messageTypes[i].setProto(proto.getMessageType(i));
}
for (int i = 0; i < enumTypes.length; i++) {
enumTypes[i].setProto(proto.getEnumType(i));
}
for (int i = 0; i < services.length; i++) {
services[i].setProto(proto.getService(i));
}
for (int i = 0; i < extensions.length; i++) {
extensions[i].setProto(proto.getExtension(i));
}
}
public void decompile(FileDescriptorProto fileDescriptor) throws IOException {
if (fileDescriptor.hasPackage()) {
indentedFormat("package %s;", fileDescriptor.getPackage());
absolutePackage = "." + fileDescriptor.getPackage() + ".";
}
for (String dependency : fileDescriptor.getDependencyList()) {
indentedFormat("import \"%s\";", dependency);
}
if (fileDescriptor.hasOptions()) {
decompileOptions(fileDescriptor.getOptions());
}
decompileMembers(fileDescriptor.getEnumTypeList(),
fileDescriptor.getMessageTypeList(),
Collections.<FieldDescriptorProto>emptyList(),
Collections.<DescriptorProto.ExtensionRange>emptyList(),
fileDescriptor.getExtensionList());
for (ServiceDescriptorProto serviceDescriptor : fileDescriptor.getServiceList()) {
decompile(serviceDescriptor);
}
newline();
flush();
}
public void testInvalidPublicDependency() throws Exception {
FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
.setName("foo.proto") .build();
FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
.setName("boo.proto")
.addDependency("foo.proto")
.addPublicDependency(1) // Error, should be 0.
.build();
FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
new FileDescriptor[0]);
try {
Descriptors.FileDescriptor.buildFrom(barProto,
new FileDescriptor[] {fooFile});
fail("DescriptorValidationException expected");
} catch (DescriptorValidationException e) {
assertTrue(
e.getMessage().indexOf("Invalid public dependency index.") != -1);
}
}
@Nullable
private static String getFullName(FileDescriptorProto descriptor, List<Integer> path) {
String fullNameSoFar = descriptor.getPackage();
switch (path.get(0)) {
case FileDescriptorProto.MESSAGE_TYPE_FIELD_NUMBER:
final DescriptorProto message = descriptor.getMessageType(path.get(1));
return appendMessageToFullName(message, path, fullNameSoFar);
case FileDescriptorProto.ENUM_TYPE_FIELD_NUMBER:
final EnumDescriptorProto enumDescriptor = descriptor.getEnumType(path.get(1));
return appendEnumToFullName(enumDescriptor, path, fullNameSoFar);
case FileDescriptorProto.SERVICE_FIELD_NUMBER:
final ServiceDescriptorProto serviceDescriptor = descriptor.getService(path.get(1));
fullNameSoFar = appendNameComponent(fullNameSoFar, serviceDescriptor.getName());
if (path.size() > 2) {
fullNameSoFar = appendFieldComponent(
fullNameSoFar, serviceDescriptor.getMethod(path.get(3)).getName());
}
return fullNameSoFar;
default:
return null;
}
}
public ProtoDomain get() {
rootNamespace = root.path("namespace").asText();
protoMessageOf(root);
Map<String, FileDescriptorProto.Builder> fileMap = new HashMap<>();
messageMap.forEach(
(fullName, message) -> {
String packageName =
fullName.substring(0, fullName.length() - message.getName().length() - 1);
FileDescriptorProto.Builder fdp = fileMap.get(packageName);
if (fdp == null) {
fdp =
DescriptorProtos.FileDescriptorProto.newBuilder()
.setName(packageNameToFileName(packageName))
.setPackage(packageName)
.setSyntax("proto3");
fileMap.put(packageName, fdp);
}
fdp.addMessageType(message);
});
DescriptorProtos.FileDescriptorSet.Builder fds =
DescriptorProtos.FileDescriptorSet.newBuilder();
fileMap.forEach(
(name, fdp) -> {
Set<String> imports = importMap.get(fdp.getPackage());
if (imports != null) {
imports.forEach(im -> fdp.addDependency(im));
}
fds.addFile(fdp);
});
fds.addFile(Int64Value.getDescriptor().getFile().toProto());
return ProtoDomain.buildFrom(fds.build());
}
/**
* Returns a map from descriptor proto name as found inside the descriptors to protos.
*/
private static ImmutableMap<String, FileDescriptorProto> computeDescriptorProtoIndex(
FileDescriptorSet fileDescriptorSet) {
ImmutableMap.Builder<String, FileDescriptorProto> resultBuilder = ImmutableMap.builder();
for (FileDescriptorProto descriptorProto : fileDescriptorSet.getFileList()) {
resultBuilder.put(descriptorProto.getName(), descriptorProto);
}
return resultBuilder.build();
}
@Override
public void onNext(ServerReflectionResponse response) {
MessageResponseCase responseCase = response.getMessageResponseCase();
switch (responseCase) {
case FILE_DESCRIPTOR_RESPONSE:
ImmutableSet<FileDescriptorProto> descriptors =
parseDescriptors(response.getFileDescriptorResponse().getFileDescriptorProtoList());
descriptors.forEach(d -> resolvedDescriptors.put(d.getName(), d));
descriptors.forEach(this::processDependencies);
break;
default:
logger.warn("Got unknown reflection response type: " + responseCase);
break;
}
}
private ImmutableSet<FileDescriptorProto> parseDescriptors(List<ByteString> descriptorBytes) {
ImmutableSet.Builder<FileDescriptorProto> resultBuilder = ImmutableSet.builder();
for (ByteString fileDescriptorBytes : descriptorBytes) {
try {
resultBuilder.add(FileDescriptorProto.parseFrom(fileDescriptorBytes));
} catch (InvalidProtocolBufferException e) {
logger.warn("Failed to parse bytes as file descriptor proto");
}
}
return resultBuilder.build();
}
/**
* Returns a map from descriptor proto name as found inside the descriptors to protos.
*/
private static ImmutableMap<String, FileDescriptorProto> computeDescriptorProtoIndex(
FileDescriptorSet fileDescriptorSet) {
ImmutableMap.Builder<String, FileDescriptorProto> resultBuilder = ImmutableMap.builder();
for (FileDescriptorProto descriptorProto : fileDescriptorSet.getFileList()) {
resultBuilder.put(descriptorProto.getName(), descriptorProto);
}
return resultBuilder.build();
}
@Override
public void onNext(ServerReflectionResponse response) {
MessageResponseCase responseCase = response.getMessageResponseCase();
switch (responseCase) {
case FILE_DESCRIPTOR_RESPONSE:
ImmutableSet<FileDescriptorProto> descriptors =
parseDescriptors(response.getFileDescriptorResponse().getFileDescriptorProtoList());
descriptors.forEach(d -> resolvedDescriptors.put(d.getName(), d));
descriptors.forEach(d -> processDependencies(d));
break;
default:
logger.warn("Got unknown reflection response type: " + responseCase);
break;
}
}
private ImmutableSet<FileDescriptorProto> parseDescriptors(List<ByteString> descriptorBytes) {
ImmutableSet.Builder<FileDescriptorProto> resultBuilder = ImmutableSet.builder();
for (ByteString fileDescriptorBytes : descriptorBytes) {
try {
resultBuilder.add(FileDescriptorProto.parseFrom(fileDescriptorBytes));
} catch (InvalidProtocolBufferException e) {
logger.warn("Failed to parse bytes as file descriptor proto");
}
}
return resultBuilder.build();
}
/**
* Returns a map from descriptor proto name as found inside the descriptors to protos.
*/
private static ImmutableMap<String, FileDescriptorProto> computeDescriptorProtoIndex(
FileDescriptorSet fileDescriptorSet) {
ImmutableMap.Builder<String, FileDescriptorProto> resultBuilder = ImmutableMap.builder();
for (FileDescriptorProto descriptorProto : fileDescriptorSet.getFileList()) {
resultBuilder.put(descriptorProto.getName(), descriptorProto);
}
return resultBuilder.build();
}