1 package org.apache.maven.session.scope.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.LinkedList;
25 import java.util.Map;
26
27 import com.google.inject.Key;
28 import com.google.inject.OutOfScopeException;
29 import com.google.inject.Provider;
30 import com.google.inject.Scope;
31 import com.google.inject.util.Providers;
32
33
34
35
36 public class SessionScope
37 implements Scope
38 {
39
40
41
42 public static class Memento
43 {
44 final Map<Key<?>, Provider<?>> seeded;
45
46 Memento( final Map<Key<?>, Provider<?>> seeded )
47 {
48 this.seeded = Collections.unmodifiableMap( new HashMap<>( seeded ) );
49 }
50 }
51
52 private static final Provider<Object> SEEDED_KEY_PROVIDER = new Provider<Object>()
53 {
54 public Object get()
55 {
56 throw new IllegalStateException();
57 }
58 };
59
60
61
62
63 private static final class ScopeState
64 {
65 private final Map<Key<?>, Provider<?>> seeded = new HashMap<>();
66
67 private final Map<Key<?>, Object> provided = new HashMap<>();
68 }
69
70 private final ThreadLocal<LinkedList<ScopeState>> values = new ThreadLocal<>();
71
72 public void enter()
73 {
74 LinkedList<ScopeState> stack = values.get();
75 if ( stack == null )
76 {
77 stack = new LinkedList<>();
78 values.set( stack );
79 }
80 stack.addFirst( new ScopeState() );
81 }
82
83
84
85
86 public void enter( Memento memento )
87 {
88 enter();
89 getScopeState().seeded.putAll( memento.seeded );
90 }
91
92 private ScopeState getScopeState()
93 {
94 LinkedList<ScopeState> stack = values.get();
95 if ( stack == null || stack.isEmpty() )
96 {
97 throw new IllegalStateException();
98 }
99 return stack.getFirst();
100 }
101
102 public void exit()
103 {
104 final LinkedList<ScopeState> stack = values.get();
105 if ( stack == null || stack.isEmpty() )
106 {
107 throw new IllegalStateException();
108 }
109 stack.removeFirst();
110 if ( stack.isEmpty() )
111 {
112 values.remove();
113 }
114 }
115
116
117
118
119 public Memento memento()
120 {
121 LinkedList<ScopeState> stack = values.get();
122 return new Memento( stack != null ? stack.getFirst().seeded : Collections.<Key<?>, Provider<?>>emptyMap() );
123 }
124
125 public <T> void seed( Class<T> clazz, Provider<T> value )
126 {
127 getScopeState().seeded.put( Key.get( clazz ), value );
128 }
129
130 public <T> void seed( Class<T> clazz, final T value )
131 {
132 getScopeState().seeded.put( Key.get( clazz ), Providers.of( value ) );
133 }
134
135 public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped )
136 {
137 return new Provider<T>()
138 {
139 @SuppressWarnings( "unchecked" )
140 public T get()
141 {
142 LinkedList<ScopeState> stack = values.get();
143 if ( stack == null || stack.isEmpty() )
144 {
145 throw new OutOfScopeException( "Cannot access " + key + " outside of a scoping block" );
146 }
147
148 ScopeState state = stack.getFirst();
149
150 Provider<?> seeded = state.seeded.get( key );
151
152 if ( seeded != null )
153 {
154 return (T) seeded.get();
155 }
156
157 T provided = (T) state.provided.get( key );
158 if ( provided == null && unscoped != null )
159 {
160 provided = unscoped.get();
161 state.provided.put( key, provided );
162 }
163
164 return provided;
165 }
166 };
167 }
168
169 @SuppressWarnings( { "unchecked" } )
170 public static <T> Provider<T> seededKeyProvider()
171 {
172 return (Provider<T>) SEEDED_KEY_PROVIDER;
173 }
174 }