1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 package com.google.protobuf;
33 import static com.google.protobuf.Internal.checkNotNull;
35 import java.io.IOException;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.concurrent.ConcurrentMap;
40 * Main runtime interface for protobuf. Applications should interact with this interface (rather
41 * than directly accessing internal APIs) in order to perform operations on protobuf messages.
44 final class Protobuf {
45 private static final Protobuf INSTANCE = new Protobuf();
47 private final SchemaFactory schemaFactory;
49 // TODO(nathanmittler): Consider using ClassValue instead.
50 private final ConcurrentMap<Class<?>, Schema<?>> schemaCache =
51 new ConcurrentHashMap<Class<?>, Schema<?>>();
53 /** Gets the singleton instance of the Protobuf runtime. */
54 public static Protobuf getInstance() {
58 /** Writes the given message to the target {@link Writer}. */
59 public <T> void writeTo(T message, Writer writer) throws IOException {
60 schemaFor(message).writeTo(message, writer);
63 /** Reads fields from the given {@link Reader} and merges them into the message. */
64 public <T> void mergeFrom(T message, Reader reader) throws IOException {
65 mergeFrom(message, reader, ExtensionRegistryLite.getEmptyRegistry());
68 /** Reads fields from the given {@link Reader} and merges them into the message. */
69 public <T> void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
71 schemaFor(message).mergeFrom(message, reader, extensionRegistry);
74 /** Marks repeated/map/extension/unknown fields as immutable. */
75 public <T> void makeImmutable(T message) {
76 schemaFor(message).makeImmutable(message);
80 * Checks if all required fields are set. TODO(xiaofeng): Make this package private when the tests
81 * are moved to protobuf package.
83 public <T> boolean isInitialized(T message) {
84 return schemaFor(message).isInitialized(message);
87 /** Gets the schema for the given message type. */
88 public <T> Schema<T> schemaFor(Class<T> messageType) {
89 checkNotNull(messageType, "messageType");
90 @SuppressWarnings("unchecked")
91 Schema<T> schema = (Schema<T>) schemaCache.get(messageType);
93 schema = schemaFactory.createSchema(messageType);
94 @SuppressWarnings("unchecked")
95 Schema<T> previous = (Schema<T>) registerSchema(messageType, schema);
96 if (previous != null) {
97 // A new schema was registered by another thread.
104 /** Gets the schema for the given message. */
105 @SuppressWarnings("unchecked")
106 public <T> Schema<T> schemaFor(T message) {
107 return schemaFor((Class<T>) message.getClass());
111 * Registers the given schema for the message type only if a schema was not already registered.
113 * @param messageType the type of message on which the schema operates.
114 * @param schema the schema for the message type.
115 * @return the previously registered schema, or {@code null} if the given schema was successfully
118 public Schema<?> registerSchema(Class<?> messageType, Schema<?> schema) {
119 checkNotNull(messageType, "messageType");
120 checkNotNull(schema, "schema");
121 return schemaCache.putIfAbsent(messageType, schema);
125 * Visible for testing only. Registers the given schema for the message type. If a schema was
126 * previously registered, it will be replaced by the provided schema.
128 * @param messageType the type of message on which the schema operates.
129 * @param schema the schema for the message type.
130 * @return the previously registered schema, or {@code null} if no schema was registered
133 public Schema<?> registerSchemaOverride(Class<?> messageType, Schema<?> schema) {
134 checkNotNull(messageType, "messageType");
135 checkNotNull(schema, "schema");
136 return schemaCache.put(messageType, schema);
140 schemaFactory = new ManifestSchemaFactory();
143 int getTotalSchemaSize() {
145 for (Schema<?> schema : schemaCache.values()) {
146 if (schema instanceof MessageSchema) {
147 result += ((MessageSchema) schema).getSchemaSize();