Export ServerInformation to extensions and plugins
Plugins can take this value by injection and learn the current server state during their own LifecycleListener. This enables a plugin to determine if it is loading as part of server startup, or because it was dynamically installed or reloaded by an administrator. Change-Id: Iac57e039ed9f9f3ecaf2f384c5a3c6a66223f5e1
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
// 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.extensions.systemstatus;
|
||||||
|
|
||||||
|
/** Exports current server information to an extension. */
|
||||||
|
public interface ServerInformation {
|
||||||
|
/** Current state of the server. */
|
||||||
|
public enum State {
|
||||||
|
/**
|
||||||
|
* The server is starting up, and network connections are not yet being
|
||||||
|
* accepted. Plugins or extensions starting during this time are starting
|
||||||
|
* for the first time in this process.
|
||||||
|
*/
|
||||||
|
STARTUP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server is running and handling requests. Plugins starting during this
|
||||||
|
* state may be reloading, or being installed into a running system.
|
||||||
|
*/
|
||||||
|
RUNNING,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server is attempting a graceful halt of operations and will exit (or
|
||||||
|
* be killed by the operating system) soon.
|
||||||
|
*/
|
||||||
|
SHUTDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
State getState();
|
||||||
|
}
|
@@ -19,6 +19,7 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.gerrit.extensions.annotations.PluginName;
|
import com.google.gerrit.extensions.annotations.PluginName;
|
||||||
import com.google.gerrit.extensions.registration.RegistrationHandle;
|
import com.google.gerrit.extensions.registration.RegistrationHandle;
|
||||||
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
|
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
|
||||||
|
import com.google.gerrit.extensions.systemstatus.ServerInformation;
|
||||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||||
import com.google.gerrit.lifecycle.LifecycleManager;
|
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
@@ -165,9 +166,16 @@ public class Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Injector newRootInjector(PluginGuiceEnvironment env) {
|
private Injector newRootInjector(PluginGuiceEnvironment env) {
|
||||||
return Guice.createInjector(
|
List<Module> modules = Lists.newArrayListWithCapacity(4);
|
||||||
env.getSysModule(),
|
modules.add(env.getSysModule());
|
||||||
new AbstractModule() {
|
final ServerInformation srvInfo = env.getServerInformation();
|
||||||
|
modules.add(new AbstractModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(ServerInformation.class).toInstance(srvInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
modules.add(new AbstractModule() {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(String.class)
|
bind(String.class)
|
||||||
@@ -175,6 +183,7 @@ public class Plugin {
|
|||||||
.toInstance(name);
|
.toInstance(name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return Guice.createInjector(modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
@@ -24,6 +24,7 @@ import com.google.gerrit.extensions.registration.DynamicSet;
|
|||||||
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
|
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
|
||||||
import com.google.gerrit.extensions.registration.RegistrationHandle;
|
import com.google.gerrit.extensions.registration.RegistrationHandle;
|
||||||
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
|
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
|
||||||
|
import com.google.gerrit.extensions.systemstatus.ServerInformation;
|
||||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Binding;
|
import com.google.inject.Binding;
|
||||||
@@ -56,6 +57,7 @@ import javax.inject.Inject;
|
|||||||
@Singleton
|
@Singleton
|
||||||
public class PluginGuiceEnvironment {
|
public class PluginGuiceEnvironment {
|
||||||
private final Injector sysInjector;
|
private final Injector sysInjector;
|
||||||
|
private final ServerInformation srvInfo;
|
||||||
private final CopyConfigModule copyConfigModule;
|
private final CopyConfigModule copyConfigModule;
|
||||||
private final List<StartPluginListener> onStart;
|
private final List<StartPluginListener> onStart;
|
||||||
private final List<ReloadPluginListener> onReload;
|
private final List<ReloadPluginListener> onReload;
|
||||||
@@ -76,8 +78,12 @@ public class PluginGuiceEnvironment {
|
|||||||
private Map<TypeLiteral<?>, DynamicMap<?>> httpMaps;
|
private Map<TypeLiteral<?>, DynamicMap<?>> httpMaps;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PluginGuiceEnvironment(Injector sysInjector, CopyConfigModule ccm) {
|
PluginGuiceEnvironment(
|
||||||
|
Injector sysInjector,
|
||||||
|
ServerInformation srvInfo,
|
||||||
|
CopyConfigModule ccm) {
|
||||||
this.sysInjector = sysInjector;
|
this.sysInjector = sysInjector;
|
||||||
|
this.srvInfo = srvInfo;
|
||||||
this.copyConfigModule = ccm;
|
this.copyConfigModule = ccm;
|
||||||
|
|
||||||
onStart = new CopyOnWriteArrayList<StartPluginListener>();
|
onStart = new CopyOnWriteArrayList<StartPluginListener>();
|
||||||
@@ -90,6 +96,10 @@ public class PluginGuiceEnvironment {
|
|||||||
sysMaps = dynamicMapsOf(sysInjector);
|
sysMaps = dynamicMapsOf(sysInjector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerInformation getServerInformation() {
|
||||||
|
return srvInfo;
|
||||||
|
}
|
||||||
|
|
||||||
boolean hasDynamicSet(TypeLiteral<?> type) {
|
boolean hasDynamicSet(TypeLiteral<?> type) {
|
||||||
return sysSets.containsKey(type)
|
return sysSets.containsKey(type)
|
||||||
|| (sshSets != null && sshSets.containsKey(type))
|
|| (sshSets != null && sshSets.containsKey(type))
|
||||||
|
@@ -17,6 +17,7 @@ package com.google.gerrit.server.plugins;
|
|||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gerrit.extensions.systemstatus.ServerInformation;
|
||||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||||
import com.google.gerrit.server.config.ConfigUtil;
|
import com.google.gerrit.server.config.ConfigUtil;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
@@ -59,6 +60,7 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
private final File pluginsDir;
|
private final File pluginsDir;
|
||||||
private final File tmpDir;
|
private final File tmpDir;
|
||||||
private final PluginGuiceEnvironment env;
|
private final PluginGuiceEnvironment env;
|
||||||
|
private final ServerInformationImpl srvInfoImpl;
|
||||||
private final ConcurrentMap<String, Plugin> running;
|
private final ConcurrentMap<String, Plugin> running;
|
||||||
private final Map<String, FileSnapshot> broken;
|
private final Map<String, FileSnapshot> broken;
|
||||||
private final ReferenceQueue<ClassLoader> cleanupQueue;
|
private final ReferenceQueue<ClassLoader> cleanupQueue;
|
||||||
@@ -68,10 +70,12 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
@Inject
|
@Inject
|
||||||
public PluginLoader(SitePaths sitePaths,
|
public PluginLoader(SitePaths sitePaths,
|
||||||
PluginGuiceEnvironment pe,
|
PluginGuiceEnvironment pe,
|
||||||
|
ServerInformationImpl sii,
|
||||||
@GerritServerConfig Config cfg) {
|
@GerritServerConfig Config cfg) {
|
||||||
pluginsDir = sitePaths.plugins_dir;
|
pluginsDir = sitePaths.plugins_dir;
|
||||||
tmpDir = sitePaths.tmp_dir;
|
tmpDir = sitePaths.tmp_dir;
|
||||||
env = pe;
|
env = pe;
|
||||||
|
srvInfoImpl = sii;
|
||||||
running = Maps.newConcurrentMap();
|
running = Maps.newConcurrentMap();
|
||||||
broken = Maps.newHashMap();
|
broken = Maps.newHashMap();
|
||||||
cleanupQueue = new ReferenceQueue<ClassLoader>();
|
cleanupQueue = new ReferenceQueue<ClassLoader>();
|
||||||
@@ -184,7 +188,9 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
@Override
|
@Override
|
||||||
public synchronized void start() {
|
public synchronized void start() {
|
||||||
log.info("Loading plugins from " + pluginsDir.getAbsolutePath());
|
log.info("Loading plugins from " + pluginsDir.getAbsolutePath());
|
||||||
|
srvInfoImpl.state = ServerInformation.State.STARTUP;
|
||||||
rescan(false);
|
rescan(false);
|
||||||
|
srvInfoImpl.state = ServerInformation.State.RUNNING;
|
||||||
if (scanner != null) {
|
if (scanner != null) {
|
||||||
scanner.start();
|
scanner.start();
|
||||||
}
|
}
|
||||||
@@ -195,6 +201,7 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
if (scanner != null) {
|
if (scanner != null) {
|
||||||
scanner.end();
|
scanner.end();
|
||||||
}
|
}
|
||||||
|
srvInfoImpl.state = ServerInformation.State.SHUTDOWN;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
boolean clean = !running.isEmpty();
|
boolean clean = !running.isEmpty();
|
||||||
for (Plugin p : running.values()) {
|
for (Plugin p : running.values()) {
|
||||||
|
@@ -14,11 +14,15 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.plugins;
|
package com.google.gerrit.server.plugins;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.systemstatus.ServerInformation;
|
||||||
import com.google.gerrit.lifecycle.LifecycleModule;
|
import com.google.gerrit.lifecycle.LifecycleModule;
|
||||||
|
|
||||||
public class PluginModule extends LifecycleModule {
|
public class PluginModule extends LifecycleModule {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
bind(ServerInformationImpl.class);
|
||||||
|
bind(ServerInformation.class).to(ServerInformationImpl.class);
|
||||||
|
|
||||||
bind(PluginGuiceEnvironment.class);
|
bind(PluginGuiceEnvironment.class);
|
||||||
bind(PluginLoader.class);
|
bind(PluginLoader.class);
|
||||||
bind(CopyConfigModule.class);
|
bind(CopyConfigModule.class);
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
// 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.plugins;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.systemstatus.ServerInformation;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class ServerInformationImpl implements ServerInformation {
|
||||||
|
volatile State state = State.STARTUP;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public State getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user