-
Notifications
You must be signed in to change notification settings - Fork 23
/
ContextManager.java
76 lines (65 loc) · 2.58 KB
/
ContextManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
* Copyright 2019 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.gestalt.assets.management;
import com.google.common.collect.Queues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.gestalt.naming.Name;
import java.util.Deque;
/**
* ContextManager provides the ability to set the module context in which a thread is currently running, and this context can be checked. In the asset system this
* is used to have the current context influence the resolution of assets.
*
* @author Immortius
*/
public final class ContextManager {
private static final Logger logger = LoggerFactory.getLogger(ContextManager.class);
private static final ThreadLocal<Deque<Name>> CONTEXT_STACK = ThreadLocal.withInitial(Queues::newArrayDeque);
private ContextManager() {
}
/**
* @return The Name of the module that is the current context of the thread. If there is no current context the result will be Name.EMPTY.
*/
public static Name getCurrentContext() {
Name context = CONTEXT_STACK.get().peek();
return (context != null) ? context : Name.EMPTY;
}
/**
* Sets the current context and returns a resource that should be closed when the context ends.
*
* @param moduleId The name of the module to make the current context
* @return A Context object that should be closed when the context ends. This will restore the preceding context if any.
*/
public static Context beginContext(final Name moduleId) {
CONTEXT_STACK.get().push(moduleId);
return new Context() {
@Override
public Name getContext() {
return moduleId;
}
@Override
public void close() {
Deque<Name> stack = CONTEXT_STACK.get();
if (!moduleId.equals(stack.pop())) {
logger.error("Module context ended out of sequence");
}
if (stack.isEmpty()) {
CONTEXT_STACK.remove();
}
}
};
}
}