- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / 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 // http://code.google.com/p/protobuf/
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.newBuilderForType()
95                                     .mergeFrom(source)
96                                     .build();
97   }
98
99   /**
100    * Creates a callback which can only be called once.  This may be useful for
101    * security, when passing a callback to untrusted code:  most callbacks do
102    * not expect to be called more than once, so doing so may expose bugs if it
103    * is not prevented.
104    */
105   public static <ParameterType>
106     RpcCallback<ParameterType> newOneTimeCallback(
107       final RpcCallback<ParameterType> originalCallback) {
108     return new RpcCallback<ParameterType>() {
109       private boolean alreadyCalled = false;
110
111       public void run(final ParameterType parameter) {
112         synchronized(this) {
113           if (alreadyCalled) {
114             throw new AlreadyCalledException();
115           }
116           alreadyCalled = true;
117         }
118
119         originalCallback.run(parameter);
120       }
121     };
122   }
123
124   /**
125    * Exception thrown when a one-time callback is called more than once.
126    */
127   public static final class AlreadyCalledException extends RuntimeException {
128     private static final long serialVersionUID = 5469741279507848266L;
129
130     public AlreadyCalledException() {
131       super("This RpcCallback was already called and cannot be called " +
132             "multiple times.");
133     }
134   }
135 }