All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.concurrent.runtime.ContextSetup Maven / Gradle / Ivy

There is a newer version: 8.0.0-JDK17-M12
Show newest version
/*
 * Copyright (c) 2022 Eclipse Foundation and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.concurrent.runtime;


import com.sun.enterprise.deployment.types.ConcurrencyContextType;
import com.sun.enterprise.deployment.types.CustomContextType;
import com.sun.enterprise.deployment.types.StandardContextType;

import jakarta.enterprise.concurrent.spi.ThreadContextProvider;
import jakarta.enterprise.concurrent.spi.ThreadContextSnapshot;

import java.io.Serializable;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.Set;

import static java.util.ServiceLoader.load;

/**
 * @author David Matejcek
 */
public class ContextSetup implements Serializable {
    private static final long serialVersionUID = 7817957604183520917L;
    private static final Logger LOG = System.getLogger(ContextSetup.class.getName());

    private final Set contextPropagate;
    private final Set contextClear;
    private final Set contextUnchanged;
    private transient Map allThreadContextProviders;


    public ContextSetup(Set propagated, Set cleared, Set unchanged) {
        this.contextPropagate = new HashSet<>(propagated);
        this.contextClear = new HashSet<>(cleared);
        this.contextUnchanged = new HashSet<>(unchanged);
    }


    public void reloadProviders(final ClassLoader loader) {
        this.allThreadContextProviders = loadAllProviders(loader);
        addRemaining(contextPropagate, contextClear, contextUnchanged, allThreadContextProviders);
        LOG.log(Level.DEBUG, "Available contexts: {0}", this);
    }


    public boolean isPropagated(StandardContextType contextType) {
        return contextPropagate.contains(contextType);
    }


    public boolean isClear(StandardContextType contextType) {
        return contextClear.contains(contextType);
    }


    public boolean isUnchanged(StandardContextType contextType) {
        return contextUnchanged.contains(contextType);
    }


    public List getThreadContextSnapshots(Map executionProperties) {
        LOG.log(Level.TRACE, "getThreadContextSnapshots(executionProperties={0})", executionProperties);
        final List snapshots = new ArrayList<>();
        contextPropagate.stream().map(allThreadContextProviders::get)
            .filter(Objects::nonNull).map(snapshot -> snapshot.currentContext(executionProperties))
            .forEach(snapshots::add);
        contextClear.stream().map(allThreadContextProviders::get)
            .filter(Objects::nonNull).map(snapshot -> snapshot.clearedContext(executionProperties))
            .forEach(snapshots::add);
        return snapshots;
    }


    @Override
    public String toString() {
        return super.toString() + "[propagated=" + contextPropagate + ", cleared=" + contextClear + ", unchanged="
            + contextUnchanged + "]";
    }


    private static Map loadAllProviders(ClassLoader loader) {
        LOG.log(Level.TRACE, "Using classloader: {0}", loader);
        ServiceLoader services = load(ThreadContextProvider.class, loader);
        Map providers = new HashMap<>();
        for (ThreadContextProvider service : services) {
            CustomContextType ctxType = new CustomContextType(service.getThreadContextType());
            providers.put(ctxType, service);
        }
        LOG.log(Level.DEBUG, "Detected ThreadContextProvider implementations: {0}", providers);
        return providers;
    }


    private static void addRemaining(Set propagated, Set clear,
        Set unchanged, Map allThreadContextProviders) {
        Set remaining = chooseSet(propagated, clear, unchanged);
        for (StandardContextType contextType : StandardContextType.values()) {
            if (contextType == StandardContextType.Remaining) {
                continue;
            }
            addIfNotInAnotherSet(contextType, remaining, propagated, clear, unchanged);
        }
        for (CustomContextType ctxType : allThreadContextProviders.keySet()) {
            addIfNotInAnotherSet(ctxType, remaining, propagated, clear, unchanged);
        }
    }


    private static Set chooseSet(Set propagated,
        Set clear, Set unchanged) {
        if (clear.contains(StandardContextType.Remaining)) {
            return clear;
        } else if (unchanged.contains(StandardContextType.Remaining)) {
            return unchanged;
        } else {
            return propagated;
        }
    }


    private static void addIfNotInAnotherSet(ConcurrencyContextType ctxType, Set remaining,
        Set propagated, Set clear,
        Set unchanged) {
        if (propagated.contains(ctxType) || clear.contains(ctxType) || unchanged.contains(ctxType)) {
            return;
        }
        remaining.add(ctxType);
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy