aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/Descriptors.java
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/Descriptors.java')
-rw-r--r--third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/Descriptors.java2547
1 files changed, 0 insertions, 2547 deletions
diff --git a/third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/Descriptors.java b/third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/Descriptors.java
deleted file mode 100644
index 38346f1559..0000000000
--- a/third_party/protobuf/3.2.0/java/core/src/main/java/com/google/protobuf/Descriptors.java
+++ /dev/null
@@ -1,2547 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf;
-
-import com.google.protobuf.DescriptorProtos.*;
-import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.logging.Logger;
-
-/**
- * Contains a collection of classes which describe protocol message types.
- *
- * Every message type has a {@link Descriptor}, which lists all
- * its fields and other information about a type. You can get a message
- * type's descriptor by calling {@code MessageType.getDescriptor()}, or
- * (given a message object of the type) {@code message.getDescriptorForType()}.
- * Furthermore, each message is associated with a {@link FileDescriptor} for
- * a relevant {@code .proto} file. You can obtain it by calling
- * {@code Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors
- * for all the messages defined in that file, and file descriptors for all the
- * imported {@code .proto} files.
- *
- * Descriptors are built from DescriptorProtos, as defined in
- * {@code google/protobuf/descriptor.proto}.
- *
- * @author kenton@google.com Kenton Varda
- */
-public final class Descriptors {
- private static final Logger logger =
- Logger.getLogger(Descriptors.class.getName());
- /**
- * Describes a {@code .proto} file, including everything defined within.
- * That includes, in particular, descriptors for all the messages and
- * file descriptors for all other imported {@code .proto} files
- * (dependencies).
- */
- public static final class FileDescriptor extends GenericDescriptor {
- /** Convert the descriptor to its protocol message representation. */
- @Override
- public FileDescriptorProto toProto() {
- return proto;
- }
-
- /** Get the file name. */
- @Override
- public String getName() {
- return proto.getName();
- }
-
- /** Returns this object. */
- @Override
- public FileDescriptor getFile() {
- return this;
- }
-
- /** Returns the same as getName(). */
- @Override
- public String getFullName() {
- return proto.getName();
- }
-
- /**
- * Get the proto package name. This is the package name given by the
- * {@code package} statement in the {@code .proto} file, which differs
- * from the Java package.
- */
- public String getPackage() { return proto.getPackage(); }
-
- /** Get the {@code FileOptions}, defined in {@code descriptor.proto}. */
- public FileOptions getOptions() { return proto.getOptions(); }
-
- /** Get a list of top-level message types declared in this file. */
- public List<Descriptor> getMessageTypes() {
- return Collections.unmodifiableList(Arrays.asList(messageTypes));
- }
-
- /** Get a list of top-level enum types declared in this file. */
- public List<EnumDescriptor> getEnumTypes() {
- return Collections.unmodifiableList(Arrays.asList(enumTypes));
- }
-
- /** Get a list of top-level services declared in this file. */
- public List<ServiceDescriptor> getServices() {
- return Collections.unmodifiableList(Arrays.asList(services));
- }
-
- /** Get a list of top-level extensions declared in this file. */
- public List<FieldDescriptor> getExtensions() {
- return Collections.unmodifiableList(Arrays.asList(extensions));
- }
-
- /** Get a list of this file's dependencies (imports). */
- public List<FileDescriptor> getDependencies() {
- return Collections.unmodifiableList(Arrays.asList(dependencies));
- }
-
- /** Get a list of this file's public dependencies (public imports). */
- public List<FileDescriptor> getPublicDependencies() {
- return Collections.unmodifiableList(Arrays.asList(publicDependencies));
- }
-
- /** The syntax of the .proto file. */
- public enum Syntax {
- UNKNOWN("unknown"),
- PROTO2("proto2"),
- PROTO3("proto3");
-
- Syntax(String name) {
- this.name = name;
- }
- private final String name;
- }
-
- /** Get the syntax of the .proto file. */
- public Syntax getSyntax() {
- if (Syntax.PROTO3.name.equals(proto.getSyntax())) {
- return Syntax.PROTO3;
- }
- return Syntax.PROTO2;
- }
-
- /**
- * Find a message type in the file by name. Does not find nested types.
- *
- * @param name The unqualified type name to look for.
- * @return The message type's descriptor, or {@code null} if not found.
- */
- public Descriptor findMessageTypeByName(String name) {
- // Don't allow looking up nested types. This will make optimization
- // easier later.
- if (name.indexOf('.') != -1) {
- return null;
- }
- if (getPackage().length() > 0) {
- name = getPackage() + '.' + name;
- }
- final GenericDescriptor result = pool.findSymbol(name);
- if (result != null && result instanceof Descriptor &&
- result.getFile() == this) {
- return (Descriptor)result;
- } else {
- return null;
- }
- }
-
- /**
- * Find an enum type in the file by name. Does not find nested types.
- *
- * @param name The unqualified type name to look for.
- * @return The enum type's descriptor, or {@code null} if not found.
- */
- public EnumDescriptor findEnumTypeByName(String name) {
- // Don't allow looking up nested types. This will make optimization
- // easier later.
- if (name.indexOf('.') != -1) {
- return null;
- }
- if (getPackage().length() > 0) {
- name = getPackage() + '.' + name;
- }
- final GenericDescriptor result = pool.findSymbol(name);
- if (result != null && result instanceof EnumDescriptor &&
- result.getFile() == this) {
- return (EnumDescriptor)result;
- } else {
- return null;
- }
- }
-
- /**
- * Find a service type in the file by name.
- *
- * @param name The unqualified type name to look for.
- * @return The service type's descriptor, or {@code null} if not found.
- */
- public ServiceDescriptor findServiceByName(String name) {
- // Don't allow looking up nested types. This will make optimization
- // easier later.
- if (name.indexOf('.') != -1) {
- return null;
- }
- if (getPackage().length() > 0) {
- name = getPackage() + '.' + name;
- }
- final GenericDescriptor result = pool.findSymbol(name);
- if (result != null && result instanceof ServiceDescriptor &&
- result.getFile() == this) {
- return (ServiceDescriptor)result;
- } else {
- return null;
- }
- }
-
- /**
- * Find an extension in the file by name. Does not find extensions nested
- * inside message types.
- *
- * @param name The unqualified extension name to look for.
- * @return The extension's descriptor, or {@code null} if not found.
- */
- public FieldDescriptor findExtensionByName(String name) {
- if (name.indexOf('.') != -1) {
- return null;
- }
- if (getPackage().length() > 0) {
- name = getPackage() + '.' + name;
- }
- final GenericDescriptor result = pool.findSymbol(name);
- if (result != null && result instanceof FieldDescriptor &&
- result.getFile() == this) {
- return (FieldDescriptor)result;
- } else {
- return null;
- }
- }
-
- /**
- * 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.
- * @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)
- throws DescriptorValidationException {
- return buildFrom(proto, dependencies, false);
- }
-
-
- /**
- * 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;
- }
-
- /**
- * This method is to be called by generated code only. It is equivalent
- * to {@code buildFrom} except that the {@code FileDescriptorProto} is
- * encoded in protocol buffer wire format.
- */
- public static void internalBuildGeneratedFileFrom(
- final String[] descriptorDataParts,
- final FileDescriptor[] dependencies,
- final InternalDescriptorAssigner descriptorAssigner) {
- // Hack: We can't embed a raw byte array inside generated Java code
- // (at least, not efficiently), but we can embed Strings. So, the
- // protocol compiler embeds the FileDescriptorProto as a giant
- // string literal which is passed to this function to construct the
- // file's FileDescriptor. The string literal contains only 8-bit
- // characters, each one representing a byte of the FileDescriptorProto's
- // serialized form. So, if we convert it to bytes in ISO-8859-1, we
- // should get the original bytes that we want.
-
- // descriptorData may contain multiple strings in order to get around the
- // Java 64k string literal limit.
- StringBuilder descriptorData = new StringBuilder();
- for (String part : descriptorDataParts) {
- descriptorData.append(part);
- }
-
- final byte[] descriptorBytes;
- descriptorBytes = descriptorData.toString().getBytes(Internal.ISO_8859_1);
-
- FileDescriptorProto proto;
- try {
- proto = FileDescriptorProto.parseFrom(descriptorBytes);
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalArgumentException(
- "Failed to parse protocol buffer descriptor for generated code.", e);
- }
-
- final FileDescriptor result;
- try {
- // When building descriptors for generated code, we allow unknown
- // dependencies by default.
- result = buildFrom(proto, dependencies, true);
- } catch (DescriptorValidationException e) {
- throw new IllegalArgumentException(
- "Invalid embedded descriptor for \"" + proto.getName() + "\".", e);
- }
-
- final ExtensionRegistry registry =
- descriptorAssigner.assignDescriptors(result);
-
- if (registry != null) {
- // We must re-parse the proto using the registry.
- try {
- proto = FileDescriptorProto.parseFrom(descriptorBytes, registry);
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalArgumentException(
- "Failed to parse protocol buffer descriptor for generated code.",
- e);
- }
-
- result.setProto(proto);
- }
- }
-
- /**
- * This method is to be called by generated code only. It uses Java
- * reflection to load the dependencies' descriptors.
- */
- public static void internalBuildGeneratedFileFrom(
- final String[] descriptorDataParts,
- final Class<?> descriptorOuterClass,
- final String[] dependencies,
- final String[] dependencyFileNames,
- final InternalDescriptorAssigner descriptorAssigner) {
- List<FileDescriptor> descriptors = new ArrayList<FileDescriptor>();
- for (int i = 0; i < dependencies.length; i++) {
- try {
- Class<?> clazz =
- descriptorOuterClass.getClassLoader().loadClass(dependencies[i]);
- descriptors.add(
- (FileDescriptor) clazz.getField("descriptor").get(null));
- } catch (Exception e) {
- // We allow unknown dependencies by default. If a dependency cannot
- // be found we only generate a warning.
- logger.warning("Descriptors for \"" + dependencyFileNames[i] +
- "\" can not be found.");
- }
- }
- FileDescriptor[] descriptorArray = new FileDescriptor[descriptors.size()];
- descriptors.toArray(descriptorArray);
- internalBuildGeneratedFileFrom(
- descriptorDataParts, descriptorArray, descriptorAssigner);
- }
-
- /**
- * This method is to be called by generated code only. It is used to
- * update the FileDescriptorProto associated with the descriptor by
- * parsing it again with the given ExtensionRegistry. This is needed to
- * recognize custom options.
- */
- public static void internalUpdateFileDescriptor(
- final FileDescriptor descriptor,
- final ExtensionRegistry registry) {
- ByteString bytes = descriptor.proto.toByteString();
- FileDescriptorProto proto;
- try {
- proto = FileDescriptorProto.parseFrom(bytes, registry);
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalArgumentException(
- "Failed to parse protocol buffer descriptor for generated code.", e);
- }
- descriptor.setProto(proto);
- }
-
- /**
- * This class should be used by generated code only. When calling
- * {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller
- * provides a callback implementing this interface. The callback is called
- * after the FileDescriptor has been constructed, in order to assign all
- * the global variables defined in the generated code which point at parts
- * of the FileDescriptor. The callback returns an ExtensionRegistry which
- * contains any extensions which might be used in the descriptor -- that
- * is, extensions of the various "Options" messages defined in
- * descriptor.proto. The callback may also return null to indicate that
- * no extensions are used in the descriptor.
- */
- public interface InternalDescriptorAssigner {
- ExtensionRegistry assignDescriptors(FileDescriptor root);
- }
-
- private FileDescriptorProto proto;
- private final Descriptor[] messageTypes;
- private final EnumDescriptor[] enumTypes;
- private final ServiceDescriptor[] services;
- private final FieldDescriptor[] extensions;
- private final FileDescriptor[] dependencies;
- private final FileDescriptor[] publicDependencies;
- private final DescriptorPool pool;
-
- private FileDescriptor(final FileDescriptorProto proto,
- final FileDescriptor[] dependencies,
- final DescriptorPool pool,
- boolean allowUnknownDependencies)
- throws DescriptorValidationException {
- this.pool = pool;
- this.proto = proto;
- this.dependencies = dependencies.clone();
- HashMap<String, FileDescriptor> nameToFileMap =
- new HashMap<String, FileDescriptor>();
- for (FileDescriptor file : dependencies) {
- nameToFileMap.put(file.getName(), file);
- }
- List<FileDescriptor> publicDependencies = new ArrayList<FileDescriptor>();
- for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
- int index = proto.getPublicDependency(i);
- if (index < 0 || index >= proto.getDependencyCount()) {
- throw new DescriptorValidationException(this,
- "Invalid public dependency index.");
- }
- String name = proto.getDependency(index);
- FileDescriptor file = nameToFileMap.get(name);
- if (file == null) {
- if (!allowUnknownDependencies) {
- throw new DescriptorValidationException(this,
- "Invalid public dependency: " + name);
- }
- // Ignore unknown dependencies.
- } else {
- publicDependencies.add(file);
- }
- }
- this.publicDependencies = new FileDescriptor[publicDependencies.size()];
- publicDependencies.toArray(this.publicDependencies);
-
- pool.addPackage(getPackage(), this);
-
- messageTypes = new Descriptor[proto.getMessageTypeCount()];
- for (int i = 0; i < proto.getMessageTypeCount(); i++) {
- messageTypes[i] =
- new Descriptor(proto.getMessageType(i), this, null, i);
- }
-
- enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
- for (int i = 0; i < proto.getEnumTypeCount(); i++) {
- enumTypes[i] = new EnumDescriptor(proto.getEnumType(i), this, null, i);
- }
-
- services = new ServiceDescriptor[proto.getServiceCount()];
- for (int i = 0; i < proto.getServiceCount(); i++) {
- services[i] = new ServiceDescriptor(proto.getService(i), this, i);
- }
-
- extensions = new FieldDescriptor[proto.getExtensionCount()];
- for (int i = 0; i < proto.getExtensionCount(); i++) {
- extensions[i] = new FieldDescriptor(
- proto.getExtension(i), this, null, i, true);
- }
- }
-
- /**
- * 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);
- }
-
- /** Look up and cross-link all field types, etc. */
- private void crossLink() throws DescriptorValidationException {
- for (final Descriptor messageType : messageTypes) {
- messageType.crossLink();
- }
-
- for (final ServiceDescriptor service : services) {
- service.crossLink();
- }
-
- for (final FieldDescriptor extension : extensions) {
- extension.crossLink();
- }
- }
-
- /**
- * 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));
- }
- }
-
- boolean supportsUnknownEnumValue() {
- return getSyntax() == Syntax.PROTO3;
- }
- }
-
- // =================================================================
-
- /** Describes a message type. */
- public static final class Descriptor extends GenericDescriptor {
- /**
- * Get the index of this descriptor within its parent. In other words,
- * given a {@link FileDescriptor} {@code file}, the following is true:
- * <pre>
- * for all i in [0, file.getMessageTypeCount()):
- * file.getMessageType(i).getIndex() == i
- * </pre>
- * Similarly, for a {@link Descriptor} {@code messageType}:
- * <pre>
- * for all i in [0, messageType.getNestedTypeCount()):
- * messageType.getNestedType(i).getIndex() == i
- * </pre>
- */
- public int getIndex() { return index; }
-
- /** Convert the descriptor to its protocol message representation. */
- @Override
- public DescriptorProto toProto() {
- return proto;
- }
-
- /** Get the type's unqualified name. */
- @Override
- public String getName() {
- return proto.getName();
- }
-
- /**
- * Get the type's fully-qualified name, within the proto language's
- * namespace. This differs from the Java name. For example, given this
- * {@code .proto}:
- * <pre>
- * package foo.bar;
- * option java_package = "com.example.protos"
- * message Baz {}
- * </pre>
- * {@code Baz}'s full name is "foo.bar.Baz".
- */
- @Override
- public String getFullName() {
- return fullName;
- }
-
- /** Get the {@link FileDescriptor} containing this descriptor. */
- @Override
- public FileDescriptor getFile() {
- return file;
- }
-
- /** If this is a nested type, get the outer descriptor, otherwise null. */
- public Descriptor getContainingType() { return containingType; }
-
- /** Get the {@code MessageOptions}, defined in {@code descriptor.proto}. */
- public MessageOptions getOptions() { return proto.getOptions(); }
-
- /** Get a list of this message type's fields. */
- public List<FieldDescriptor> getFields() {
- return Collections.unmodifiableList(Arrays.asList(fields));
- }
-
- /** Get a list of this message type's oneofs. */
- public List<OneofDescriptor> getOneofs() {
- return Collections.unmodifiableList(Arrays.asList(oneofs));
- }
-
- /** Get a list of this message type's extensions. */
- public List<FieldDescriptor> getExtensions() {
- return Collections.unmodifiableList(Arrays.asList(extensions));
- }
-
- /** Get a list of message types nested within this one. */
- public List<Descriptor> getNestedTypes() {
- return Collections.unmodifiableList(Arrays.asList(nestedTypes));
- }
-
- /** Get a list of enum types nested within this one. */
- public List<EnumDescriptor> getEnumTypes() {
- return Collections.unmodifiableList(Arrays.asList(enumTypes));
- }
-
- /** Determines if the given field number is an extension. */
- public boolean isExtensionNumber(final int number) {
- for (final DescriptorProto.ExtensionRange range :
- proto.getExtensionRangeList()) {
- if (range.getStart() <= number && number < range.getEnd()) {
- return true;
- }
- }
- return false;
- }
-
- /** Determines if the given field number is reserved. */
- public boolean isReservedNumber(final int number) {
- for (final DescriptorProto.ReservedRange range :
- proto.getReservedRangeList()) {
- if (range.getStart() <= number && number < range.getEnd()) {
- return true;
- }
- }
- return false;
- }
-
- /** Determines if the given field name is reserved. */
- public boolean isReservedName(final String name) {
- if (name == null) {
- throw new NullPointerException();
- }
- for (final String reservedName : proto.getReservedNameList()) {
- if (reservedName.equals(name)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Indicates whether the message can be extended. That is, whether it has
- * any "extensions x to y" ranges declared on it.
- */
- public boolean isExtendable() {
- return proto.getExtensionRangeList().size() != 0;
- }
-
- /**
- * Finds a field by name.
- * @param name The unqualified name of the field (e.g. "foo").
- * @return The field's descriptor, or {@code null} if not found.
- */
- public FieldDescriptor findFieldByName(final String name) {
- final GenericDescriptor result =
- file.pool.findSymbol(fullName + '.' + name);
- if (result != null && result instanceof FieldDescriptor) {
- return (FieldDescriptor)result;
- } else {
- return null;
- }
- }
-
- /**
- * Finds a field by field number.
- * @param number The field number within this message type.
- * @return The field's descriptor, or {@code null} if not found.
- */
- public FieldDescriptor findFieldByNumber(final int number) {
- return file.pool.fieldsByNumber.get(
- new DescriptorPool.DescriptorIntPair(this, number));
- }
-
- /**
- * Finds a nested message type by name.
- * @param name The unqualified name of the nested type (e.g. "Foo").
- * @return The types's descriptor, or {@code null} if not found.
- */
- public Descriptor findNestedTypeByName(final String name) {
- final GenericDescriptor result =
- file.pool.findSymbol(fullName + '.' + name);
- if (result != null && result instanceof Descriptor) {
- return (Descriptor)result;
- } else {
- return null;
- }
- }
-
- /**
- * Finds a nested enum type by name.
- * @param name The unqualified name of the nested type (e.g. "Foo").
- * @return The types's descriptor, or {@code null} if not found.
- */
- public EnumDescriptor findEnumTypeByName(final String name) {
- final GenericDescriptor result =
- file.pool.findSymbol(fullName + '.' + name);
- if (result != null && result instanceof EnumDescriptor) {
- return (EnumDescriptor)result;
- } else {
- return null;
- }
- }
-
- private final int index;
- private DescriptorProto proto;
- private final String fullName;
- private final FileDescriptor file;
- private final Descriptor containingType;
- private final Descriptor[] nestedTypes;
- private final EnumDescriptor[] enumTypes;
- private final FieldDescriptor[] fields;
- private final FieldDescriptor[] extensions;
- private final OneofDescriptor[] oneofs;
-
- // Used to create a placeholder when the type cannot be found.
- Descriptor(final String fullname) throws DescriptorValidationException {
- String name = fullname;
- String packageName = "";
- int pos = fullname.lastIndexOf('.');
- if (pos != -1) {
- name = fullname.substring(pos + 1);
- packageName = fullname.substring(0, pos);
- }
- this.index = 0;
- this.proto = DescriptorProto.newBuilder().setName(name).addExtensionRange(
- DescriptorProto.ExtensionRange.newBuilder().setStart(1)
- .setEnd(536870912).build()).build();
- this.fullName = fullname;
- this.containingType = null;
-
- this.nestedTypes = new Descriptor[0];
- this.enumTypes = new EnumDescriptor[0];
- this.fields = new FieldDescriptor[0];
- this.extensions = new FieldDescriptor[0];
- this.oneofs = new OneofDescriptor[0];
-
- // Create a placeholder FileDescriptor to hold this message.
- this.file = new FileDescriptor(packageName, this);
- }
-
- private Descriptor(final DescriptorProto proto,
- final FileDescriptor file,
- final Descriptor parent,
- final int index)
- throws DescriptorValidationException {
- this.index = index;
- this.proto = proto;
- fullName = computeFullName(file, parent, proto.getName());
- this.file = file;
- containingType = parent;
-
- oneofs = new OneofDescriptor[proto.getOneofDeclCount()];
- for (int i = 0; i < proto.getOneofDeclCount(); i++) {
- oneofs[i] = new OneofDescriptor(
- proto.getOneofDecl(i), file, this, i);
- }
-
- nestedTypes = new Descriptor[proto.getNestedTypeCount()];
- for (int i = 0; i < proto.getNestedTypeCount(); i++) {
- nestedTypes[i] = new Descriptor(
- proto.getNestedType(i), file, this, i);
- }
-
- enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
- for (int i = 0; i < proto.getEnumTypeCount(); i++) {
- enumTypes[i] = new EnumDescriptor(
- proto.getEnumType(i), file, this, i);
- }
-
- fields = new FieldDescriptor[proto.getFieldCount()];
- for (int i = 0; i < proto.getFieldCount(); i++) {
- fields[i] = new FieldDescriptor(
- proto.getField(i), file, this, i, false);
- }
-
- extensions = new FieldDescriptor[proto.getExtensionCount()];
- for (int i = 0; i < proto.getExtensionCount(); i++) {
- extensions[i] = new FieldDescriptor(
- proto.getExtension(i), file, this, i, true);
- }
-
- for (int i = 0; i < proto.getOneofDeclCount(); i++) {
- oneofs[i].fields = new FieldDescriptor[oneofs[i].getFieldCount()];
- oneofs[i].fieldCount = 0;
- }
- for (int i = 0; i < proto.getFieldCount(); i++) {
- OneofDescriptor oneofDescriptor = fields[i].getContainingOneof();
- if (oneofDescriptor != null) {
- oneofDescriptor.fields[oneofDescriptor.fieldCount++] = fields[i];
- }
- }
-
- file.pool.addSymbol(this);
- }
-
- /** Look up and cross-link all field types, etc. */
- private void crossLink() throws DescriptorValidationException {
- for (final Descriptor nestedType : nestedTypes) {
- nestedType.crossLink();
- }
-
- for (final FieldDescriptor field : fields) {
- field.crossLink();
- }
-
- for (final FieldDescriptor extension : extensions) {
- extension.crossLink();
- }
- }
-
- /** See {@link FileDescriptor#setProto}. */
- private void setProto(final DescriptorProto proto) {
- this.proto = proto;
-
- for (int i = 0; i < nestedTypes.length; i++) {
- nestedTypes[i].setProto(proto.getNestedType(i));
- }
-
- for (int i = 0; i < oneofs.length; i++) {
- oneofs[i].setProto(proto.getOneofDecl(i));
- }
-
- for (int i = 0; i < enumTypes.length; i++) {
- enumTypes[i].setProto(proto.getEnumType(i));
- }
-
- for (int i = 0; i < fields.length; i++) {
- fields[i].setProto(proto.getField(i));
- }
-
- for (int i = 0; i < extensions.length; i++) {
- extensions[i].setProto(proto.getExtension(i));
- }
- }
- }
-
- // =================================================================
-
- /** Describes a field of a message type. */
- public static final class FieldDescriptor
- extends GenericDescriptor
- implements Comparable<FieldDescriptor>,
- FieldSet.FieldDescriptorLite<FieldDescriptor> {
- /**
- * Get the index of this descriptor within its parent.
- * @see Descriptors.Descriptor#getIndex()
- */
- public int getIndex() { return index; }
-
- /** Convert the descriptor to its protocol message representation. */
- @Override
- public FieldDescriptorProto toProto() {
- return proto;
- }
-
- /** Get the field's unqualified name. */
- @Override
- public String getName() {
- return proto.getName();
- }
-
- /** Get the field's number. */
- @Override
- public int getNumber() {
- return proto.getNumber();
- }
-
- /**
- * Get the field's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
- */
- @Override
- public String getFullName() {
- return fullName;
- }
-
- /** Get the JSON name of this field. */
- public String getJsonName() {
- return jsonName;
- }
-
- /**
- * Get the field's java type. This is just for convenience. Every
- * {@code FieldDescriptorProto.Type} maps to exactly one Java type.
- */
- public JavaType getJavaType() { return type.getJavaType(); }
-
- /** For internal use only. */
- @Override
- public WireFormat.JavaType getLiteJavaType() {
- return getLiteType().getJavaType();
- }
-
- /** Get the {@code FileDescriptor} containing this descriptor. */
- @Override
- public FileDescriptor getFile() {
- return file;
- }
-
- /** Get the field's declared type. */
- public Type getType() { return type; }
-
- /** For internal use only. */
- @Override
- public WireFormat.FieldType getLiteType() {
- return table[type.ordinal()];
- }
-
- /** For internal use only. */
- public boolean needsUtf8Check() {
- if (type != Type.STRING) {
- return false;
- }
- if (getContainingType().getOptions().getMapEntry()) {
- // Always enforce strict UTF-8 checking for map fields.
- return true;
- }
- if (getFile().getSyntax() == Syntax.PROTO3) {
- return true;
- }
- return getFile().getOptions().getJavaStringCheckUtf8();
- }
-
- public boolean isMapField() {
- return getType() == Type.MESSAGE && isRepeated()
- && getMessageType().getOptions().getMapEntry();
- }
-
- // I'm pretty sure values() constructs a new array every time, since there
- // is nothing stopping the caller from mutating the array. Therefore we
- // make a static copy here.
- private static final WireFormat.FieldType[] table =
- WireFormat.FieldType.values();
-
- /** Is this field declared required? */
- public boolean isRequired() {
- return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED;
- }
-
- /** Is this field declared optional? */
- public boolean isOptional() {
- return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL;
- }
-
- /** Is this field declared repeated? */
- @Override
- public boolean isRepeated() {
- return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
- }
-
- /** Does this field have the {@code [packed = true]} option or is this field
- * packable in proto3 and not explicitly setted to unpacked?
- */
- @Override
- public boolean isPacked() {
- if (!isPackable()) {
- return false;
- }
- if (getFile().getSyntax() == FileDescriptor.Syntax.PROTO2) {
- return getOptions().getPacked();
- } else {
- return !getOptions().hasPacked() || getOptions().getPacked();
- }
- }
-
- /** Can this field be packed? i.e. is it a repeated primitive field? */
- public boolean isPackable() {
- return isRepeated() && getLiteType().isPackable();
- }
-
- /** Returns true if the field had an explicitly-defined default value. */
- public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
-
- /**
- * Returns the field's default value. Valid for all types except for
- * messages and groups. For all other types, the object returned is of
- * the same class that would returned by Message.getField(this).
- */
- public Object getDefaultValue() {
- if (getJavaType() == JavaType.MESSAGE) {
- throw new UnsupportedOperationException(
- "FieldDescriptor.getDefaultValue() called on an embedded message " +
- "field.");
- }
- return defaultValue;
- }
-
- /** Get the {@code FieldOptions}, defined in {@code descriptor.proto}. */
- public FieldOptions getOptions() { return proto.getOptions(); }
-
- /** Is this field an extension? */
- public boolean isExtension() { return proto.hasExtendee(); }
-
- /**
- * Get the field's containing type. For extensions, this is the type being
- * extended, not the location where the extension was defined. See
- * {@link #getExtensionScope()}.
- */
- public Descriptor getContainingType() { return containingType; }
-
- /** Get the field's containing oneof. */
- public OneofDescriptor getContainingOneof() { return containingOneof; }
-
- /**
- * For extensions defined nested within message types, gets the outer
- * type. Not valid for non-extension fields. For example, consider
- * this {@code .proto} file:
- * <pre>
- * message Foo {
- * extensions 1000 to max;
- * }
- * extend Foo {
- * optional int32 baz = 1234;
- * }
- * message Bar {
- * extend Foo {
- * optional int32 qux = 4321;
- * }
- * }
- * </pre>
- * Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}.
- * However, {@code baz}'s extension scope is {@code null} while
- * {@code qux}'s extension scope is {@code Bar}.
- */
- public Descriptor getExtensionScope() {
- if (!isExtension()) {
- throw new UnsupportedOperationException(
- "This field is not an extension.");
- }
- return extensionScope;
- }
-
- /** For embedded message and group fields, gets the field's type. */
- public Descriptor getMessageType() {
- if (getJavaType() != JavaType.MESSAGE) {
- throw new UnsupportedOperationException(
- "This field is not of message type.");
- }
- return messageType;
- }
-
- /** For enum fields, gets the field's type. */
- @Override
- public EnumDescriptor getEnumType() {
- if (getJavaType() != JavaType.ENUM) {
- throw new UnsupportedOperationException(
- "This field is not of enum type.");
- }
- return enumType;
- }
-
- /**
- * Compare with another {@code FieldDescriptor}. This orders fields in
- * "canonical" order, which simply means ascending order by field number.
- * {@code other} must be a field of the same type -- i.e.
- * {@code getContainingType()} must return the same {@code Descriptor} for
- * both fields.
- *
- * @return negative, zero, or positive if {@code this} is less than,
- * equal to, or greater than {@code other}, respectively.
- */
- @Override
- public int compareTo(final FieldDescriptor other) {
- if (other.containingType != containingType) {
- throw new IllegalArgumentException(
- "FieldDescriptors can only be compared to other FieldDescriptors " +
- "for fields of the same message type.");
- }
- return getNumber() - other.getNumber();
- }
-
- @Override
- public String toString() {
- return getFullName();
- }
-
- private final int index;
-
- private FieldDescriptorProto proto;
- private final String fullName;
- private final String jsonName;
- private final FileDescriptor file;
- private final Descriptor extensionScope;
-
- // Possibly initialized during cross-linking.
- private Type type;
- private Descriptor containingType;
- private Descriptor messageType;
- private OneofDescriptor containingOneof;
- private EnumDescriptor enumType;
- private Object defaultValue;
-
- public enum Type {
- DOUBLE (JavaType.DOUBLE ),
- FLOAT (JavaType.FLOAT ),
- INT64 (JavaType.LONG ),
- UINT64 (JavaType.LONG ),
- INT32 (JavaType.INT ),
- FIXED64 (JavaType.LONG ),
- FIXED32 (JavaType.INT ),
- BOOL (JavaType.BOOLEAN ),
- STRING (JavaType.STRING ),
- GROUP (JavaType.MESSAGE ),
- MESSAGE (JavaType.MESSAGE ),
- BYTES (JavaType.BYTE_STRING),
- UINT32 (JavaType.INT ),
- ENUM (JavaType.ENUM ),
- SFIXED32(JavaType.INT ),
- SFIXED64(JavaType.LONG ),
- SINT32 (JavaType.INT ),
- SINT64 (JavaType.LONG );
-
- Type(final JavaType javaType) {
- this.javaType = javaType;
- }
-
- private JavaType javaType;
-
- public FieldDescriptorProto.Type toProto() {
- return FieldDescriptorProto.Type.forNumber(ordinal() + 1);
- }
- public JavaType getJavaType() { return javaType; }
-
- public static Type valueOf(final FieldDescriptorProto.Type type) {
- return values()[type.getNumber() - 1];
- }
- }
-
- static {
- // Refuse to init if someone added a new declared type.
- if (Type.values().length != FieldDescriptorProto.Type.values().length) {
- throw new RuntimeException(""
- + "descriptor.proto has a new declared type but Descriptors.java "
- + "wasn't updated.");
- }
- }
-
- public enum JavaType {
- INT(0),
- LONG(0L),
- FLOAT(0F),
- DOUBLE(0D),
- BOOLEAN(false),
- STRING(""),
- BYTE_STRING(ByteString.EMPTY),
- ENUM(null),
- MESSAGE(null);
-
- JavaType(final Object defaultDefault) {
- this.defaultDefault = defaultDefault;
- }
-
- /**
- * The default default value for fields of this type, if it's a primitive
- * type. This is meant for use inside this file only, hence is private.
- */
- private final Object defaultDefault;
- }
-
- // This method should match exactly with the ToJsonName() function in C++
- // descriptor.cc.
- private static String fieldNameToJsonName(String name) {
- StringBuilder result = new StringBuilder(name.length());
- boolean isNextUpperCase = false;
- for (int i = 0; i < name.length(); i++) {
- Character ch = name.charAt(i);
- if (ch == '_') {
- isNextUpperCase = true;
- } else if (isNextUpperCase) {
- result.append(Character.toUpperCase(ch));
- isNextUpperCase = false;
- } else {
- result.append(ch);
- }
- }
- return result.toString();
- }
-
- private FieldDescriptor(final FieldDescriptorProto proto,
- final FileDescriptor file,
- final Descriptor parent,
- final int index,
- final boolean isExtension)
- throws DescriptorValidationException {
- this.index = index;
- this.proto = proto;
- fullName = computeFullName(file, parent, proto.getName());
- this.file = file;
- if (proto.hasJsonName()) {
- jsonName = proto.getJsonName();
- } else {
- jsonName = fieldNameToJsonName(proto.getName());
- }
-
- if (proto.hasType()) {
- type = Type.valueOf(proto.getType());
- }
-
- if (getNumber() <= 0) {
- throw new DescriptorValidationException(this,
- "Field numbers must be positive integers.");
- }
-
- if (isExtension) {
- if (!proto.hasExtendee()) {
- throw new DescriptorValidationException(this,
- "FieldDescriptorProto.extendee not set for extension field.");
- }
- containingType = null; // Will be filled in when cross-linking
- if (parent != null) {
- extensionScope = parent;
- } else {
- extensionScope = null;
- }
-
- if (proto.hasOneofIndex()) {
- throw new DescriptorValidationException(this,
- "FieldDescriptorProto.oneof_index set for extension field.");
- }
- containingOneof = null;
- } else {
- if (proto.hasExtendee()) {
- throw new DescriptorValidationException(this,
- "FieldDescriptorProto.extendee set for non-extension field.");
- }
- containingType = parent;
-
- if (proto.hasOneofIndex()) {
- if (proto.getOneofIndex() < 0 ||
- proto.getOneofIndex() >= parent.toProto().getOneofDeclCount()) {
- throw new DescriptorValidationException(this,
- "FieldDescriptorProto.oneof_index is out of range for type "
- + parent.getName());
- }
- containingOneof = parent.getOneofs().get(proto.getOneofIndex());
- containingOneof.fieldCount++;
- } else {
- containingOneof = null;
- }
- extensionScope = null;
- }
-
- file.pool.addSymbol(this);
- }
-
- /** Look up and cross-link all field types, etc. */
- private void crossLink() throws DescriptorValidationException {
- if (proto.hasExtendee()) {
- final GenericDescriptor extendee =
- file.pool.lookupSymbol(proto.getExtendee(), this,
- DescriptorPool.SearchFilter.TYPES_ONLY);
- if (!(extendee instanceof Descriptor)) {
- throw new DescriptorValidationException(this,
- '\"' + proto.getExtendee() + "\" is not a message type.");
- }
- containingType = (Descriptor)extendee;
-
- if (!getContainingType().isExtensionNumber(getNumber())) {
- throw new DescriptorValidationException(this,
- '\"' + getContainingType().getFullName() +
- "\" does not declare " + getNumber() +
- " as an extension number.");
- }
- }
-
- if (proto.hasTypeName()) {
- final GenericDescriptor typeDescriptor =
- file.pool.lookupSymbol(proto.getTypeName(), this,
- DescriptorPool.SearchFilter.TYPES_ONLY);
-
- if (!proto.hasType()) {
- // Choose field type based on symbol.
- if (typeDescriptor instanceof Descriptor) {
- type = Type.MESSAGE;
- } else if (typeDescriptor instanceof EnumDescriptor) {
- type = Type.ENUM;
- } else {
- throw new DescriptorValidationException(this,
- '\"' + proto.getTypeName() + "\" is not a type.");
- }
- }
-
- if (getJavaType() == JavaType.MESSAGE) {
- if (!(typeDescriptor instanceof Descriptor)) {
- throw new DescriptorValidationException(this,
- '\"' + proto.getTypeName() + "\" is not a message type.");
- }
- messageType = (Descriptor)typeDescriptor;
-
- if (proto.hasDefaultValue()) {
- throw new DescriptorValidationException(this,
- "Messages can't have default values.");
- }
- } else if (getJavaType() == JavaType.ENUM) {
- if (!(typeDescriptor instanceof EnumDescriptor)) {
- throw new DescriptorValidationException(this,
- '\"' + proto.getTypeName() + "\" is not an enum type.");
- }
- enumType = (EnumDescriptor)typeDescriptor;
- } else {
- throw new DescriptorValidationException(this,
- "Field with primitive type has type_name.");
- }
- } else {
- if (getJavaType() == JavaType.MESSAGE ||
- getJavaType() == JavaType.ENUM) {
- throw new DescriptorValidationException(this,
- "Field with message or enum type missing type_name.");
- }
- }
-
- // Only repeated primitive fields may be packed.
- if (proto.getOptions().getPacked() && !isPackable()) {
- throw new DescriptorValidationException(this,
- "[packed = true] can only be specified for repeated primitive " +
- "fields.");
- }
-
- // We don't attempt to parse the default value until here because for
- // enums we need the enum type's descriptor.
- if (proto.hasDefaultValue()) {
- if (isRepeated()) {
- throw new DescriptorValidationException(this,
- "Repeated fields cannot have default values.");
- }
-
- try {
- switch (getType()) {
- case INT32:
- case SINT32:
- case SFIXED32:
- defaultValue = TextFormat.parseInt32(proto.getDefaultValue());
- break;
- case UINT32:
- case FIXED32:
- defaultValue = TextFormat.parseUInt32(proto.getDefaultValue());
- break;
- case INT64:
- case SINT64:
- case SFIXED64:
- defaultValue = TextFormat.parseInt64(proto.getDefaultValue());
- break;
- case UINT64:
- case FIXED64:
- defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
- break;
- case FLOAT:
- if (proto.getDefaultValue().equals("inf")) {
- defaultValue = Float.POSITIVE_INFINITY;
- } else if (proto.getDefaultValue().equals("-inf")) {
- defaultValue = Float.NEGATIVE_INFINITY;
- } else if (proto.getDefaultValue().equals("nan")) {
- defaultValue = Float.NaN;
- } else {
- defaultValue = Float.valueOf(proto.getDefaultValue());
- }
- break;
- case DOUBLE:
- if (proto.getDefaultValue().equals("inf")) {
- defaultValue = Double.POSITIVE_INFINITY;
- } else if (proto.getDefaultValue().equals("-inf")) {
- defaultValue = Double.NEGATIVE_INFINITY;
- } else if (proto.getDefaultValue().equals("nan")) {
- defaultValue = Double.NaN;
- } else {
- defaultValue = Double.valueOf(proto.getDefaultValue());
- }
- break;
- case BOOL:
- defaultValue = Boolean.valueOf(proto.getDefaultValue());
- break;
- case STRING:
- defaultValue = proto.getDefaultValue();
- break;
- case BYTES:
- try {
- defaultValue =
- TextFormat.unescapeBytes(proto.getDefaultValue());
- } catch (TextFormat.InvalidEscapeSequenceException e) {
- throw new DescriptorValidationException(this,
- "Couldn't parse default value: " + e.getMessage(), e);
- }
- break;
- case ENUM:
- defaultValue = enumType.findValueByName(proto.getDefaultValue());
- if (defaultValue == null) {
- throw new DescriptorValidationException(this,
- "Unknown enum default value: \"" +
- proto.getDefaultValue() + '\"');
- }
- break;
- case MESSAGE:
- case GROUP:
- throw new DescriptorValidationException(this,
- "Message type had default value.");
- }
- } catch (NumberFormatException e) {
- throw new DescriptorValidationException(this,
- "Could not parse default value: \"" +
- proto.getDefaultValue() + '\"', e);
- }
- } else {
- // Determine the default default for this field.
- if (isRepeated()) {
- defaultValue = Collections.emptyList();
- } else {
- switch (getJavaType()) {
- case ENUM:
- // We guarantee elsewhere that an enum type always has at least
- // one possible value.
- defaultValue = enumType.getValues().get(0);
- break;
- case MESSAGE:
- defaultValue = null;
- break;
- default:
- defaultValue = getJavaType().defaultDefault;
- break;
- }
- }
- }
-
- if (!isExtension()) {
- file.pool.addFieldByNumber(this);
- }
-
- if (containingType != null &&
- containingType.getOptions().getMessageSetWireFormat()) {
- if (isExtension()) {
- if (!isOptional() || getType() != Type.MESSAGE) {
- throw new DescriptorValidationException(this,
- "Extensions of MessageSets must be optional messages.");
- }
- } else {
- throw new DescriptorValidationException(this,
- "MessageSets cannot have fields, only extensions.");
- }
- }
- }
-
- /** See {@link FileDescriptor#setProto}. */
- private void setProto(final FieldDescriptorProto proto) {
- this.proto = proto;
- }
-
- /**
- * For internal use only. This is to satisfy the FieldDescriptorLite
- * interface.
- */
- @Override
- public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
- // FieldDescriptors are only used with non-lite messages so we can just
- // down-cast and call mergeFrom directly.
- return ((Message.Builder) to).mergeFrom((Message) from);
- }
-
- }
-
- // =================================================================
-
- /** Describes an enum type. */
- public static final class EnumDescriptor extends GenericDescriptor
- implements Internal.EnumLiteMap<EnumValueDescriptor> {
- /**
- * Get the index of this descriptor within its parent.
- * @see Descriptors.Descriptor#getIndex()
- */
- public int getIndex() { return index; }
-
- /** Convert the descriptor to its protocol message representation. */
- @Override
- public EnumDescriptorProto toProto() {
- return proto;
- }
-
- /** Get the type's unqualified name. */
- @Override
- public String getName() {
- return proto.getName();
- }
-
- /**
- * Get the type's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
- */
- @Override
- public String getFullName() {
- return fullName;
- }
-
- /** Get the {@link FileDescriptor} containing this descriptor. */
- @Override
- public FileDescriptor getFile() {
- return file;
- }
-
- /** If this is a nested type, get the outer descriptor, otherwise null. */
- public Descriptor getContainingType() { return containingType; }
-
- /** Get the {@code EnumOptions}, defined in {@code descriptor.proto}. */
- public EnumOptions getOptions() { return proto.getOptions(); }
-
- /** Get a list of defined values for this enum. */
- public List<EnumValueDescriptor> getValues() {
- return Collections.unmodifiableList(Arrays.asList(values));
- }
-
- /**
- * Find an enum value by name.
- * @param name The unqualified name of the value (e.g. "FOO").
- * @return the value's descriptor, or {@code null} if not found.
- */
- public EnumValueDescriptor findValueByName(final String name) {
- final GenericDescriptor result =
- file.pool.findSymbol(fullName + '.' + name);
- if (result != null && result instanceof EnumValueDescriptor) {
- return (EnumValueDescriptor)result;
- } else {
- return null;
- }
- }
-
- /**
- * Find an enum value by number. If multiple enum values have the same
- * number, this returns the first defined value with that number.
- * @param number The value's number.
- * @return the value's descriptor, or {@code null} if not found.
- */
- @Override
- public EnumValueDescriptor findValueByNumber(final int number) {
- return file.pool.enumValuesByNumber.get(
- new DescriptorPool.DescriptorIntPair(this, number));
- }
-
- /**
- * Get the enum value for a number. If no enum value has this number,
- * construct an EnumValueDescriptor for it.
- */
- public EnumValueDescriptor findValueByNumberCreatingIfUnknown(final int number) {
- EnumValueDescriptor result = findValueByNumber(number);
- if (result != null) {
- return result;
- }
- // The number represents an unknown enum value.
- synchronized (this) {
- // Descriptors are compared by object identity so for the same number
- // we need to return the same EnumValueDescriptor object. This means
- // we have to store created EnumValueDescriptors. However, as there
- // are potentially 2G unknown enum values, storing all of these
- // objects persistently will consume lots of memory for long-running
- // services and it's also unnecessary as not many EnumValueDescriptors
- // will be used at the same time.
- //
- // To solve the problem we take advantage of Java's weak references and
- // rely on gc to release unused descriptors.
- //
- // Here is how it works:
- // * We store unknown EnumValueDescriptors in a WeakHashMap with the
- // value being a weak reference to the descriptor.
- // * The descriptor holds a strong reference to the key so as long
- // as the EnumValueDescriptor is in use, the key will be there
- // and the corresponding map entry will be there. Following-up
- // queries with the same number will return the same descriptor.
- // * If the user no longer uses an unknown EnumValueDescriptor,
- // it will be gc-ed since we only hold a weak reference to it in
- // the map. The key in the corresponding map entry will also be
- // gc-ed as the only strong reference to it is in the descriptor
- // which is just gc-ed. With the key being gone WeakHashMap will
- // then remove the whole entry. This way unknown descriptors will
- // be freed automatically and we don't need to do anything to
- // clean-up unused map entries.
-
- // Note: We must use "new Integer(number)" here because we don't want
- // these Integer objects to be cached.
- Integer key = new Integer(number);
- WeakReference<EnumValueDescriptor> reference = unknownValues.get(key);
- if (reference != null) {
- result = reference.get();
- }
- if (result == null) {
- result = new EnumValueDescriptor(file, this, key);
- unknownValues.put(key, new WeakReference<EnumValueDescriptor>(result));
- }
- }
- return result;
- }
-
- // Used in tests only.
- int getUnknownEnumValueDescriptorCount() {
- return unknownValues.size();
- }
-
- private final int index;
- private EnumDescriptorProto proto;
- private final String fullName;
- private final FileDescriptor file;
- private final Descriptor containingType;
- private EnumValueDescriptor[] values;
- private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
- new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
-
- private EnumDescriptor(final EnumDescriptorProto proto,
- final FileDescriptor file,
- final Descriptor parent,
- final int index)
- throws DescriptorValidationException {
- this.index = index;
- this.proto = proto;
- fullName = computeFullName(file, parent, proto.getName());
- this.file = file;
- containingType = parent;
-
- if (proto.getValueCount() == 0) {
- // We cannot allow enums with no values because this would mean there
- // would be no valid default value for fields of this type.
- throw new DescriptorValidationException(this,
- "Enums must contain at least one value.");
- }
-
- values = new EnumValueDescriptor[proto.getValueCount()];
- for (int i = 0; i < proto.getValueCount(); i++) {
- values[i] = new EnumValueDescriptor(
- proto.getValue(i), file, this, i);
- }
-
- file.pool.addSymbol(this);
- }
-
- /** See {@link FileDescriptor#setProto}. */
- private void setProto(final EnumDescriptorProto proto) {
- this.proto = proto;
-
- for (int i = 0; i < values.length; i++) {
- values[i].setProto(proto.getValue(i));
- }
- }
- }
-
- // =================================================================
-
- /**
- * Describes one value within an enum type. Note that multiple defined
- * values may have the same number. In generated Java code, all values
- * with the same number after the first become aliases of the first.
- * However, they still have independent EnumValueDescriptors.
- */
- public static final class EnumValueDescriptor extends GenericDescriptor
- implements Internal.EnumLite {
- /**
- * Get the index of this descriptor within its parent.
- * @see Descriptors.Descriptor#getIndex()
- */
- public int getIndex() { return index; }
-
- /** Convert the descriptor to its protocol message representation. */
- @Override
- public EnumValueDescriptorProto toProto() {
- return proto;
- }
-
- /** Get the value's unqualified name. */
- @Override
- public String getName() {
- return proto.getName();
- }
-
- /** Get the value's number. */
- @Override
- public int getNumber() {
- return proto.getNumber();
- }
-
- @Override
- public String toString() { return proto.getName(); }
-
- /**
- * Get the value's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
- */
- @Override
- public String getFullName() {
- return fullName;
- }
-
- /** Get the {@link FileDescriptor} containing this descriptor. */
- @Override
- public FileDescriptor getFile() {
- return file;
- }
-
- /** Get the value's enum type. */
- public EnumDescriptor getType() { return type; }
-
- /**
- * Get the {@code EnumValueOptions}, defined in {@code descriptor.proto}.
- */
- public EnumValueOptions getOptions() { return proto.getOptions(); }
-
- private final int index;
- private EnumValueDescriptorProto proto;
- private final String fullName;
- private final FileDescriptor file;
- private final EnumDescriptor type;
-
- private EnumValueDescriptor(final EnumValueDescriptorProto proto,
- final FileDescriptor file,
- final EnumDescriptor parent,
- final int index)
- throws DescriptorValidationException {
- this.index = index;
- this.proto = proto;
- this.file = file;
- type = parent;
-
- fullName = parent.getFullName() + '.' + proto.getName();
-
- file.pool.addSymbol(this);
- file.pool.addEnumValueByNumber(this);
- }
-
- private Integer number;
- // Create an unknown enum value.
- private EnumValueDescriptor(
- final FileDescriptor file,
- final EnumDescriptor parent,
- final Integer number) {
- String name = "UNKNOWN_ENUM_VALUE_" + parent.getName() + "_" + number;
- EnumValueDescriptorProto proto = EnumValueDescriptorProto
- .newBuilder().setName(name).setNumber(number).build();
- this.index = -1;
- this.proto = proto;
- this.file = file;
- this.type = parent;
- this.fullName = parent.getFullName() + '.' + proto.getName();
- this.number = number;
-
- // Don't add this descriptor into pool.
- }
-
- /** See {@link FileDescriptor#setProto}. */
- private void setProto(final EnumValueDescriptorProto proto) {
- this.proto = proto;
- }
- }
-
- // =================================================================
-
- /** Describes a service type. */
- public static final class ServiceDescriptor extends GenericDescriptor {
- /**
- * Get the index of this descriptor within its parent.
- * * @see Descriptors.Descriptor#getIndex()
- */
- public int getIndex() { return index; }
-
- /** Convert the descriptor to its protocol message representation. */
- @Override
- public ServiceDescriptorProto toProto() {
- return proto;
- }
-
- /** Get the type's unqualified name. */
- @Override
- public String getName() {
- return proto.getName();
- }
-
- /**
- * Get the type's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
- */
- @Override
- public String getFullName() {
- return fullName;
- }
-
- /** Get the {@link FileDescriptor} containing this descriptor. */
- @Override
- public FileDescriptor getFile() {
- return file;
- }
-
- /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */
- public ServiceOptions getOptions() { return proto.getOptions(); }
-
- /** Get a list of methods for this service. */
- public List<MethodDescriptor> getMethods() {
- return Collections.unmodifiableList(Arrays.asList(methods));
- }
-
- /**
- * Find a method by name.
- * @param name The unqualified name of the method (e.g. "Foo").
- * @return the method's descriptor, or {@code null} if not found.
- */
- public MethodDescriptor findMethodByName(final String name) {
- final GenericDescriptor result =
- file.pool.findSymbol(fullName + '.' + name);
- if (result != null && result instanceof MethodDescriptor) {
- return (MethodDescriptor)result;
- } else {
- return null;
- }
- }
-
- private final int index;
- private ServiceDescriptorProto proto;
- private final String fullName;
- private final FileDescriptor file;
- private MethodDescriptor[] methods;
-
- private ServiceDescriptor(final ServiceDescriptorProto proto,
- final FileDescriptor file,
- final int index)
- throws DescriptorValidationException {
- this.index = index;
- this.proto = proto;
- fullName = computeFullName(file, null, proto.getName());
- this.file = file;
-
- methods = new MethodDescriptor[proto.getMethodCount()];
- for (int i = 0; i < proto.getMethodCount(); i++) {
- methods[i] = new MethodDescriptor(
- proto.getMethod(i), file, this, i);
- }
-
- file.pool.addSymbol(this);
- }
-
- private void crossLink() throws DescriptorValidationException {
- for (final MethodDescriptor method : methods) {
- method.crossLink();
- }
- }
-
- /** See {@link FileDescriptor#setProto}. */
- private void setProto(final ServiceDescriptorProto proto) {
- this.proto = proto;
-
- for (int i = 0; i < methods.length; i++) {
- methods[i].setProto(proto.getMethod(i));
- }
- }
- }
-
- // =================================================================
-
- /**
- * Describes one method within a service type.
- */
- public static final class MethodDescriptor extends GenericDescriptor {
- /**
- * Get the index of this descriptor within its parent.
- * * @see Descriptors.Descriptor#getIndex()
- */
- public int getIndex() { return index; }
-
- /** Convert the descriptor to its protocol message representation. */
- @Override
- public MethodDescriptorProto toProto() {
- return proto;
- }
-
- /** Get the method's unqualified name. */
- @Override
- public String getName() {
- return proto.getName();
- }
-
- /**
- * Get the method's fully-qualified name.
- * @see Descriptors.Descriptor#getFullName()
- */
- @Override
- public String getFullName() {
- return fullName;
- }
-
- /** Get the {@link FileDescriptor} containing this descriptor. */
- @Override
- public FileDescriptor getFile() {
- return file;
- }
-
- /** Get the method's service type. */
- public ServiceDescriptor getService() { return service; }
-
- /** Get the method's input type. */
- public Descriptor getInputType() { return inputType; }
-
- /** Get the method's output type. */
- public Descriptor getOutputType() { return outputType; }
-
- /**
- * Get the {@code MethodOptions}, defined in {@code descriptor.proto}.
- */
- public MethodOptions getOptions() { return proto.getOptions(); }
-
- private final int index;
- private MethodDescriptorProto proto;
- private final String fullName;
- private final FileDescriptor file;
- private final ServiceDescriptor service;
-
- // Initialized during cross-linking.
- private Descriptor inputType;
- private Descriptor outputType;
-
- private MethodDescriptor(final MethodDescriptorProto proto,
- final FileDescriptor file,
- final ServiceDescriptor parent,
- final int index)
- throws DescriptorValidationException {
- this.index = index;
- this.proto = proto;
- this.file = file;
- service = parent;
-
- fullName = parent.getFullName() + '.' + proto.getName();
-
- file.pool.addSymbol(this);
- }
-
- private void crossLink() throws DescriptorValidationException {
- final GenericDescriptor input =
- file.pool.lookupSymbol(proto.getInputType(), this,
- DescriptorPool.SearchFilter.TYPES_ONLY);
- if (!(input instanceof Descriptor)) {
- throw new DescriptorValidationException(this,
- '\"' + proto.getInputType() + "\" is not a message type.");
- }
- inputType = (Descriptor)input;
-
- final GenericDescriptor output =
- file.pool.lookupSymbol(proto.getOutputType(), this,
- DescriptorPool.SearchFilter.TYPES_ONLY);
- if (!(output instanceof Descriptor)) {
- throw new DescriptorValidationException(this,
- '\"' + proto.getOutputType() + "\" is not a message type.");
- }
- outputType = (Descriptor)output;
- }
-
- /** See {@link FileDescriptor#setProto}. */
- private void setProto(final MethodDescriptorProto proto) {
- this.proto = proto;
- }
- }
-
- // =================================================================
-
- private static String computeFullName(final FileDescriptor file,
- final Descriptor parent,
- final String name) {
- if (parent != null) {
- return parent.getFullName() + '.' + name;
- } else if (file.getPackage().length() > 0) {
- return file.getPackage() + '.' + name;
- } else {
- return name;
- }
- }
-
- // =================================================================
-
- /**
- * All descriptors implement this to make it easier to implement tools like
- * {@code DescriptorPool}.<p>
- *
- * This class is public so that the methods it exposes can be called from
- * outside of this package. However, it should only be subclassed from
- * nested classes of Descriptors.
- */
- public abstract static class GenericDescriptor {
- public abstract Message toProto();
- public abstract String getName();
- public abstract String getFullName();
- public abstract FileDescriptor getFile();
- }
-
- /**
- * Thrown when building descriptors fails because the source DescriptorProtos
- * are not valid.
- */
- public static class DescriptorValidationException extends Exception {
- private static final long serialVersionUID = 5750205775490483148L;
-
- /** Gets the full name of the descriptor where the error occurred. */
- public String getProblemSymbolName() { return name; }
-
- /**
- * Gets the protocol message representation of the invalid descriptor.
- */
- public Message getProblemProto() { return proto; }
-
- /**
- * Gets a human-readable description of the error.
- */
- public String getDescription() { return description; }
-
- private final String name;
- private final Message proto;
- private final String description;
-
- private DescriptorValidationException(
- final GenericDescriptor problemDescriptor,
- final String description) {
- super(problemDescriptor.getFullName() + ": " + description);
-
- // Note that problemDescriptor may be partially uninitialized, so we
- // don't want to expose it directly to the user. So, we only provide
- // the name and the original proto.
- name = problemDescriptor.getFullName();
- proto = problemDescriptor.toProto();
- this.description = description;
- }
-
- private DescriptorValidationException(
- final GenericDescriptor problemDescriptor,
- final String description,
- final Throwable cause) {
- this(problemDescriptor, description);
- initCause(cause);
- }
-
- private DescriptorValidationException(
- final FileDescriptor problemDescriptor,
- final String description) {
- super(problemDescriptor.getName() + ": " + description);
-
- // Note that problemDescriptor may be partially uninitialized, so we
- // don't want to expose it directly to the user. So, we only provide
- // the name and the original proto.
- name = problemDescriptor.getName();
- proto = problemDescriptor.toProto();
- this.description = description;
- }
- }
-
- // =================================================================
-
- /**
- * A private helper class which contains lookup tables containing all the
- * descriptors defined in a particular file.
- */
- private static final class DescriptorPool {
-
- /** Defines what subclass of descriptors to search in the descriptor pool.
- */
- enum SearchFilter {
- TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS
- }
-
- DescriptorPool(final FileDescriptor[] dependencies,
- boolean allowUnknownDependencies) {
- this.dependencies = new HashSet<FileDescriptor>();
- this.allowUnknownDependencies = allowUnknownDependencies;
-
- for (int i = 0; i < dependencies.length; i++) {
- this.dependencies.add(dependencies[i]);
- importPublicDependencies(dependencies[i]);
- }
-
- for (final FileDescriptor dependency : this.dependencies) {
- try {
- addPackage(dependency.getPackage(), dependency);
- } catch (DescriptorValidationException e) {
- // Can't happen, because addPackage() only fails when the name
- // conflicts with a non-package, but we have not yet added any
- // non-packages at this point.
- throw new AssertionError(e);
- }
- }
- }
-
- /** Find and put public dependencies of the file into dependencies set.*/
- private void importPublicDependencies(final FileDescriptor file) {
- for (FileDescriptor dependency : file.getPublicDependencies()) {
- if (dependencies.add(dependency)) {
- importPublicDependencies(dependency);
- }
- }
- }
-
- private final Set<FileDescriptor> dependencies;
- private boolean allowUnknownDependencies;
-
- private final Map<String, GenericDescriptor> descriptorsByName =
- new HashMap<String, GenericDescriptor>();
- private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
- new HashMap<DescriptorIntPair, FieldDescriptor>();
- private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber
- = new HashMap<DescriptorIntPair, EnumValueDescriptor>();
-
- /** Find a generic descriptor by fully-qualified name. */
- GenericDescriptor findSymbol(final String fullName) {
- return findSymbol(fullName, SearchFilter.ALL_SYMBOLS);
- }
-
- /** Find a descriptor by fully-qualified name and given option to only
- * search valid field type descriptors.
- */
- GenericDescriptor findSymbol(final String fullName,
- final SearchFilter filter) {
- GenericDescriptor result = descriptorsByName.get(fullName);
- if (result != null) {
- if ((filter==SearchFilter.ALL_SYMBOLS) ||
- ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
- ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
- return result;
- }
- }
-
- for (final FileDescriptor dependency : dependencies) {
- result = dependency.pool.descriptorsByName.get(fullName);
- if (result != null) {
- if ((filter==SearchFilter.ALL_SYMBOLS) ||
- ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
- ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
- return result;
- }
- }
- }
-
- return null;
- }
-
- /** Checks if the descriptor is a valid type for a message field. */
- boolean isType(GenericDescriptor descriptor) {
- return (descriptor instanceof Descriptor) ||
- (descriptor instanceof EnumDescriptor);
- }
-
- /** Checks if the descriptor is a valid namespace type. */
- boolean isAggregate(GenericDescriptor descriptor) {
- return (descriptor instanceof Descriptor) ||
- (descriptor instanceof EnumDescriptor) ||
- (descriptor instanceof PackageDescriptor) ||
- (descriptor instanceof ServiceDescriptor);
- }
-
- /**
- * Look up a type descriptor by name, relative to some other descriptor.
- * The name may be fully-qualified (with a leading '.'),
- * partially-qualified, or unqualified. C++-like name lookup semantics
- * are used to search for the matching descriptor.
- */
- GenericDescriptor lookupSymbol(final String name,
- final GenericDescriptor relativeTo,
- final DescriptorPool.SearchFilter filter)
- throws DescriptorValidationException {
- // TODO(kenton): This could be optimized in a number of ways.
-
- GenericDescriptor result;
- String fullname;
- if (name.startsWith(".")) {
- // Fully-qualified name.
- fullname = name.substring(1);
- result = findSymbol(fullname, filter);
- } else {
- // If "name" is a compound identifier, we want to search for the
- // first component of it, then search within it for the rest.
- // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
- // defined in multiple parent scopes, we only want to find "Bar.baz" in
- // the innermost one. E.g., the following should produce an error:
- // message Bar { message Baz {} }
- // message Foo {
- // message Bar {
- // }
- // optional Bar.Baz baz = 1;
- // }
- // So, we look for just "Foo" first, then look for "Bar.baz" within it
- // if found.
- final int firstPartLength = name.indexOf('.');
- final String firstPart;
- if (firstPartLength == -1) {
- firstPart = name;
- } else {
- firstPart = name.substring(0, firstPartLength);
- }
-
- // We will search each parent scope of "relativeTo" looking for the
- // symbol.
- final StringBuilder scopeToTry =
- new StringBuilder(relativeTo.getFullName());
-
- while (true) {
- // Chop off the last component of the scope.
- final int dotpos = scopeToTry.lastIndexOf(".");
- if (dotpos == -1) {
- fullname = name;
- result = findSymbol(name, filter);
- break;
- } else {
- scopeToTry.setLength(dotpos + 1);
-
- // Append firstPart and try to find
- scopeToTry.append(firstPart);
- result = findSymbol(scopeToTry.toString(),
- DescriptorPool.SearchFilter.AGGREGATES_ONLY);
-
- if (result != null) {
- if (firstPartLength != -1) {
- // We only found the first part of the symbol. Now look for
- // the whole thing. If this fails, we *don't* want to keep
- // searching parent scopes.
- scopeToTry.setLength(dotpos + 1);
- scopeToTry.append(name);
- result = findSymbol(scopeToTry.toString(), filter);
- }
- fullname = scopeToTry.toString();
- break;
- }
-
- // Not found. Remove the name so we can try again.
- scopeToTry.setLength(dotpos);
- }
- }
- }
-
- if (result == null) {
- if (allowUnknownDependencies && filter == SearchFilter.TYPES_ONLY) {
- logger.warning("The descriptor for message type \"" + name +
- "\" can not be found and a placeholder is created for it");
- // We create a dummy message descriptor here regardless of the
- // expected type. If the type should be message, this dummy
- // descriptor will work well and if the type should be enum, a
- // DescriptorValidationException will be thrown latter. In either
- // case, the code works as expected: we allow unknown message types
- // but not unknwon enum types.
- result = new Descriptor(fullname);
- // Add the placeholder file as a dependency so we can find the
- // placeholder symbol when resolving other references.
- this.dependencies.add(result.getFile());
- return result;
- } else {
- throw new DescriptorValidationException(relativeTo,
- '\"' + name + "\" is not defined.");
- }
- } else {
- return result;
- }
- }
-
- /**
- * Adds a symbol to the symbol table. If a symbol with the same name
- * already exists, throws an error.
- */
- void addSymbol(final GenericDescriptor descriptor)
- throws DescriptorValidationException {
- validateSymbolName(descriptor);
-
- final String fullName = descriptor.getFullName();
- final int dotpos = fullName.lastIndexOf('.');
-
- final GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
- if (old != null) {
- descriptorsByName.put(fullName, old);
-
- if (descriptor.getFile() == old.getFile()) {
- if (dotpos == -1) {
- throw new DescriptorValidationException(descriptor,
- '\"' + fullName + "\" is already defined.");
- } else {
- throw new DescriptorValidationException(descriptor,
- '\"' + fullName.substring(dotpos + 1) +
- "\" is already defined in \"" +
- fullName.substring(0, dotpos) + "\".");
- }
- } else {
- throw new DescriptorValidationException(descriptor,
- '\"' + fullName + "\" is already defined in file \"" +
- old.getFile().getName() + "\".");
- }
- }
- }
-
- /**
- * Represents a package in the symbol table. We use PackageDescriptors
- * just as placeholders so that someone cannot define, say, a message type
- * that has the same name as an existing package.
- */
- private static final class PackageDescriptor extends GenericDescriptor {
- @Override
- public Message toProto() {
- return file.toProto();
- }
- @Override
- public String getName() {
- return name;
- }
- @Override
- public String getFullName() {
- return fullName;
- }
- @Override
- public FileDescriptor getFile() {
- return file;
- }
-
- PackageDescriptor(final String name, final String fullName,
- final FileDescriptor file) {
- this.file = file;
- this.fullName = fullName;
- this.name = name;
- }
-
- private final String name;
- private final String fullName;
- private final FileDescriptor file;
- }
-
- /**
- * Adds a package to the symbol tables. If a package by the same name
- * already exists, that is fine, but if some other kind of symbol exists
- * under the same name, an exception is thrown. If the package has
- * multiple components, this also adds the parent package(s).
- */
- void addPackage(final String fullName, final FileDescriptor file)
- throws DescriptorValidationException {
- final int dotpos = fullName.lastIndexOf('.');
- final String name;
- if (dotpos == -1) {
- name = fullName;
- } else {
- addPackage(fullName.substring(0, dotpos), file);
- name = fullName.substring(dotpos + 1);
- }
-
- final GenericDescriptor old =
- descriptorsByName.put(fullName,
- new PackageDescriptor(name, fullName, file));
- if (old != null) {
- descriptorsByName.put(fullName, old);
- if (!(old instanceof PackageDescriptor)) {
- throw new DescriptorValidationException(file,
- '\"' + name + "\" is already defined (as something other than a "
- + "package) in file \"" + old.getFile().getName() + "\".");
- }
- }
- }
-
- /** A (GenericDescriptor, int) pair, used as a map key. */
- private static final class DescriptorIntPair {
- private final GenericDescriptor descriptor;
- private final int number;
-
- DescriptorIntPair(final GenericDescriptor descriptor, final int number) {
- this.descriptor = descriptor;
- this.number = number;
- }
-
- @Override
- public int hashCode() {
- return descriptor.hashCode() * ((1 << 16) - 1) + number;
- }
- @Override
- public boolean equals(final Object obj) {
- if (!(obj instanceof DescriptorIntPair)) {
- return false;
- }
- final DescriptorIntPair other = (DescriptorIntPair)obj;
- return descriptor == other.descriptor && number == other.number;
- }
- }
-
- /**
- * Adds a field to the fieldsByNumber table. Throws an exception if a
- * field with the same containing type and number already exists.
- */
- void addFieldByNumber(final FieldDescriptor field)
- throws DescriptorValidationException {
- final DescriptorIntPair key =
- new DescriptorIntPair(field.getContainingType(), field.getNumber());
- final FieldDescriptor old = fieldsByNumber.put(key, field);
- if (old != null) {
- fieldsByNumber.put(key, old);
- throw new DescriptorValidationException(field,
- "Field number " + field.getNumber() +
- " has already been used in \"" +
- field.getContainingType().getFullName() +
- "\" by field \"" + old.getName() + "\".");
- }
- }
-
- /**
- * Adds an enum value to the enumValuesByNumber table. If an enum value
- * with the same type and number already exists, does nothing. (This is
- * allowed; the first value define with the number takes precedence.)
- */
- void addEnumValueByNumber(final EnumValueDescriptor value) {
- final DescriptorIntPair key =
- new DescriptorIntPair(value.getType(), value.getNumber());
- final EnumValueDescriptor old = enumValuesByNumber.put(key, value);
- if (old != null) {
- enumValuesByNumber.put(key, old);
- // Not an error: Multiple enum values may have the same number, but
- // we only want the first one in the map.
- }
- }
-
- /**
- * Verifies that the descriptor's name is valid (i.e. it contains only
- * letters, digits, and underscores, and does not start with a digit).
- */
- static void validateSymbolName(final GenericDescriptor descriptor)
- throws DescriptorValidationException {
- final String name = descriptor.getName();
- if (name.length() == 0) {
- throw new DescriptorValidationException(descriptor, "Missing name.");
- } else {
- boolean valid = true;
- for (int i = 0; i < name.length(); i++) {
- final char c = name.charAt(i);
- // Non-ASCII characters are not valid in protobuf identifiers, even
- // if they are letters or digits.
- if (c >= 128) {
- valid = false;
- }
- // First character must be letter or _. Subsequent characters may
- // be letters, numbers, or digits.
- if (Character.isLetter(c) || c == '_' ||
- (Character.isDigit(c) && i > 0)) {
- // Valid
- } else {
- valid = false;
- }
- }
- if (!valid) {
- throw new DescriptorValidationException(descriptor,
- '\"' + name + "\" is not a valid identifier.");
- }
- }
- }
- }
-
- /** Describes an oneof of a message type. */
- public static final class OneofDescriptor {
- /** Get the index of this descriptor within its parent. */
- public int getIndex() { return index; }
-
- public String getName() { return proto.getName(); }
-
- public FileDescriptor getFile() { return file; }
-
- public String getFullName() { return fullName; }
-
- public Descriptor getContainingType() { return containingType; }
-
- public int getFieldCount() { return fieldCount; }
-
- public OneofOptions getOptions() {
- return proto.getOptions();
- }
-
- /** Get a list of this message type's fields. */
- public List<FieldDescriptor> getFields() {
- return Collections.unmodifiableList(Arrays.asList(fields));
- }
-
- public FieldDescriptor getField(int index) {
- return fields[index];
- }
-
- private void setProto(final OneofDescriptorProto proto) {
- this.proto = proto;
- }
-
- private OneofDescriptor(final OneofDescriptorProto proto,
- final FileDescriptor file,
- final Descriptor parent,
- final int index)
- throws DescriptorValidationException {
- this.proto = proto;
- fullName = computeFullName(file, parent, proto.getName());
- this.file = file;
- this.index = index;
-
- containingType = parent;
- fieldCount = 0;
- }
-
- private final int index;
- private OneofDescriptorProto proto;
- private final String fullName;
- private final FileDescriptor file;
-
- private Descriptor containingType;
- private int fieldCount;
- private FieldDescriptor[] fields;
- }
-}