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: 326026 $, $Date: 2005-10-18 00:35:27 -0400 (Tue, 18 Oct 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 * Returns true if the stack is empty false otherwise.
97 */
98 public boolean isEmpty()
99 {
100 return this.stack.isEmpty();
101 }
102
103 /***
104 * Pushes the specified invocation to this stack.
105 */
106 public void push( Invocation invocation )
107 {
108 this.stack.add( 0, invocation );
109 }
110
111 /***
112 * Pops the latest invocation from this stack. This stack is released
113 * automatically if you pop all items from this stack.
114 */
115 public Invocation pop()
116 {
117 Invocation invocation = ( Invocation ) this.stack.remove( 0 );
118 if( this.stack.size() == 0 )
119 {
120 synchronized( stacks )
121 {
122 stacks.remove( thread );
123 }
124 }
125
126 return invocation;
127 }
128 }