1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package org.apache.thrift.protocol;
21 
22 import org.apache.thrift.TException;
23 
24 /**
25  * Utility class with static methods for interacting with protocol data
26  * streams.
27  *
28  */
29 public class TProtocolUtil {
30 
31   /**
32    * The maximum recursive depth the skip() function will traverse before
33    * throwing a TException.
34    */
35   private static int maxSkipDepth = Integer.MAX_VALUE;
36 
37   /**
38    * Specifies the maximum recursive depth that the skip function will
39    * traverse before throwing a TException.  This is a global setting, so
40    * any call to skip in this JVM will enforce this value.
41    *
42    * @param depth  the maximum recursive depth.  A value of 2 would allow
43    *    the skip function to skip a structure or collection with basic children,
44    *    but it would not permit skipping a struct that had a field containing
45    *    a child struct.  A value of 1 would only allow skipping of simple
46    *    types and empty structs/collections.
47    */
setMaxSkipDepth(int depth)48   public static void setMaxSkipDepth(int depth) {
49     maxSkipDepth = depth;
50   }
51 
52   /**
53    * Skips over the next data element from the provided input TProtocol object.
54    *
55    * @param prot  the protocol object to read from
56    * @param type  the next value will be intepreted as this TType value.
57    */
skip(TProtocol prot, byte type)58   public static void skip(TProtocol prot, byte type)
59     throws TException {
60     skip(prot, type, maxSkipDepth);
61   }
62 
63   /**
64    * Skips over the next data element from the provided input TProtocol object.
65    *
66    * @param prot  the protocol object to read from
67    * @param type  the next value will be intepreted as this TType value.
68    * @param maxDepth  this function will only skip complex objects to this
69    *   recursive depth, to prevent Java stack overflow.
70    */
skip(TProtocol prot, byte type, int maxDepth)71   public static void skip(TProtocol prot, byte type, int maxDepth)
72   throws TException {
73     if (maxDepth <= 0) {
74       throw new TException("Maximum skip depth exceeded");
75     }
76     switch (type) {
77     case TType.BOOL:
78       {
79         prot.readBool();
80         break;
81       }
82     case TType.BYTE:
83       {
84         prot.readByte();
85         break;
86       }
87     case TType.I16:
88       {
89         prot.readI16();
90         break;
91       }
92     case TType.I32:
93       {
94         prot.readI32();
95         break;
96       }
97     case TType.I64:
98       {
99         prot.readI64();
100         break;
101       }
102     case TType.DOUBLE:
103       {
104         prot.readDouble();
105         break;
106       }
107     case TType.STRING:
108       {
109         prot.readBinary();
110         break;
111       }
112     case TType.STRUCT:
113       {
114         prot.readStructBegin();
115         while (true) {
116           TField field = prot.readFieldBegin();
117           if (field.type == TType.STOP) {
118             break;
119           }
120           skip(prot, field.type, maxDepth - 1);
121           prot.readFieldEnd();
122         }
123         prot.readStructEnd();
124         break;
125       }
126     case TType.MAP:
127       {
128         TMap map = prot.readMapBegin();
129         for (int i = 0; i < map.size; i++) {
130           skip(prot, map.keyType, maxDepth - 1);
131           skip(prot, map.valueType, maxDepth - 1);
132         }
133         prot.readMapEnd();
134         break;
135       }
136     case TType.SET:
137       {
138         TSet set = prot.readSetBegin();
139         for (int i = 0; i < set.size; i++) {
140           skip(prot, set.elemType, maxDepth - 1);
141         }
142         prot.readSetEnd();
143         break;
144       }
145     case TType.LIST:
146       {
147         TList list = prot.readListBegin();
148         for (int i = 0; i < list.size; i++) {
149           skip(prot, list.elemType, maxDepth - 1);
150         }
151         prot.readListEnd();
152         break;
153       }
154     default:
155         throw new TProtocolException(TProtocolException.INVALID_DATA,
156                                    "Unrecognized type " + type);
157     }
158   }
159 }
160