This method was the source of lots of complexity in reopening ReviewDbs in background threads and Guice request scopes. Thankfully we don't need it anymore. Change-Id: Ifd76484bcf308362c24ca7df38b07f604476c932
111 lines
3.1 KiB
Java
111 lines
3.1 KiB
Java
// Copyright (C) 2009 The Android Open Source Project
|
|
//
|
|
// 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 com.google.gerrit.server.git;
|
|
|
|
import com.google.gerrit.server.util.RequestContext;
|
|
import com.google.gerrit.server.util.ThreadLocalRequestContext;
|
|
import com.google.gerrit.server.util.ThreadLocalRequestScopePropagator;
|
|
import com.google.inject.Inject;
|
|
import com.google.inject.Key;
|
|
import com.google.inject.OutOfScopeException;
|
|
import com.google.inject.Provider;
|
|
import com.google.inject.Scope;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.concurrent.Callable;
|
|
|
|
public class PerThreadRequestScope {
|
|
public interface Scoper {
|
|
<T> Callable<T> scope(Callable<T> callable);
|
|
}
|
|
|
|
private static class Context {
|
|
private final Map<Key<?>, Object> map;
|
|
|
|
private Context() {
|
|
map = new HashMap<>();
|
|
}
|
|
|
|
private <T> T get(Key<T> key, Provider<T> creator) {
|
|
@SuppressWarnings("unchecked")
|
|
T t = (T) map.get(key);
|
|
if (t == null) {
|
|
t = creator.get();
|
|
map.put(key, t);
|
|
}
|
|
return t;
|
|
}
|
|
}
|
|
|
|
public static class Propagator extends ThreadLocalRequestScopePropagator<Context> {
|
|
@Inject
|
|
Propagator(ThreadLocalRequestContext local) {
|
|
super(REQUEST, current, local);
|
|
}
|
|
|
|
@Override
|
|
protected Context continuingContext(Context ctx) {
|
|
return new Context();
|
|
}
|
|
|
|
public <T> Callable<T> scope(RequestContext requestContext, Callable<T> callable) {
|
|
Context ctx = new Context();
|
|
Callable<T> wrapped = context(requestContext, cleanup(callable));
|
|
return () -> {
|
|
Context old = current.get();
|
|
current.set(ctx);
|
|
try {
|
|
return wrapped.call();
|
|
} finally {
|
|
current.set(old);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
private static final ThreadLocal<Context> current = new ThreadLocal<>();
|
|
|
|
private static Context requireContext() {
|
|
final Context ctx = current.get();
|
|
if (ctx == null) {
|
|
throw new OutOfScopeException("Not in command/request");
|
|
}
|
|
return ctx;
|
|
}
|
|
|
|
public static final Scope REQUEST =
|
|
new Scope() {
|
|
@Override
|
|
public <T> Provider<T> scope(Key<T> key, Provider<T> creator) {
|
|
return new Provider<T>() {
|
|
@Override
|
|
public T get() {
|
|
return requireContext().get(key, creator);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return String.format("%s[%s]", creator, REQUEST);
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "PerThreadRequestScope.REQUEST";
|
|
}
|
|
};
|
|
}
|