1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package tests.util;
19
20import java.util.Stack;
21
22/**
23 * A stack to store the parameters of a call, as well as the call stack.
24 */
25public class CallVerificationStack extends Stack<Object> {
26
27    /*
28      * --------------------------------------------------------------------
29      * Class variables
30      * --------------------------------------------------------------------
31      */
32
33    private static final long serialVersionUID = 1L;
34
35    // the singleton
36    private static final CallVerificationStack _instance = new CallVerificationStack();
37
38    /*
39      * --------------------------------------------------------------------
40      * Instance variables
41      * --------------------------------------------------------------------
42      */
43
44    // the call stack, store StackTraceElement
45    private final Stack<StackTraceElement> callStack = new Stack<StackTraceElement>();
46
47    /*
48      * -------------------------------------------------------------------
49      * Constructors
50      * -------------------------------------------------------------------
51      */
52
53    /**
54     * Can't be instantiated.
55     */
56    private CallVerificationStack() {
57        // empty
58    }
59
60    /*
61      * -------------------------------------------------------------------
62      * Methods
63      * -------------------------------------------------------------------
64      */
65
66    /**
67     * Gets the singleton instance.
68     *
69     * @return the singleton instance
70     */
71    public static CallVerificationStack getInstance() {
72        return _instance;
73    }
74
75    /**
76     * Pushes the call stack.
77     */
78    private void pushCallStack() {
79        StackTraceElement[] eles = (new Throwable()).getStackTrace();
80        int i;
81        for (i = 1; i < eles.length; i++) {
82            if (!eles[i].getClassName().equals(this.getClass().getName())) {
83                break;
84            }
85        }
86        this.callStack.push(eles[i]);
87    }
88
89    /**
90     * Gets the "current" calling class name.
91     *
92     * @return the "current" calling class name
93     */
94    public String getCurrentSourceClass() {
95        return this.callStack.peek().getClassName();
96    }
97
98    /**
99     * Gets the "current" calling method name.
100     *
101     * @return the "current" calling method name
102     */
103    public String getCurrentSourceMethod() {
104        return this.callStack.peek().getMethodName();
105    }
106
107    /**
108     * Clear the parameter stack and the call stack.
109     */
110    @Override
111    public void clear() {
112        this.callStack.clear();
113        super.clear();
114    }
115
116    @Override
117    public Object push(Object o) {
118        pushCallStack();
119        return super.push(o);
120    }
121
122    /**
123     * Pushes a boolean onto the top of this stack.
124     *
125     * @param val the value to push
126     */
127    public void push(boolean val) {
128        this.push(new BaseTypeWrapper(val));
129    }
130
131    /**
132     * Pushes a char onto the top of this stack.
133     *
134     * @param val the value to push
135     */
136    public void push(char val) {
137        this.push(new BaseTypeWrapper(val));
138    }
139
140    /**
141     * Pushes a double onto the top of this stack.
142     *
143     * @param val the value to push
144     */
145    public void push(double val) {
146        this.push(new BaseTypeWrapper(val));
147    }
148
149    /**
150     * Pushes a float onto the top of this stack.
151     *
152     * @param val the value to push
153     */
154    public void push(float val) {
155        this.push(new BaseTypeWrapper(val));
156    }
157
158    /**
159     * Pushes an int onto the top of this stack.
160     *
161     * @param val the value to push
162     */
163    public void push(int val) {
164        this.push(new BaseTypeWrapper(val));
165    }
166
167    /**
168     * Pushes a long onto the top of this stack.
169     *
170     * @param val the value to push
171     */
172    public void push(long val) {
173        this.push(new BaseTypeWrapper(val));
174    }
175
176    /**
177     * Pushes a short onto the top of this stack.
178     *
179     * @param val the value to push
180     */
181    public void push(short val) {
182        this.push(new BaseTypeWrapper(val));
183    }
184
185    /**
186     * Pop an object.
187     *
188     * @return the object
189     */
190    @Override
191    public Object pop() {
192        this.callStack.pop();
193        return super.pop();
194    }
195
196    /**
197     * Pop a boolean.
198     *
199     * @return the value
200     */
201    public boolean popBoolean() {
202        BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
203        Boolean value = (Boolean) wrapper.getValue();
204        return value.booleanValue();
205    }
206
207    /**
208     * Pop a char.
209     *
210     * @return the value
211     */
212    public char popChar() {
213        BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
214        Character value = (Character) wrapper.getValue();
215        return value.charValue();
216    }
217
218    /**
219     * Pop a double.
220     *
221     * @return the value
222     */
223    public double popDouble() {
224        BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
225        Double value = (Double) wrapper.getValue();
226        return value.doubleValue();
227    }
228
229    /**
230     * Pop a float.
231     *
232     * @return the value
233     */
234    public float popFloat() {
235        BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
236        Float value = (Float) wrapper.getValue();
237        return value.floatValue();
238    }
239
240    /**
241     * Pop a int.
242     *
243     * @return the value
244     */
245    public int popInt() {
246        BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
247        Integer value = (Integer) wrapper.getValue();
248        return value.intValue();
249    }
250
251    /**
252     * Pop a long.
253     *
254     * @return the value
255     */
256    public long popLong() {
257        BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
258        Long value = (Long) wrapper.getValue();
259        return value.longValue();
260    }
261
262    /**
263     * Pop a short.
264     *
265     * @return the value
266     */
267    public short popShort() {
268        BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
269        Short value = (Short) wrapper.getValue();
270        return value.shortValue();
271    }
272
273    /*
274      * Wrapper of base types.
275      */
276    class BaseTypeWrapper {
277
278        // the internal value
279        private Object value;
280
281        /*
282           * Constructs a wrapper object for the base type <code> boolean </code> .
283           */
284        public BaseTypeWrapper(boolean val) {
285            this.value = new Boolean(val);
286        }
287
288        /*
289           * Constructs a wrapper object for the base type <code> c </code> .
290           */
291        public BaseTypeWrapper(byte val) {
292            this.value = new Byte(val);
293        }
294
295        /*
296           * Constructs a wrapper object for the base type <code> char </code> .
297           */
298        public BaseTypeWrapper(char val) {
299            this.value = new Character(val);
300        }
301
302        /*
303           * Constructs a wrapper object for the base type <code> double </code> .
304           */
305        public BaseTypeWrapper(double val) {
306            this.value = new Double(val);
307        }
308
309        /*
310           * Constructs a wrapper object for the base type <code> float </code> .
311           */
312        public BaseTypeWrapper(float val) {
313            this.value = new Float(val);
314        }
315
316        /*
317           * Constructs a wrapper object for the base type <code> int </code> .
318           */
319        public BaseTypeWrapper(int val) {
320            this.value = new Integer(val);
321        }
322
323        /*
324           * Constructs a wrapper object for the base type <code> long </code> .
325           */
326        public BaseTypeWrapper(long val) {
327            this.value = new Long(val);
328        }
329
330        /*
331           * Constructs a wrapper object for the base type <code> short </code> .
332           */
333        public BaseTypeWrapper(short val) {
334            this.value = new Short(val);
335        }
336
337        /*
338           * Gets the internal value.
339           */
340        public Object getValue() {
341            return this.value;
342        }
343    }
344}
345