diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/FallbackRequestContext.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/FallbackRequestContext.java new file mode 100644 index 0000000000..686a108eae --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/FallbackRequestContext.java @@ -0,0 +1,40 @@ +// Copyright (C) 2012 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.util; + +import com.google.gerrit.server.AnonymousUser; +import com.google.gerrit.server.CurrentUser; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +/** + * The default RequestContext to use when not in a request scope e.g. + * ThreadLocalRequestContext is not set. + */ +@Singleton +public class FallbackRequestContext implements RequestContext { + + private final AnonymousUser user; + + @Inject + FallbackRequestContext(AnonymousUser user) { + this.user = user; + } + + @Override + public CurrentUser getCurrentUser() { + return user; + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestContext.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestContext.java new file mode 100644 index 0000000000..ca8573f764 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestContext.java @@ -0,0 +1,26 @@ +// Copyright (C) 2012 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.util; + +import com.google.gerrit.server.CurrentUser; + +/** + * The RequestContext is an interface exposing the fields that are needed + * by the GerritGlobalModule scope. + */ +public interface RequestContext { + + CurrentUser getCurrentUser(); +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/ThreadLocalRequestContext.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/ThreadLocalRequestContext.java new file mode 100644 index 0000000000..88240cab6b --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/ThreadLocalRequestContext.java @@ -0,0 +1,88 @@ +// Copyright (C) 2012 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.util; + +import com.google.common.base.Objects; +import com.google.gerrit.common.errors.NotSignedInException; +import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.IdentifiedUser; +import com.google.inject.AbstractModule; +import com.google.inject.Inject; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.ProvisionException; +import com.google.inject.name.Named; +import com.google.inject.name.Names; + +import javax.annotation.Nullable; + +/** + * ThreadLocalRequestContext manages the current RequestContext using a + * ThreadLocal. When the context is set, the fields exposed by the context + * are considered in scope. Otherwise, the FallbackRequestContext is used. + */ +public class ThreadLocalRequestContext { + private static final String FALLBACK = "FALLBACK"; + + public static Module module() { + return new AbstractModule() { + @Override + protected void configure() { + bind(ThreadLocalRequestContext.class); + bind(RequestContext.class).annotatedWith(Names.named(FALLBACK)) + .to(FallbackRequestContext.class); + } + + @Provides + RequestContext provideRequestContext( + @Named(FALLBACK) RequestContext fallback) { + return Objects.firstNonNull(local.get(), fallback); + } + + @Provides + CurrentUser provideCurrentUser(RequestContext ctx) { + return ctx.getCurrentUser(); + } + + @Provides + IdentifiedUser provideCurrentUser(CurrentUser user) { + if (user instanceof IdentifiedUser) { + return (IdentifiedUser) user; + } + throw new ProvisionException(NotSignedInException.MESSAGE, + new NotSignedInException()); + } + }; + } + + private static final ThreadLocal local = + new ThreadLocal(); + + @Inject + ThreadLocalRequestContext() { + } + + public RequestContext setContext(@Nullable RequestContext ctx) { + RequestContext old = getContext(); + local.set(ctx); + return old; + } + + @Nullable + public RequestContext getContext() { + return local.get(); + } +}