OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 */ | 72 */ |
73 public class ExtensionRegistryLite { | 73 public class ExtensionRegistryLite { |
74 | 74 |
75 // Set true to enable lazy parsing feature for MessageSet. | 75 // Set true to enable lazy parsing feature for MessageSet. |
76 // | 76 // |
77 // TODO(xiangl): Now we use a global flag to control whether enable lazy | 77 // TODO(xiangl): Now we use a global flag to control whether enable lazy |
78 // parsing feature for MessageSet, which may be too crude for some | 78 // parsing feature for MessageSet, which may be too crude for some |
79 // applications. Need to support this feature on smaller granularity. | 79 // applications. Need to support this feature on smaller granularity. |
80 private static volatile boolean eagerlyParseMessageSets = false; | 80 private static volatile boolean eagerlyParseMessageSets = false; |
81 | 81 |
| 82 // Visible for testing. |
| 83 static final String EXTENSION_CLASS_NAME = "com.google.protobuf.Extension"; |
| 84 |
| 85 /* @Nullable */ |
| 86 static Class<?> resolveExtensionClass() { |
| 87 try { |
| 88 return Class.forName(EXTENSION_CLASS_NAME); |
| 89 } catch (ClassNotFoundException e) { |
| 90 // See comment in ExtensionRegistryFactory on the potential expense of thi
s. |
| 91 return null; |
| 92 } |
| 93 } |
| 94 |
| 95 /* @Nullable */ |
| 96 private static final Class<?> extensionClass = resolveExtensionClass(); |
| 97 |
82 public static boolean isEagerlyParseMessageSets() { | 98 public static boolean isEagerlyParseMessageSets() { |
83 return eagerlyParseMessageSets; | 99 return eagerlyParseMessageSets; |
84 } | 100 } |
85 | 101 |
86 public static void setEagerlyParseMessageSets(boolean isEagerlyParse) { | 102 public static void setEagerlyParseMessageSets(boolean isEagerlyParse) { |
87 eagerlyParseMessageSets = isEagerlyParse; | 103 eagerlyParseMessageSets = isEagerlyParse; |
88 } | 104 } |
89 | 105 |
90 /** Construct a new, empty instance. */ | 106 /** |
| 107 * Construct a new, empty instance. |
| 108 * |
| 109 * <p>This may be an {@code ExtensionRegistry} if the full (non-Lite) proto li
braries are |
| 110 * available. |
| 111 */ |
91 public static ExtensionRegistryLite newInstance() { | 112 public static ExtensionRegistryLite newInstance() { |
92 return new ExtensionRegistryLite(); | 113 return ExtensionRegistryFactory.create(); |
93 } | 114 } |
94 | 115 |
95 /** Get the unmodifiable singleton empty instance. */ | 116 /** |
| 117 * Get the unmodifiable singleton empty instance of either ExtensionRegistryLi
te or |
| 118 * {@code ExtensionRegistry} (if the full (non-Lite) proto libraries are avail
able). |
| 119 */ |
96 public static ExtensionRegistryLite getEmptyRegistry() { | 120 public static ExtensionRegistryLite getEmptyRegistry() { |
97 return EMPTY; | 121 return ExtensionRegistryFactory.createEmpty(); |
98 } | 122 } |
99 | 123 |
| 124 |
100 /** Returns an unmodifiable view of the registry. */ | 125 /** Returns an unmodifiable view of the registry. */ |
101 public ExtensionRegistryLite getUnmodifiable() { | 126 public ExtensionRegistryLite getUnmodifiable() { |
102 return new ExtensionRegistryLite(this); | 127 return new ExtensionRegistryLite(this); |
103 } | 128 } |
104 | 129 |
105 /** | 130 /** |
106 * Find an extension by containing type and field number. | 131 * Find an extension by containing type and field number. |
107 * | 132 * |
108 * @return Information about the extension if found, or {@code null} | 133 * @return Information about the extension if found, or {@code null} |
109 * otherwise. | 134 * otherwise. |
(...skipping 11 matching lines...) Expand all Loading... |
121 | 146 |
122 /** Add an extension from a lite generated file to the registry. */ | 147 /** Add an extension from a lite generated file to the registry. */ |
123 public final void add( | 148 public final void add( |
124 final GeneratedMessageLite.GeneratedExtension<?, ?> extension) { | 149 final GeneratedMessageLite.GeneratedExtension<?, ?> extension) { |
125 extensionsByNumber.put( | 150 extensionsByNumber.put( |
126 new ObjectIntPair(extension.getContainingTypeDefaultInstance(), | 151 new ObjectIntPair(extension.getContainingTypeDefaultInstance(), |
127 extension.getNumber()), | 152 extension.getNumber()), |
128 extension); | 153 extension); |
129 } | 154 } |
130 | 155 |
| 156 /** |
| 157 * Add an extension from a lite generated file to the registry only if it is |
| 158 * a non-lite extension i.e. {@link GeneratedMessageLite.GeneratedExtension}.
*/ |
| 159 public final void add(ExtensionLite<?, ?> extension) { |
| 160 if (GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom(extension
.getClass())) { |
| 161 add((GeneratedMessageLite.GeneratedExtension<?, ?>) extension); |
| 162 } |
| 163 if (ExtensionRegistryFactory.isFullRegistry(this)) { |
| 164 try { |
| 165 this.getClass().getMethod("add", extensionClass).invoke(this, extension)
; |
| 166 } catch (Exception e) { |
| 167 throw new IllegalArgumentException( |
| 168 String.format("Could not invoke ExtensionRegistry#add for %s", exten
sion), e); |
| 169 } |
| 170 } |
| 171 } |
| 172 |
131 // ================================================================= | 173 // ================================================================= |
132 // Private stuff. | 174 // Private stuff. |
133 | 175 |
134 // Constructors are package-private so that ExtensionRegistry can subclass | 176 // Constructors are package-private so that ExtensionRegistry can subclass |
135 // this. | 177 // this. |
136 | 178 |
137 ExtensionRegistryLite() { | 179 ExtensionRegistryLite() { |
138 this.extensionsByNumber = | 180 this.extensionsByNumber = |
139 new HashMap<ObjectIntPair, | 181 new HashMap<ObjectIntPair, |
140 GeneratedMessageLite.GeneratedExtension<?, ?>>(); | 182 GeneratedMessageLite.GeneratedExtension<?, ?>>(); |
141 } | 183 } |
| 184 static final ExtensionRegistryLite EMPTY_REGISTRY_LITE = |
| 185 new ExtensionRegistryLite(true); |
142 | 186 |
143 ExtensionRegistryLite(ExtensionRegistryLite other) { | 187 ExtensionRegistryLite(ExtensionRegistryLite other) { |
144 if (other == EMPTY) { | 188 if (other == EMPTY_REGISTRY_LITE) { |
145 this.extensionsByNumber = Collections.emptyMap(); | 189 this.extensionsByNumber = Collections.emptyMap(); |
146 } else { | 190 } else { |
147 this.extensionsByNumber = | 191 this.extensionsByNumber = |
148 Collections.unmodifiableMap(other.extensionsByNumber); | 192 Collections.unmodifiableMap(other.extensionsByNumber); |
149 } | 193 } |
150 } | 194 } |
151 | 195 |
152 private final Map<ObjectIntPair, | 196 private final Map<ObjectIntPair, |
153 GeneratedMessageLite.GeneratedExtension<?, ?>> | 197 GeneratedMessageLite.GeneratedExtension<?, ?>> |
154 extensionsByNumber; | 198 extensionsByNumber; |
155 | 199 |
156 private ExtensionRegistryLite(boolean empty) { | 200 ExtensionRegistryLite(boolean empty) { |
157 this.extensionsByNumber = Collections.emptyMap(); | 201 this.extensionsByNumber = Collections.emptyMap(); |
158 } | 202 } |
159 private static final ExtensionRegistryLite EMPTY = | |
160 new ExtensionRegistryLite(true); | |
161 | 203 |
162 /** A (Object, int) pair, used as a map key. */ | 204 /** A (Object, int) pair, used as a map key. */ |
163 private static final class ObjectIntPair { | 205 private static final class ObjectIntPair { |
164 private final Object object; | 206 private final Object object; |
165 private final int number; | 207 private final int number; |
166 | 208 |
167 ObjectIntPair(final Object object, final int number) { | 209 ObjectIntPair(final Object object, final int number) { |
168 this.object = object; | 210 this.object = object; |
169 this.number = number; | 211 this.number = number; |
170 } | 212 } |
171 | 213 |
172 @Override | 214 @Override |
173 public int hashCode() { | 215 public int hashCode() { |
174 return System.identityHashCode(object) * ((1 << 16) - 1) + number; | 216 return System.identityHashCode(object) * ((1 << 16) - 1) + number; |
175 } | 217 } |
176 @Override | 218 @Override |
177 public boolean equals(final Object obj) { | 219 public boolean equals(final Object obj) { |
178 if (!(obj instanceof ObjectIntPair)) { | 220 if (!(obj instanceof ObjectIntPair)) { |
179 return false; | 221 return false; |
180 } | 222 } |
181 final ObjectIntPair other = (ObjectIntPair)obj; | 223 final ObjectIntPair other = (ObjectIntPair)obj; |
182 return object == other.object && number == other.number; | 224 return object == other.object && number == other.number; |
183 } | 225 } |
184 } | 226 } |
185 } | 227 } |
OLD | NEW |