/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.communication.api;
import de.rcenvironment.core.communication.common.LogicalNodeId;
import de.rcenvironment.core.communication.common.LogicalNodeSessionId;
import de.rcenvironment.core.communication.rpc.internal.ServiceCallContextImpl;
import de.rcenvironment.toolkit.modules.concurrency.api.threadcontext.ThreadContext;
import de.rcenvironment.toolkit.modules.concurrency.api.threadcontext.ThreadContextBuilder;
import de.rcenvironment.toolkit.modules.concurrency.api.threadcontext.ThreadContextHolder;
import de.rcenvironment.toolkit.modules.concurrency.api.threadcontext.ThreadContextMemento;
import de.rcenvironment.toolkit.modules.concurrency.api.threadcontext.ThreadContextNameProvider;
/**
* Allows externally available service methods (and methods transitively called by them) to access the context of the remote service call
* that triggered their invocation. This is especially useful in cases where the {@link LogicalNodeId} or the {@link LogicalNodeSessionId}
* under which a service was called is relevant for its behavior.
*
* @author Robert Mischke
*/
public final class ServiceCallContextUtils {
private static final ThreadContextNameProvider THREAD_CONTEXT_NAME_PROVIDER = new ThreadContextNameProvider() {
@Override
public String getName(ThreadContext context) {
final ServiceCallContext scc = context.getAspect(ServiceCallContext.class);
return scc.toString();
}
};
private ServiceCallContextUtils() {}
/**
* @return The {@link ServiceCallContext} for the current {@link Thread}, or null if no context is available. Note that asynchronous
* tasks do not inherit the {@link ServiceCallContext} of their initiating {@link Thread} yet; this behavior will be added
* later.
*/
public static ServiceCallContext getCurrentServiceCallContext() {
return ThreadContextHolder.getCurrentContextAspect(ServiceCallContext.class);
}
/**
* Creates and registers a {@link ServiceCallContext} for the current {@link Thread}.
*
* @param caller the {@link LogicalNodeSessionId} used while invoking the local service method
* @param target the {@link LogicalNodeSessionId} under which the service method was called
* @param serviceName the name of the invoked service
* @param methodName the name of the invoked method
* @return a {@link ThreadContextMemento} to restore the previous {@link ThreadContext} with later (using
* {@link ThreadContextMemento#restore()})
*/
public static ThreadContextMemento attachServiceCallDataToThreadContext(final LogicalNodeSessionId caller,
final LogicalNodeSessionId target, String serviceName, String methodName) {
// construct object
final ServiceCallContext serviceCallContext = new ServiceCallContextImpl(caller, target, serviceName, methodName);
// attach to current thread's context
final ThreadContext newThreadContext = ThreadContextBuilder.fromCurrent()
.setAspect(ServiceCallContext.class, serviceCallContext)
.setNameProvider(THREAD_CONTEXT_NAME_PROVIDER)
.build();
return ThreadContextHolder.setCurrentContext(newThreadContext);
}
}