1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.invocation;
18
19
20 import java.util.ArrayList;
21 import java.util.IdentityHashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.naming.Context;
26
27
28 /***
29 * Keeps track of recursive {@link Invocation}s. This stack assumes an invocation
30 * occurs in the same thread since it is called first, so we manages stacks
31 * for each invocation in {@link ThreadLocal}-like manner. You can just use
32 * {@link #getInstance()} to get current invocation stack.
33 * <p>
34 * Using {@link InvocationStack}, you can find out current effective JNDI
35 * {@link Context} or detect infinite recursions.
36 *
37 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38 * @version $Rev: 264732 $, $Date: 2005-08-30 04:04:51 -0400 (Tue, 30 Aug 2005) $
39 */
40 public final class InvocationStack
41 {
42
43
44
45 private static final Map stacks = new IdentityHashMap();
46
47 /***
48 * Returns the invocation stack of current thread.
49 */
50 public static InvocationStack getInstance()
51 {
52 Thread currentThread = Thread.currentThread();
53 InvocationStack ctx;
54 synchronized( stacks )
55 {
56 ctx = ( InvocationStack ) stacks.get( currentThread );
57 if( ctx == null )
58 {
59 ctx = new InvocationStack();
60 }
61 }
62 return ctx;
63 }
64
65 private final Thread thread;
66 private final List stack = new ArrayList();
67
68 private InvocationStack()
69 {
70 Thread currentThread = Thread.currentThread();
71 this.thread = currentThread;
72
73 stacks.put( currentThread, this );
74 }
75
76 /***
77 * Returns an array of {@link Invocation}s. 0th element is the
78 * latest invocation.
79 */
80 public Invocation[] toArray()
81 {
82 Invocation[] result = new Invocation[ stack.size() ];
83 result = ( Invocation[] ) stack.toArray( result );
84 return result;
85 }
86
87 /***
88 * Returns the latest invocation.
89 */
90 public Invocation peek()
91 {
92 return ( Invocation ) this.stack.get( 0 );
93 }
94
95 /***
96 * Pushes the specified invocation to this stack.
97 */
98 public void push( Invocation invocation )
99 {
100 this.stack.add( 0, invocation );
101 }
102
103 /***
104 * Pops the latest invocation from this stack. This stack is released
105 * automatically if you pop all items from this stack.
106 */
107 public Invocation pop()
108 {
109 Invocation invocation = ( Invocation ) this.stack.remove( 0 );
110 if( this.stack.size() == 0 )
111 {
112 synchronized( stacks )
113 {
114 stacks.remove( thread );
115 }
116 }
117
118 return invocation;
119 }
120 }