tizen 2.3.1 release
[external/protobuf.git] / java / src / main / java / com / google / protobuf / RpcUtil.java
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 /**
34  * Grab-bag of utility functions useful when dealing with RPCs.
35  *
36  * @author kenton@google.com Kenton Varda
37  */
38 public final class RpcUtil {
39   private RpcUtil() {}
40
41   /**
42    * Take an {@code RpcCallback<Message>} and convert it to an
43    * {@code RpcCallback} accepting a specific message type.  This is always
44    * type-safe (parameter type contravariance).
45    */
46   @SuppressWarnings("unchecked")
47   public static <Type extends Message> RpcCallback<Type>
48   specializeCallback(final RpcCallback<Message> originalCallback) {
49     return (RpcCallback<Type>)originalCallback;
50     // The above cast works, but only due to technical details of the Java
51     // implementation.  A more theoretically correct -- but less efficient --
52     // implementation would be as follows:
53     //   return new RpcCallback<Type>() {
54     //     public void run(Type parameter) {
55     //       originalCallback.run(parameter);
56     //     }
57     //   };
58   }
59
60   /**
61    * Take an {@code RpcCallback} accepting a specific message type and convert
62    * it to an {@code RpcCallback<Message>}.  The generalized callback will
63    * accept any message object which has the same descriptor, and will convert
64    * it to the correct class before calling the original callback.  However,
65    * if the generalized callback is given a message with a different descriptor,
66    * an exception will be thrown.
67    */
68   public static <Type extends Message>
69   RpcCallback<Message> generalizeCallback(
70       final RpcCallback<Type> originalCallback,
71       final Class<Type> originalClass,
72       final Type defaultInstance) {
73     return new RpcCallback<Message>() {
74       public void run(final Message parameter) {
75         Type typedParameter;
76         try {
77           typedParameter = originalClass.cast(parameter);
78         } catch (ClassCastException ignored) {
79           typedParameter = copyAsType(defaultInstance, parameter);
80         }
81         originalCallback.run(typedParameter);
82       }
83     };
84   }
85
86   /**
87    * Creates a new message of type "Type" which is a copy of "source".  "source"
88    * must have the same descriptor but may be a different class (e.g.
89    * DynamicMessage).
90    */
91   @SuppressWarnings("unchecked")
92   private static <Type extends Message> Type copyAsType(
93       final Type typeDefaultInstance, final Message source) {
94     return (Type) typeDefaultInstance
95         .newBuilderForType().mergeFrom(source).build();
96   }
97
98   /**
99    * Creates a callback which can only be called once.  This may be useful for
100    * security, when passing a callback to untrusted code:  most callbacks do
101    * not expect to be called more than once, so doing so may expose bugs if it
102    * is not prevented.
103    */
104   public static <ParameterType>
105     RpcCallback<ParameterType> newOneTimeCallback(
106       final RpcCallback<ParameterType> originalCallback) {
107     return new RpcCallback<ParameterType>() {
108       private boolean alreadyCalled = false;
109
110       public void run(final ParameterType parameter) {
111         synchronized(this) {
112           if (alreadyCalled) {
113             throw new AlreadyCalledException();
114           }
115           alreadyCalled = true;
116         }
117
118         originalCallback.run(parameter);
119       }
120     };
121   }
122
123   /**
124    * Exception thrown when a one-time callback is called more than once.
125    */
126   public static final class AlreadyCalledException extends RuntimeException {
127     private static final long serialVersionUID = 5469741279507848266L;
128
129     public AlreadyCalledException() {
130       super("This RpcCallback was already called and cannot be called " +
131             "multiple times.");
132     }
133   }
134 }