Index: third_party/protobuf/java/src/main/java/com/google/protobuf/RpcUtil.java |
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/RpcUtil.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/RpcUtil.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..694b8d132b4c60c275c32051d77a23e9510d1ef1 |
--- /dev/null |
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/RpcUtil.java |
@@ -0,0 +1,134 @@ |
+// 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; |
+ |
+/** |
+ * Grab-bag of utility functions useful when dealing with RPCs. |
+ * |
+ * @author kenton@google.com Kenton Varda |
+ */ |
+public final class RpcUtil { |
+ private RpcUtil() {} |
+ |
+ /** |
+ * Take an {@code RpcCallback<Message>} and convert it to an |
+ * {@code RpcCallback} accepting a specific message type. This is always |
+ * type-safe (parameter type contravariance). |
+ */ |
+ @SuppressWarnings("unchecked") |
+ public static <Type extends Message> RpcCallback<Type> |
+ specializeCallback(final RpcCallback<Message> originalCallback) { |
+ return (RpcCallback<Type>)originalCallback; |
+ // The above cast works, but only due to technical details of the Java |
+ // implementation. A more theoretically correct -- but less efficient -- |
+ // implementation would be as follows: |
+ // return new RpcCallback<Type>() { |
+ // public void run(Type parameter) { |
+ // originalCallback.run(parameter); |
+ // } |
+ // }; |
+ } |
+ |
+ /** |
+ * Take an {@code RpcCallback} accepting a specific message type and convert |
+ * it to an {@code RpcCallback<Message>}. The generalized callback will |
+ * accept any message object which has the same descriptor, and will convert |
+ * it to the correct class before calling the original callback. However, |
+ * if the generalized callback is given a message with a different descriptor, |
+ * an exception will be thrown. |
+ */ |
+ public static <Type extends Message> |
+ RpcCallback<Message> generalizeCallback( |
+ final RpcCallback<Type> originalCallback, |
+ final Class<Type> originalClass, |
+ final Type defaultInstance) { |
+ return new RpcCallback<Message>() { |
+ public void run(final Message parameter) { |
+ Type typedParameter; |
+ try { |
+ typedParameter = originalClass.cast(parameter); |
+ } catch (ClassCastException ignored) { |
+ typedParameter = copyAsType(defaultInstance, parameter); |
+ } |
+ originalCallback.run(typedParameter); |
+ } |
+ }; |
+ } |
+ |
+ /** |
+ * Creates a new message of type "Type" which is a copy of "source". "source" |
+ * must have the same descriptor but may be a different class (e.g. |
+ * DynamicMessage). |
+ */ |
+ @SuppressWarnings("unchecked") |
+ private static <Type extends Message> Type copyAsType( |
+ final Type typeDefaultInstance, final Message source) { |
+ return (Type) typeDefaultInstance |
+ .newBuilderForType().mergeFrom(source).build(); |
+ } |
+ |
+ /** |
+ * Creates a callback which can only be called once. This may be useful for |
+ * security, when passing a callback to untrusted code: most callbacks do |
+ * not expect to be called more than once, so doing so may expose bugs if it |
+ * is not prevented. |
+ */ |
+ public static <ParameterType> |
+ RpcCallback<ParameterType> newOneTimeCallback( |
+ final RpcCallback<ParameterType> originalCallback) { |
+ return new RpcCallback<ParameterType>() { |
+ private boolean alreadyCalled = false; |
+ |
+ public void run(final ParameterType parameter) { |
+ synchronized(this) { |
+ if (alreadyCalled) { |
+ throw new AlreadyCalledException(); |
+ } |
+ alreadyCalled = true; |
+ } |
+ |
+ originalCallback.run(parameter); |
+ } |
+ }; |
+ } |
+ |
+ /** |
+ * Exception thrown when a one-time callback is called more than once. |
+ */ |
+ public static final class AlreadyCalledException extends RuntimeException { |
+ private static final long serialVersionUID = 5469741279507848266L; |
+ |
+ public AlreadyCalledException() { |
+ super("This RpcCallback was already called and cannot be called " + |
+ "multiple times."); |
+ } |
+ } |
+} |