31 package com.google.protobuf;
53 import java.util.ArrayList;
54 import java.util.Arrays;
55 import java.util.Collections;
56 import java.util.HashMap;
57 import java.util.HashSet;
58 import java.util.List;
61 import java.util.WeakHashMap;
62 import java.util.logging.Logger;
97 return proto.getName();
109 return proto.getName();
117 return proto.getPackage();
122 return proto.getOptions();
127 return Collections.unmodifiableList(Arrays.asList(
messageTypes));
132 return Collections.unmodifiableList(Arrays.asList(
enumTypes));
137 return Collections.unmodifiableList(Arrays.asList(
services));
142 return Collections.unmodifiableList(Arrays.asList(
extensions));
147 return Collections.unmodifiableList(Arrays.asList(
dependencies));
185 if (
name.indexOf(
'.') != -1) {
189 if (!packageName.isEmpty()) {
193 if (result !=
null && result instanceof
Descriptor && result.
getFile() ==
this) {
209 if (
name.indexOf(
'.') != -1) {
213 if (!packageName.isEmpty()) {
233 if (
name.indexOf(
'.') != -1) {
237 if (!packageName.isEmpty()) {
255 if (
name.indexOf(
'.') != -1) {
259 if (!packageName.isEmpty()) {
297 final FileDescriptorProto
proto,
299 final boolean allowUnknownDependencies)
330 StringBuilder descriptorData =
new StringBuilder();
332 descriptorData.append(part);
334 return descriptorData.toString().getBytes(
Internal.ISO_8859_1);
338 final Class<?> descriptorOuterClass,
339 final String[] dependencyClassNames,
340 final String[] dependencyFileNames) {
341 List<FileDescriptor> descriptors =
new ArrayList<FileDescriptor>();
342 for (
int i = 0;
i < dependencyClassNames.length;
i++) {
344 Class<?> clazz = descriptorOuterClass.getClassLoader().loadClass(dependencyClassNames[
i]);
345 descriptors.add((
FileDescriptor) clazz.getField(
"descriptor").get(
null));
346 }
catch (Exception e) {
349 logger.warning(
"Descriptors for \"" + dependencyFileNames[
i] +
"\" can not be found.");
361 final String[] descriptorDataParts,
364 final byte[] descriptorBytes =
latin1Cat(descriptorDataParts);
366 FileDescriptorProto
proto;
368 proto = FileDescriptorProto.parseFrom(descriptorBytes);
370 throw new IllegalArgumentException(
371 "Failed to parse protocol buffer descriptor for generated code.", e);
380 throw new IllegalArgumentException(
381 "Invalid embedded descriptor for \"" +
proto.getName() +
"\".", e);
386 if (registry !=
null) {
389 proto = FileDescriptorProto.parseFrom(descriptorBytes, registry);
391 throw new IllegalArgumentException(
392 "Failed to parse protocol buffer descriptor for generated code.", e);
404 final String[] descriptorDataParts,
406 final byte[] descriptorBytes =
latin1Cat(descriptorDataParts);
408 FileDescriptorProto
proto;
410 proto = FileDescriptorProto.parseFrom(descriptorBytes);
412 throw new IllegalArgumentException(
413 "Failed to parse protocol buffer descriptor for generated code.", e);
421 throw new IllegalArgumentException(
422 "Invalid embedded descriptor for \"" +
proto.getName() +
"\".", e);
432 final String[] descriptorDataParts,
433 final Class<?> descriptorOuterClass,
434 final String[] dependencyClassNames,
435 final String[] dependencyFileNames,
438 descriptorOuterClass, dependencyClassNames, dependencyFileNames);
448 final String[] descriptorDataParts,
449 final Class<?> descriptorOuterClass,
450 final String[] dependencyClassNames,
451 final String[] dependencyFileNames) {
453 descriptorOuterClass, dependencyClassNames, dependencyFileNames);
465 FileDescriptorProto
proto;
467 proto = FileDescriptorProto.parseFrom(
bytes, registry);
469 throw new IllegalArgumentException(
470 "Failed to parse protocol buffer descriptor for generated code.", e);
502 final FileDescriptorProto
proto,
505 boolean allowUnknownDependencies)
510 HashMap<String, FileDescriptor> nameToFileMap =
new HashMap<String, FileDescriptor>();
512 nameToFileMap.put(file.getName(), file);
515 for (
int i = 0;
i <
proto.getPublicDependencyCount();
i++) {
523 if (!allowUnknownDependencies) {
537 for (
int i = 0;
i <
proto.getMessageTypeCount();
i++) {
542 for (
int i = 0;
i <
proto.getEnumTypeCount();
i++) {
547 for (
int i = 0;
i <
proto.getServiceCount();
i++) {
552 for (
int i = 0;
i <
proto.getExtensionCount();
i++) {
561 FileDescriptorProto.newBuilder()
562 .setName(
message.getFullName() +
".placeholder.proto")
563 .setPackage(packageName)
564 .addMessageType(
message.toProto())
574 pool.addPackage(packageName,
this);
581 messageType.crossLink();
621 boolean supportsUnknownEnumValue() {
659 return proto.getName();
692 return proto.getOptions();
697 return Collections.unmodifiableList(Arrays.asList(
fields));
702 return Collections.unmodifiableList(Arrays.asList(
oneofs));
707 return Collections.unmodifiableList(Arrays.asList(
extensions));
712 return Collections.unmodifiableList(Arrays.asList(
nestedTypes));
717 return Collections.unmodifiableList(Arrays.asList(
enumTypes));
722 for (
final DescriptorProto.ExtensionRange
range :
proto.getExtensionRangeList()) {
732 for (
final DescriptorProto.ReservedRange
range :
proto.getReservedRangeList()) {
743 for (
final String reservedName :
proto.getReservedNameList()) {
744 if (reservedName.equals(
name)) {
756 return proto.getExtensionRangeList().size() != 0;
792 if (result !=
null && result instanceof
Descriptor) {
827 String
name = fullname;
828 String packageName =
"";
829 int pos = fullname.lastIndexOf(
'.');
831 name = fullname.substring(pos + 1);
832 packageName = fullname.substring(0, pos);
836 DescriptorProto.newBuilder()
839 DescriptorProto.ExtensionRange.newBuilder().setStart(1).setEnd(536870912).build())
841 this.fullName = fullname;
842 this.containingType =
null;
855 final DescriptorProto
proto,
867 for (
int i = 0;
i <
proto.getOneofDeclCount();
i++) {
872 for (
int i = 0;
i <
proto.getNestedTypeCount();
i++) {
877 for (
int i = 0;
i <
proto.getEnumTypeCount();
i++) {
882 for (
int i = 0;
i <
proto.getFieldCount();
i++) {
887 for (
int i = 0;
i <
proto.getExtensionCount();
i++) {
891 for (
int i = 0;
i <
proto.getOneofDeclCount();
i++) {
895 for (
int i = 0;
i <
proto.getFieldCount();
i++) {
897 if (oneofDescriptor !=
null) {
908 nestedType.crossLink();
928 for (
int i = 0;
i <
oneofs.length;
i++) {
936 for (
int i = 0;
i <
fields.length;
i++) {
969 return proto.getName();
975 return proto.getNumber();
998 return type.getJavaType();
1052 return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED;
1057 return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL;
1063 return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
1089 return proto.hasDefaultValue();
1099 throw new UnsupportedOperationException(
1100 "FieldDescriptor.getDefaultValue() called on an embedded message field.");
1107 return proto.getOptions();
1112 return proto.hasExtendee();
1151 throw new UnsupportedOperationException(
1152 String.format(
"This field is not an extension. (%s)",
fullName));
1160 throw new UnsupportedOperationException(
1161 String.format(
"This field is not of message type. (%s)",
fullName));
1170 throw new UnsupportedOperationException(
1171 String.format(
"This field is not of enum type. (%s)",
fullName));
1187 throw new IllegalArgumentException(
1188 "FieldDescriptors can only be compared to other FieldDescriptors "
1189 +
"for fields of the same message type.");
1236 this.javaType = javaType;
1242 return FieldDescriptorProto.
Type.forNumber(ordinal() + 1);
1256 if (
Type.values().length != FieldDescriptorProto.
Type.values().length) {
1257 throw new RuntimeException(
1258 "descriptor.proto has a new declared type but Descriptors.java wasn't updated.");
1274 this.defaultDefault = defaultDefault;
1288 StringBuilder result =
new StringBuilder(
length);
1289 boolean isNextUpperCase =
false;
1293 isNextUpperCase =
true;
1294 }
else if (isNextUpperCase) {
1297 if (
'a' <=
ch &&
ch <=
'z') {
1298 ch = (char) (
ch -
'a' +
'A');
1301 isNextUpperCase =
false;
1306 return result.toString();
1310 final FieldDescriptorProto
proto,
1320 if (
proto.hasJsonName()) {
1326 if (
proto.hasType()) {
1335 if (!
proto.hasExtendee()) {
1337 this,
"FieldDescriptorProto.extendee not set for extension field.");
1340 if (parent !=
null) {
1346 if (
proto.hasOneofIndex()) {
1348 this,
"FieldDescriptorProto.oneof_index set for extension field.");
1352 if (
proto.hasExtendee()) {
1354 this,
"FieldDescriptorProto.extendee set for non-extension field.");
1358 if (
proto.hasOneofIndex()) {
1359 if (
proto.getOneofIndex() < 0
1360 ||
proto.getOneofIndex() >= parent.toProto().getOneofDeclCount()) {
1363 "FieldDescriptorProto.oneof_index is out of range for type " + parent.getName());
1378 if (
proto.hasExtendee()) {
1384 this,
'\"' +
proto.getExtendee() +
"\" is not a message type.");
1393 +
"\" does not declare "
1395 +
" as an extension number.");
1399 if (
proto.hasTypeName()) {
1404 if (!
proto.hasType()) {
1412 this,
'\"' +
proto.getTypeName() +
"\" is not a type.");
1417 if (!(typeDescriptor instanceof
Descriptor)) {
1419 this,
'\"' +
proto.getTypeName() +
"\" is not a message type.");
1423 if (
proto.hasDefaultValue()) {
1429 this,
'\"' +
proto.getTypeName() +
"\" is not an enum type.");
1438 this,
"Field with message or enum type missing type_name.");
1445 this,
"[packed = true] can only be specified for repeated primitive fields.");
1450 if (
proto.hasDefaultValue()) {
1453 this,
"Repeated fields cannot have default values.");
1477 if (
proto.getDefaultValue().equals(
"inf")) {
1479 }
else if (
proto.getDefaultValue().equals(
"-inf")) {
1481 }
else if (
proto.getDefaultValue().equals(
"nan")) {
1488 if (
proto.getDefaultValue().equals(
"inf")) {
1490 }
else if (
proto.getDefaultValue().equals(
"-inf")) {
1492 }
else if (
proto.getDefaultValue().equals(
"nan")) {
1509 this,
"Couldn't parse default value: " + e.getMessage(), e);
1516 this,
"Unknown enum default value: \"" +
proto.getDefaultValue() +
'\"');
1523 }
catch (NumberFormatException e) {
1525 this,
"Could not parse default value: \"" +
proto.getDefaultValue() +
'\"', e);
1556 this,
"Extensions of MessageSets must be optional messages.");
1560 this,
"MessageSets cannot have fields, only extensions.");
1603 return proto.getName();
1629 return proto.getOptions();
1634 return Collections.unmodifiableList(Arrays.asList(
values));
1670 if (result !=
null) {
1674 synchronized (
this) {
1706 if (reference !=
null) {
1707 result = reference.get();
1709 if (result ==
null) {
1718 int getUnknownEnumValueDescriptorCount() {
1728 private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>
unknownValues =
1729 new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
1732 final EnumDescriptorProto
proto,
1743 if (
proto.getValueCount() == 0) {
1750 for (
int i = 0;
i <
proto.getValueCount();
i++) {
1761 for (
int i = 0;
i <
values.length;
i++) {
1794 return proto.getName();
1800 return proto.getNumber();
1805 return proto.getName();
1831 return proto.getOptions();
1841 final EnumValueDescriptorProto
proto,
1854 file.
pool.addEnumValueByNumber(
this);
1861 EnumValueDescriptorProto
proto =
1862 EnumValueDescriptorProto.newBuilder().setName(
name).setNumber(
number).build();
1898 return proto.getName();
1919 return proto.getOptions();
1924 return Collections.unmodifiableList(Arrays.asList(
methods));
1957 for (
int i = 0;
i <
proto.getMethodCount();
i++) {
2000 return proto.getName();
2036 return proto.getClientStreaming();
2041 return proto.getServerStreaming();
2046 return proto.getOptions();
2060 final MethodDescriptorProto
proto,
2081 this,
'\"' +
proto.getInputType() +
"\" is not a message type.");
2090 this,
'\"' +
proto.getOutputType() +
"\" is not a message type.");
2105 if (parent !=
null) {
2109 final String packageName = file.
getPackage();
2110 if (!packageName.isEmpty()) {
2111 return packageName +
'.' +
name;
2130 public abstract String
getName();
2175 final Throwable cause) {
2209 this.dependencies =
new HashSet<FileDescriptor>();
2219 addPackage(dependency.getPackage(), dependency);
2224 throw new AssertionError(e);
2242 new HashMap<String, GenericDescriptor>();
2244 new HashMap<DescriptorIntPair, FieldDescriptor>();
2246 new HashMap<DescriptorIntPair, EnumValueDescriptor>();
2250 return findSymbol(fullName, SearchFilter.ALL_SYMBOLS);
2259 if (result !=
null) {
2260 if ((
filter == SearchFilter.ALL_SYMBOLS)
2261 || ((
filter == SearchFilter.TYPES_ONLY) && isType(result))
2262 || ((
filter == SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
2268 result = dependency.pool.descriptorsByName.get(fullName);
2269 if (result !=
null) {
2270 if ((
filter == SearchFilter.ALL_SYMBOLS)
2271 || ((
filter == SearchFilter.TYPES_ONLY) && isType(result))
2272 || ((
filter == SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
2282 boolean isType(GenericDescriptor
descriptor) {
2287 boolean isAggregate(GenericDescriptor
descriptor) {
2291 || (
descriptor instanceof ServiceDescriptor);
2299 GenericDescriptor lookupSymbol(
2301 final GenericDescriptor relativeTo,
2303 throws DescriptorValidationException {
2306 GenericDescriptor result;
2308 if (
name.startsWith(
".")) {
2310 fullname =
name.substring(1);
2311 result = findSymbol(fullname,
filter);
2326 final int firstPartLength =
name.indexOf(
'.');
2327 final String firstPart;
2328 if (firstPartLength == -1) {
2331 firstPart =
name.substring(0, firstPartLength);
2336 final StringBuilder scopeToTry =
new StringBuilder(relativeTo.getFullName());
2340 final int dotpos = scopeToTry.lastIndexOf(
".");
2346 scopeToTry.setLength(dotpos + 1);
2349 scopeToTry.append(firstPart);
2350 result = findSymbol(scopeToTry.toString(),
DescriptorPool.SearchFilter.AGGREGATES_ONLY);
2352 if (result !=
null) {
2353 if (firstPartLength != -1) {
2357 scopeToTry.setLength(dotpos + 1);
2358 scopeToTry.append(
name);
2359 result = findSymbol(scopeToTry.toString(),
filter);
2361 fullname = scopeToTry.toString();
2366 scopeToTry.setLength(dotpos);
2371 if (result ==
null) {
2374 "The descriptor for message type \""
2376 +
"\" can not be found and a placeholder is created for it");
2386 this.dependencies.add(result.getFile());
2389 throw new DescriptorValidationException(relativeTo,
'\"' +
name +
"\" is not defined.");
2400 void addSymbol(
final GenericDescriptor
descriptor)
throws DescriptorValidationException {
2403 final String fullName =
descriptor.getFullName();
2410 final int dotpos = fullName.lastIndexOf(
'.');
2412 throw new DescriptorValidationException(
2413 descriptor,
'\"' + fullName +
"\" is already defined.");
2415 throw new DescriptorValidationException(
2418 + fullName.substring(dotpos + 1)
2419 +
"\" is already defined in \""
2420 + fullName.substring(0, dotpos)
2424 throw new DescriptorValidationException(
2428 +
"\" is already defined in file \""
2429 + old.getFile().getName()
2477 void addPackage(
final String fullName,
final FileDescriptor file)
2479 final int dotpos = fullName.lastIndexOf(
'.');
2484 addPackage(fullName.substring(0, dotpos), file);
2485 name = fullName.substring(dotpos + 1);
2488 final GenericDescriptor old =
2492 if (!(old instanceof PackageDescriptor)) {
2497 +
"\" is already defined (as something other than a "
2498 +
"package) in file \""
2499 + old.getFile().getName()
2535 final DescriptorIntPair
key =
2536 new DescriptorIntPair(
field.getContainingType(),
field.getNumber());
2544 +
" has already been used in \""
2545 +
field.getContainingType().getFullName()
2558 final DescriptorIntPair
key =
new DescriptorIntPair(
value.getType(),
value.getNumber());
2571 static void validateSymbolName(
final GenericDescriptor
descriptor)
2572 throws DescriptorValidationException {
2574 if (
name.length() == 0) {
2575 throw new DescriptorValidationException(
descriptor,
"Missing name.");
2582 for (
int i = 0;
i <
name.length();
i++) {
2583 final char c =
name.charAt(
i);
2584 if ((
'a' <= c && c <=
'z') || (
'A' <= c && c <=
'Z')
2586 || (
'0' <= c && c <= '9' && i > 0)) {
2590 throw new DescriptorValidationException(
2605 return proto.getName();
2627 return proto.getOptions();
2632 return Collections.unmodifiableList(Arrays.asList(
fields));
2649 final OneofDescriptorProto
proto,