Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2022-2023 VMware Inc. or its affiliates, All Rights Reserved.
*
* 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
*
* https://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 reactor.core.publisher;
import java.util.AbstractQueue;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Queue;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import io.micrometer.context.ContextAccessor;
import io.micrometer.context.ContextRegistry;
import io.micrometer.context.ContextSnapshot;
import io.micrometer.context.ContextSnapshotFactory;
import io.micrometer.context.ThreadLocalAccessor;
import reactor.core.observability.SignalListener;
import reactor.util.annotation.Nullable;
import reactor.util.context.Context;
import reactor.util.context.ContextView;
/**
* Utility private class to detect if the context-propagation library is on the classpath and to offer
* ContextSnapshot support to {@link Flux} and {@link Mono}.
*
* @author Simon Baslé
*/finalclassContextPropagation{
staticfinal Function NO_OP = c -> c;
staticfinal Function WITH_GLOBAL_REGISTRY_NO_PREDICATE;
static ContextSnapshotFactory globalContextSnapshotFactory = null;
static {
WITH_GLOBAL_REGISTRY_NO_PREDICATE = ContextPropagationSupport.isContextPropagationAvailable() ?
new ContextCaptureNoPredicate() : NO_OP;
if (ContextPropagationSupport.isContextPropagation103Available()) {
globalContextSnapshotFactory = ContextSnapshotFactory.builder()
.clearMissing(false)
.build();
}
}
static FluxfluxRestoreThreadLocals(Flux flux){
returnnew FluxContextWriteRestoringThreadLocals<>(flux, Function.identity());
}
static MonomonoRestoreThreadLocals(Mono mono){
returnnew MonoContextWriteRestoringThreadLocals<>(mono, Function.identity());
}
staticvoidconfigureContextSnapshotFactory(boolean clearMissing){
if (ContextPropagationSupport.isContextPropagation103OnClasspath) {
globalContextSnapshotFactory = ContextSnapshotFactory.builder()
.clearMissing(clearMissing)
.build();
}
}
@SuppressWarnings("unchecked")
static ContextSnapshot.Scope setThreadLocals(Object context){
if (ContextPropagationSupport.isContextPropagation103OnClasspath) {
return globalContextSnapshotFactory.setThreadLocalsFrom(context);
}
else {
ContextRegistry registry = ContextRegistry.getInstance();
ContextAccessor contextAccessor = registry.getContextAccessorForRead(context);
Map
Note, this is only applied to {@link FluxTap}, {@link FluxTapFuseable},
* {@link MonoTap}, and {@link MonoTapFuseable}. The automatic propagation
* variants: {@link FluxTapRestoringThreadLocals} and
* {@link MonoTapRestoringThreadLocals} do not use this method.
* @param original the original {@link SignalListener} from the user
* @param contextSupplier supplies the potentially modified {@link Context} to
* restore {@link ThreadLocal} values from
* @return potentially wrapped {@link SignalListener} or the original
* @param type of handled values
*/
static SignalListenercontextRestoreForTap(final SignalListener original, Supplier contextSupplier){
if (!ContextPropagationSupport.isContextPropagationAvailable()) {
return original;
}
final Context ctx = contextSupplier.get();
if (ctx.isEmpty()) {
return original;
}
if (ContextPropagationSupport.isContextPropagation103OnClasspath) {
returnnew ContextRestore103SignalListener<>(original, ctx, globalContextSnapshotFactory);
}
else {
returnnew ContextRestoreSignalListener<>(original, ctx);
}
}
//the SignalListener implementation can be tested independently with a test-specific ContextRegistrystaticclassContextRestoreSignalListenerimplementsSignalListener{
final SignalListener original;
final ContextView context;
publicContextRestoreSignalListener(SignalListener original,
ContextView context){
this.original = original;
this.context = context;
}
ContextSnapshot.Scope restoreThreadLocals(){
return ContextSnapshot.setAllThreadLocalsFrom(this.context);
}
@OverridepublicfinalvoiddoFirst()throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doFirst();
}
}
@OverridepublicfinalvoiddoFinally(SignalType terminationType)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doFinally(terminationType);
}
}
@OverridepublicfinalvoiddoOnSubscription()throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnSubscription();
}
}
@OverridepublicfinalvoiddoOnFusion(int negotiatedFusion)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnFusion(negotiatedFusion);
}
}
@OverridepublicfinalvoiddoOnRequest(long requested)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnRequest(requested);
}
}
@OverridepublicfinalvoiddoOnCancel()throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnCancel();
}
}
@OverridepublicfinalvoiddoOnNext(T value)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnNext(value);
}
}
@OverridepublicfinalvoiddoOnComplete()throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnComplete();
}
}
@OverridepublicfinalvoiddoOnError(Throwable error)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnError(error);
}
}
@OverridepublicfinalvoiddoAfterComplete()throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doAfterComplete();
}
}
@OverridepublicfinalvoiddoAfterError(Throwable error)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doAfterError(error);
}
}
@OverridepublicfinalvoiddoOnMalformedOnNext(T value)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnMalformedOnNext(value);
}
}
@OverridepublicfinalvoiddoOnMalformedOnError(Throwable error)throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnMalformedOnError(error);
}
}
@OverridepublicfinalvoiddoOnMalformedOnComplete()throws Throwable {
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.doOnMalformedOnComplete();
}
}
@OverridepublicfinalvoidhandleListenerError(Throwable listenerError){
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
original.handleListenerError(listenerError);
}
}
@Overridepublicfinal Context addToContext(Context originalContext){
try (ContextSnapshot.Scope ignored = restoreThreadLocals()) {
return original.addToContext(originalContext);
}
}
}
//the SignalListener implementation can be tested independently with a test-specific ContextRegistrystaticfinalclassContextRestore103SignalListenerextendsContextRestoreSignalListener{
final ContextSnapshotFactory contextSnapshotFactory;
publicContextRestore103SignalListener(SignalListener original,
ContextView context, ContextSnapshotFactory contextSnapshotFactory){
super(original, context);
this.contextSnapshotFactory = contextSnapshotFactory;
}
ContextSnapshot.Scope restoreThreadLocals(){
return contextSnapshotFactory.setThreadLocalsFrom(this.context);
}
}
staticfinalclassContextCaptureNoPredicateimplementsFunction{
@Overridepublic Context apply(Context context){
return captureThreadLocals().updateContext(context);
}
}
staticfinalclassContextQueueextendsAbstractQueue{
staticfinal String NOT_SUPPORTED_MESSAGE = "ContextQueue wrapper is intended " +
"for use with instances returned by Queues class. Iterator based " +
"methods are usually unsupported.";
final Queue> envelopeQueue;
boolean cleanOnNull;
boolean hasPrevious = false;
Thread lastReader;
ContextSnapshot.Scope scope;
@SuppressWarnings({"unchecked", "rawtypes"})
ContextQueue(Queue queue) {
this.envelopeQueue = (Queue) queue;
}
@Overridepublicintsize(){
return envelopeQueue.size();
}
@Overridepublicbooleanoffer(T o){
ContextSnapshot contextSnapshot = captureThreadLocals();
return envelopeQueue.offer(new Envelope<>(o, contextSnapshot));
}
@Overridepublic T poll(){
Envelope envelope = envelopeQueue.poll();
if (envelope == null) {
if (cleanOnNull && scope != null) {
// clear thread-locals if they were just restored
scope.close();
}
cleanOnNull = true;
lastReader = Thread.currentThread();
hasPrevious = false;
returnnull;
}
restoreTheContext(envelope);
hasPrevious = true;
return envelope.body;
}
privatevoidrestoreTheContext(Envelope envelope){
ContextSnapshot contextSnapshot = envelope.contextSnapshot;
// tries to read existing Thread for existing ThreadLocals
ContextSnapshot currentContextSnapshot = captureThreadLocals();
if (!contextSnapshot.equals(currentContextSnapshot)) {
if (!hasPrevious || !Thread.currentThread().equals(this.lastReader)) {
// means context was restored form the envelope,// thus it has to be cleared
cleanOnNull = true;
lastReader = Thread.currentThread();
}
scope = contextSnapshot.setThreadLocals();
}
elseif (!hasPrevious || !Thread.currentThread().equals(this.lastReader)) {
// means same context was already available, no need to clean anything
cleanOnNull = false;
lastReader = Thread.currentThread();
}
}
@Override@Nullablepublic T peek(){
Envelope envelope = envelopeQueue.peek();
return envelope == null ? null : envelope.body;
}
@Overridepublic Iteratoriterator(){
thrownew UnsupportedOperationException(NOT_SUPPORTED_MESSAGE);
}
}
staticclassEnvelope{
final T body;
final ContextSnapshot contextSnapshot;
Envelope(T body, ContextSnapshot contextSnapshot) {
this.body = body;
this.contextSnapshot = contextSnapshot;
}
}
privatestaticclassReactorScopeImplimplementsContextSnapshot.Scope{
privatefinal Map previousValues;
privatefinal ContextRegistry contextRegistry;
privateReactorScopeImpl(Map previousValues,
ContextRegistry contextRegistry){
this.previousValues = previousValues;
this.contextRegistry = contextRegistry;
}
@Overridepublicvoidclose(){
for (ThreadLocalAccessor accessor : this.contextRegistry.getThreadLocalAccessors()) {
if (this.previousValues.containsKey(accessor.key())) {
Object previousValue = this.previousValues.get(accessor.key());
resetThreadLocalValue(accessor, previousValue);
}
}
}
@SuppressWarnings("unchecked")
privatevoidresetThreadLocalValue(ThreadLocalAccessor accessor, @Nullable V previousValue){
if (previousValue != null) {
((ThreadLocalAccessor) accessor).restore(previousValue);
}
else {
accessor.reset();
}
}
publicstatic ContextSnapshot.Scope from(@Nullable Map previousValues, ContextRegistry registry){
return (previousValues != null ? new ReactorScopeImpl(previousValues, registry) : () -> {
});
}
}
privatestaticclassReactorScopeImpl100implementsContextSnapshot.Scope{
privatefinal Map previousValues;
privatefinal ContextRegistry contextRegistry;
privateReactorScopeImpl100(Map previousValues,
ContextRegistry contextRegistry){
this.previousValues = previousValues;
this.contextRegistry = contextRegistry;
}
@Overridepublicvoidclose(){
for (ThreadLocalAccessor accessor : this.contextRegistry.getThreadLocalAccessors()) {
if (this.previousValues.containsKey(accessor.key())) {
Object previousValue = this.previousValues.get(accessor.key());
resetThreadLocalValue(accessor, previousValue);
}
}
}
@SuppressWarnings("unchecked")
privatevoidresetThreadLocalValue(ThreadLocalAccessor accessor, @Nullable V previousValue){
if (previousValue != null) {
((ThreadLocalAccessor) accessor).setValue(previousValue);
}
else {
accessor.reset();
}
}
publicstatic ContextSnapshot.Scope from(@Nullable Map previousValues, ContextRegistry registry){
return (previousValues != null ? new ReactorScopeImpl100(previousValues, registry) : () -> {
});
}
}
}