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