• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
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
14 // distribution.
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.
18 //
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.
30 
31 package com.google.protobuf;
32 
33 import java.io.FilterInputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import java.util.Collection;
38 
39 /**
40  * A partial implementation of the {@link MessageLite} interface which
41  * implements as many methods of that interface as possible in terms of other
42  * methods.
43  *
44  * @author kenton@google.com Kenton Varda
45  */
46 public abstract class AbstractMessageLite<
47     MessageType extends AbstractMessageLite<MessageType, BuilderType>,
48     BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>>
49         implements MessageLite {
50   protected int memoizedHashCode = 0;
51 
52   @Override
toByteString()53   public ByteString toByteString() {
54     try {
55       final ByteString.CodedBuilder out =
56         ByteString.newCodedBuilder(getSerializedSize());
57       writeTo(out.getCodedOutput());
58       return out.build();
59     } catch (IOException e) {
60       throw new RuntimeException(getSerializingExceptionMessage("ByteString"), e);
61     }
62   }
63 
64   @Override
toByteArray()65   public byte[] toByteArray() {
66     try {
67       final byte[] result = new byte[getSerializedSize()];
68       final CodedOutputStream output = CodedOutputStream.newInstance(result);
69       writeTo(output);
70       output.checkNoSpaceLeft();
71       return result;
72     } catch (IOException e) {
73       throw new RuntimeException(getSerializingExceptionMessage("byte array"), e);
74     }
75   }
76 
77   @Override
writeTo(final OutputStream output)78   public void writeTo(final OutputStream output) throws IOException {
79     final int bufferSize =
80         CodedOutputStream.computePreferredBufferSize(getSerializedSize());
81     final CodedOutputStream codedOutput =
82         CodedOutputStream.newInstance(output, bufferSize);
83     writeTo(codedOutput);
84     codedOutput.flush();
85   }
86 
87   @Override
writeDelimitedTo(final OutputStream output)88   public void writeDelimitedTo(final OutputStream output) throws IOException {
89     final int serialized = getSerializedSize();
90     final int bufferSize = CodedOutputStream.computePreferredBufferSize(
91         CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
92     final CodedOutputStream codedOutput =
93         CodedOutputStream.newInstance(output, bufferSize);
94     codedOutput.writeRawVarint32(serialized);
95     writeTo(codedOutput);
96     codedOutput.flush();
97   }
98 
99 
100   /**
101    * Package private helper method for AbstractParser to create
102    * UninitializedMessageException.
103    */
newUninitializedMessageException()104   UninitializedMessageException newUninitializedMessageException() {
105     return new UninitializedMessageException(this);
106   }
107 
getSerializingExceptionMessage(String target)108   private String getSerializingExceptionMessage(String target) {
109     return "Serializing " + getClass().getName() + " to a " + target
110         + " threw an IOException (should never happen).";
111   }
112 
checkByteStringIsUtf8(ByteString byteString)113   protected static void checkByteStringIsUtf8(ByteString byteString)
114       throws IllegalArgumentException {
115     if (!byteString.isValidUtf8()) {
116       throw new IllegalArgumentException("Byte string is not UTF-8.");
117     }
118   }
119 
addAll(final Iterable<T> values, final Collection<? super T> list)120   protected static <T> void addAll(final Iterable<T> values,
121       final Collection<? super T> list) {
122     Builder.addAll(values, list);
123   }
124 
125   /**
126    * A partial implementation of the {@link Message.Builder} interface which
127    * implements as many methods of that interface as possible in terms of
128    * other methods.
129    */
130   @SuppressWarnings("unchecked")
131   public abstract static class Builder<
132       MessageType extends AbstractMessageLite<MessageType, BuilderType>,
133       BuilderType extends Builder<MessageType, BuilderType>>
134       implements MessageLite.Builder {
135     // The compiler produces an error if this is not declared explicitly.
136     @Override
clone()137     public abstract BuilderType clone();
138 
139     @Override
mergeFrom(final CodedInputStream input)140     public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
141       return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
142     }
143 
144     // Re-defined here for return type covariance.
145     @Override
mergeFrom( final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)146     public abstract BuilderType mergeFrom(
147         final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
148         throws IOException;
149 
150     @Override
mergeFrom(final ByteString data)151     public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
152       try {
153         final CodedInputStream input = data.newCodedInput();
154         mergeFrom(input);
155         input.checkLastTagWas(0);
156         return (BuilderType) this;
157       } catch (InvalidProtocolBufferException e) {
158         throw e;
159       } catch (IOException e) {
160         throw new RuntimeException(getReadingExceptionMessage("ByteString"), e);
161       }
162     }
163 
164     @Override
mergeFrom( final ByteString data, final ExtensionRegistryLite extensionRegistry)165     public BuilderType mergeFrom(
166         final ByteString data, final ExtensionRegistryLite extensionRegistry)
167         throws InvalidProtocolBufferException {
168       try {
169         final CodedInputStream input = data.newCodedInput();
170         mergeFrom(input, extensionRegistry);
171         input.checkLastTagWas(0);
172         return (BuilderType) this;
173       } catch (InvalidProtocolBufferException e) {
174         throw e;
175       } catch (IOException e) {
176         throw new RuntimeException(getReadingExceptionMessage("ByteString"), e);
177       }
178     }
179 
180     @Override
mergeFrom(final byte[] data)181     public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
182       return mergeFrom(data, 0, data.length);
183     }
184 
185     @Override
mergeFrom(final byte[] data, final int off, final int len)186     public BuilderType mergeFrom(final byte[] data, final int off, final int len)
187         throws InvalidProtocolBufferException {
188       try {
189         final CodedInputStream input =
190             CodedInputStream.newInstance(data, off, len);
191         mergeFrom(input);
192         input.checkLastTagWas(0);
193         return (BuilderType) this;
194       } catch (InvalidProtocolBufferException e) {
195         throw e;
196       } catch (IOException e) {
197         throw new RuntimeException(getReadingExceptionMessage("byte array"), e);
198       }
199     }
200 
201     @Override
mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)202     public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
203         throws InvalidProtocolBufferException {
204       return mergeFrom(data, 0, data.length, extensionRegistry);
205     }
206 
207     @Override
mergeFrom( final byte[] data, final int off, final int len, final ExtensionRegistryLite extensionRegistry)208     public BuilderType mergeFrom(
209         final byte[] data,
210         final int off,
211         final int len,
212         final ExtensionRegistryLite extensionRegistry)
213         throws InvalidProtocolBufferException {
214       try {
215         final CodedInputStream input =
216             CodedInputStream.newInstance(data, off, len);
217         mergeFrom(input, extensionRegistry);
218         input.checkLastTagWas(0);
219         return (BuilderType) this;
220       } catch (InvalidProtocolBufferException e) {
221         throw e;
222       } catch (IOException e) {
223         throw new RuntimeException(getReadingExceptionMessage("byte array"), e);
224       }
225     }
226 
227     @Override
mergeFrom(final InputStream input)228     public BuilderType mergeFrom(final InputStream input) throws IOException {
229       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
230       mergeFrom(codedInput);
231       codedInput.checkLastTagWas(0);
232       return (BuilderType) this;
233     }
234 
235     @Override
mergeFrom( final InputStream input, final ExtensionRegistryLite extensionRegistry)236     public BuilderType mergeFrom(
237         final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
238       final CodedInputStream codedInput = CodedInputStream.newInstance(input);
239       mergeFrom(codedInput, extensionRegistry);
240       codedInput.checkLastTagWas(0);
241       return (BuilderType) this;
242     }
243 
244     /**
245      * An InputStream implementations which reads from some other InputStream
246      * but is limited to a particular number of bytes.  Used by
247      * mergeDelimitedFrom().  This is intentionally package-private so that
248      * UnknownFieldSet can share it.
249      */
250     static final class LimitedInputStream extends FilterInputStream {
251       private int limit;
252 
LimitedInputStream(InputStream in, int limit)253       LimitedInputStream(InputStream in, int limit) {
254         super(in);
255         this.limit = limit;
256       }
257 
258       @Override
available()259       public int available() throws IOException {
260         return Math.min(super.available(), limit);
261       }
262 
263       @Override
read()264       public int read() throws IOException {
265         if (limit <= 0) {
266           return -1;
267         }
268         final int result = super.read();
269         if (result >= 0) {
270           --limit;
271         }
272         return result;
273       }
274 
275       @Override
read(final byte[] b, final int off, int len)276       public int read(final byte[] b, final int off, int len)
277                       throws IOException {
278         if (limit <= 0) {
279           return -1;
280         }
281         len = Math.min(len, limit);
282         final int result = super.read(b, off, len);
283         if (result >= 0) {
284           limit -= result;
285         }
286         return result;
287       }
288 
289       @Override
skip(final long n)290       public long skip(final long n) throws IOException {
291         final long result = super.skip(Math.min(n, limit));
292         if (result >= 0) {
293           limit -= result;
294         }
295         return result;
296       }
297     }
298 
299     @Override
mergeDelimitedFrom( final InputStream input, final ExtensionRegistryLite extensionRegistry)300     public boolean mergeDelimitedFrom(
301         final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
302       final int firstByte = input.read();
303       if (firstByte == -1) {
304         return false;
305       }
306       final int size = CodedInputStream.readRawVarint32(firstByte, input);
307       final InputStream limitedInput = new LimitedInputStream(input, size);
308       mergeFrom(limitedInput, extensionRegistry);
309       return true;
310     }
311 
312     @Override
mergeDelimitedFrom(final InputStream input)313     public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
314       return mergeDelimitedFrom(input,
315           ExtensionRegistryLite.getEmptyRegistry());
316     }
317 
318     @Override
319     @SuppressWarnings("unchecked") // isInstance takes care of this
mergeFrom(final MessageLite other)320     public BuilderType mergeFrom(final MessageLite other) {
321       if (!getDefaultInstanceForType().getClass().isInstance(other)) {
322         throw new IllegalArgumentException(
323             "mergeFrom(MessageLite) can only merge messages of the same type.");
324       }
325 
326       return internalMergeFrom((MessageType) other);
327     }
328 
internalMergeFrom(MessageType message)329     protected abstract BuilderType internalMergeFrom(MessageType message);
330 
getReadingExceptionMessage(String target)331     private String getReadingExceptionMessage(String target) {
332       return "Reading " + getClass().getName() + " from a " + target
333           + " threw an IOException (should never happen).";
334     }
335 
336     /**
337      * Construct an UninitializedMessageException reporting missing fields in
338      * the given message.
339      */
340     protected static UninitializedMessageException
newUninitializedMessageException(MessageLite message)341         newUninitializedMessageException(MessageLite message) {
342       return new UninitializedMessageException(message);
343     }
344 
345     /**
346      * Adds the {@code values} to the {@code list}.  This is a helper method
347      * used by generated code.  Users should ignore it.
348      *
349      * @throws NullPointerException if {@code values} or any of the elements of
350      * {@code values} is null. When that happens, some elements of
351      * {@code values} may have already been added to the result {@code list}.
352      */
addAll(final Iterable<T> values, final Collection<? super T> list)353     protected static <T> void addAll(final Iterable<T> values,
354                                      final Collection<? super T> list) {
355       if (values == null) {
356         throw new NullPointerException();
357       }
358       if (values instanceof LazyStringList) {
359         // For StringOrByteStringLists, check the underlying elements to avoid
360         // forcing conversions of ByteStrings to Strings.
361         checkForNullValues(((LazyStringList) values).getUnderlyingElements());
362         list.addAll((Collection<T>) values);
363       } else if (values instanceof Collection) {
364         checkForNullValues(values);
365         list.addAll((Collection<T>) values);
366       } else {
367         for (final T value : values) {
368           if (value == null) {
369             throw new NullPointerException();
370           }
371           list.add(value);
372         }
373       }
374     }
375 
checkForNullValues(final Iterable<?> values)376     private static void checkForNullValues(final Iterable<?> values) {
377       for (final Object value : values) {
378         if (value == null) {
379           throw new NullPointerException();
380         }
381       }
382     }
383   }
384 }
385