Skip to contentPackage: DefaultContextManager$1
DefaultContextManager$1
Coverage
1: /*
2: * *********************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2024 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
23: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.role.impl;
28:
29: import javax.annotation.Nonnull;
30: import java.util.ArrayList;
31: import java.util.Collections;
32: import java.util.List;
33: import java.util.Optional;
34: import java.util.Stack;
35: import it.tidalwave.util.ContextManager;
36: import lombok.extern.slf4j.Slf4j;
37: import static it.tidalwave.util.CollectionUtils.reversed;
38: import static it.tidalwave.util.ShortNames.*;
39:
40: /***********************************************************************************************************************
41: *
42: * @author Fabrizio Giudici
43: *
44: **********************************************************************************************************************/
45: @Slf4j
46: public class DefaultContextManager implements ContextManager
47: {
48: /** Useful for troubleshooting in cases when multiple instances are erroneously created. */
49: private static final boolean DUMP_STACK_AT_CREATION = Boolean.getBoolean(
50: DefaultContextManager.class.getName() + ".dumpStackAtCreation");
51:
52: /** The list of global contexts, ordered by priority. */
53: private final List<Object> globalContexts = Collections.synchronizedList(new ArrayList<>());
54:
55: /** The list of local contexts, ordered by priority. */
56: private final ThreadLocal<Stack<Object>> localContexts = new ThreadLocal<>()
57: {
58: @Override @Nonnull
59: protected Stack<Object> initialValue ()
60: {
61: return new Stack<>();
62: }
63: };
64:
65: /*******************************************************************************************************************
66: *
67: *
68: *
69: ******************************************************************************************************************/
70: public DefaultContextManager()
71: {
72: if (DUMP_STACK_AT_CREATION)
73: {
74: try
75: {
76: throw new RuntimeException();
77: }
78: catch (Exception e)
79: {
80: log.trace(">>>> created context manager " + this, e);
81: }
82: }
83: }
84:
85: /*******************************************************************************************************************
86: *
87: * {@inheritDoc}
88: *
89: ******************************************************************************************************************/
90: @Override @Nonnull
91: public List<Object> getContexts()
92: {
93: final var contexts = reversed(new ArrayList<>(localContexts.get()));
94: contexts.addAll(0, globalContexts);
95: return contexts;
96: }
97:
98: /*******************************************************************************************************************
99: *
100: * {@inheritDoc}
101: *
102: ******************************************************************************************************************/
103: @Override @Nonnull @SuppressWarnings("BoundedWildcard")
104: public <T> Optional<T> findContextOfType (@Nonnull final Class<T> contextType)
105: {
106: for (final var context : getContexts())
107: {
108: if (contextType.isAssignableFrom(context.getClass()))
109: {
110: return Optional.of(contextType.cast(context));
111: }
112: }
113:
114: return Optional.empty();
115: }
116:
117: /*******************************************************************************************************************
118: *
119: * {@inheritDoc}
120: *
121: ******************************************************************************************************************/
122: @Override
123: public void addGlobalContext (@Nonnull final Object context)
124: {
125: globalContexts.add(context);
126: }
127:
128: /*******************************************************************************************************************
129: *
130: * {@inheritDoc}
131: *
132: ******************************************************************************************************************/
133: @Override
134: public void removeGlobalContext (@Nonnull final Object context)
135: {
136: globalContexts.remove(context);
137: }
138:
139: /*******************************************************************************************************************
140: *
141: * {@inheritDoc}
142: *
143: ******************************************************************************************************************/
144: @Override
145: public void addLocalContext (@Nonnull final Object context)
146: {
147: localContexts.get().push(context);
148: }
149:
150: /*******************************************************************************************************************
151: *
152: * {@inheritDoc}
153: *
154: ******************************************************************************************************************/
155: @Override
156: public void removeLocalContext (@Nonnull final Object context)
157: {
158: localContexts.get().remove(context);
159: }
160:
161: /*******************************************************************************************************************
162: *
163: * {@inheritDoc}
164: *
165: ******************************************************************************************************************/
166: @Override @Nonnull
167: public <T, E extends Throwable> T runEWithContexts (@Nonnull final SupplierWithException<T, E> supplier,
168: @Nonnull final Object ... contexts)
169: throws E
170: {
171: log.trace("runWithContexts({}, {})", shortId(supplier), shortIds(contexts));
172:
173: try (final var __ = binder(contexts))
174: {
175: if (log.isTraceEnabled())
176: {
177: log.trace(">>>> contexts now: {} - {}", shortIds(getContexts()), this);
178: }
179:
180: final var result = supplier.get();
181: log.trace(">>>> runWithContexts({}, {}) completed", shortId(supplier), shortIds(contexts));
182: return result;
183: }
184: }
185: }