Merge "Make Plugin class abstract"
This commit is contained in:
@@ -0,0 +1,301 @@
|
|||||||
|
// 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.common.base.Strings;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gerrit.extensions.annotations.PluginData;
|
||||||
|
import com.google.gerrit.extensions.annotations.PluginName;
|
||||||
|
import com.google.gerrit.extensions.registration.RegistrationHandle;
|
||||||
|
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
|
||||||
|
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||||
|
import com.google.gerrit.server.PluginUser;
|
||||||
|
import com.google.gerrit.server.util.RequestContext;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.ProvisionException;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.jar.Attributes;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
class JarPlugin extends Plugin {
|
||||||
|
|
||||||
|
/** Unique key that changes whenever a plugin reloads. */
|
||||||
|
public static final class CacheKey {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
CacheKey(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
int id = System.identityHashCode(this);
|
||||||
|
return String.format("Plugin[%s@%x]", name, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Guice logs warnings about multiple injectors being created.
|
||||||
|
// Silence this in case HTTP plugins are used.
|
||||||
|
java.util.logging.Logger.getLogger("com.google.inject.servlet.GuiceFilter")
|
||||||
|
.setLevel(java.util.logging.Level.OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ApiType getApiType(Manifest manifest) throws InvalidPluginException {
|
||||||
|
Attributes main = manifest.getMainAttributes();
|
||||||
|
String v = main.getValue("Gerrit-ApiType");
|
||||||
|
if (Strings.isNullOrEmpty(v)
|
||||||
|
|| ApiType.EXTENSION.name().equalsIgnoreCase(v)) {
|
||||||
|
return ApiType.EXTENSION;
|
||||||
|
} else if (ApiType.PLUGIN.name().equalsIgnoreCase(v)) {
|
||||||
|
return ApiType.PLUGIN;
|
||||||
|
} else if (ApiType.JS.name().equalsIgnoreCase(v)) {
|
||||||
|
return ApiType.JS;
|
||||||
|
} else {
|
||||||
|
throw new InvalidPluginException("Invalid Gerrit-ApiType: " + v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final FileSnapshot snapshot;
|
||||||
|
private final JarFile jarFile;
|
||||||
|
private final Manifest manifest;
|
||||||
|
private final File dataDir;
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
private final boolean disabled;
|
||||||
|
private Class<? extends Module> sysModule;
|
||||||
|
private Class<? extends Module> sshModule;
|
||||||
|
private Class<? extends Module> httpModule;
|
||||||
|
|
||||||
|
private Injector sysInjector;
|
||||||
|
private Injector sshInjector;
|
||||||
|
private Injector httpInjector;
|
||||||
|
private LifecycleManager manager;
|
||||||
|
private List<ReloadableRegistrationHandle<?>> reloadableHandles;
|
||||||
|
|
||||||
|
public JarPlugin(String name,
|
||||||
|
PluginUser pluginUser,
|
||||||
|
File srcJar,
|
||||||
|
FileSnapshot snapshot,
|
||||||
|
JarFile jarFile,
|
||||||
|
Manifest manifest,
|
||||||
|
File dataDir,
|
||||||
|
ApiType apiType,
|
||||||
|
ClassLoader classLoader,
|
||||||
|
@Nullable Class<? extends Module> sysModule,
|
||||||
|
@Nullable Class<? extends Module> sshModule,
|
||||||
|
@Nullable Class<? extends Module> httpModule) {
|
||||||
|
super(name, srcJar, pluginUser, snapshot, apiType);
|
||||||
|
this.snapshot = snapshot;
|
||||||
|
this.jarFile = jarFile;
|
||||||
|
this.manifest = manifest;
|
||||||
|
this.dataDir = dataDir;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
this.disabled = srcJar.getName().endsWith(".disabled");
|
||||||
|
this.sysModule = sysModule;
|
||||||
|
this.sshModule = sshModule;
|
||||||
|
this.httpModule = httpModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
File getSrcJar() {
|
||||||
|
return getSrcFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getVersion() {
|
||||||
|
Attributes main = manifest.getMainAttributes();
|
||||||
|
return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean canReload() {
|
||||||
|
Attributes main = manifest.getMainAttributes();
|
||||||
|
String v = main.getValue("Gerrit-ReloadMode");
|
||||||
|
if (Strings.isNullOrEmpty(v) || "reload".equalsIgnoreCase(v)) {
|
||||||
|
return true;
|
||||||
|
} else if ("restart".equalsIgnoreCase(v)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
PluginLoader.log.warn(String.format(
|
||||||
|
"Plugin %s has invalid Gerrit-ReloadMode %s; assuming restart",
|
||||||
|
getName(), v));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isModified(File jar) {
|
||||||
|
return snapshot.lastModified() != jar.lastModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDisabled() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start(PluginGuiceEnvironment env) throws Exception {
|
||||||
|
RequestContext oldContext = env.enter(this);
|
||||||
|
try {
|
||||||
|
startPlugin(env);
|
||||||
|
} finally {
|
||||||
|
env.exit(oldContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startPlugin(PluginGuiceEnvironment env) throws Exception {
|
||||||
|
Injector root = newRootInjector(env);
|
||||||
|
manager = new LifecycleManager();
|
||||||
|
|
||||||
|
AutoRegisterModules auto = null;
|
||||||
|
if (sysModule == null && sshModule == null && httpModule == null) {
|
||||||
|
auto = new AutoRegisterModules(getName(), env, jarFile, classLoader);
|
||||||
|
auto.discover();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysModule != null) {
|
||||||
|
sysInjector = root.createChildInjector(root.getInstance(sysModule));
|
||||||
|
manager.add(sysInjector);
|
||||||
|
} else if (auto != null && auto.sysModule != null) {
|
||||||
|
sysInjector = root.createChildInjector(auto.sysModule);
|
||||||
|
manager.add(sysInjector);
|
||||||
|
} else {
|
||||||
|
sysInjector = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env.hasSshModule()) {
|
||||||
|
List<Module> modules = Lists.newLinkedList();
|
||||||
|
if (getApiType() == ApiType.PLUGIN) {
|
||||||
|
modules.add(env.getSshModule());
|
||||||
|
}
|
||||||
|
if (sshModule != null) {
|
||||||
|
modules.add(sysInjector.getInstance(sshModule));
|
||||||
|
sshInjector = sysInjector.createChildInjector(modules);
|
||||||
|
manager.add(sshInjector);
|
||||||
|
} else if (auto != null && auto.sshModule != null) {
|
||||||
|
modules.add(auto.sshModule);
|
||||||
|
sshInjector = sysInjector.createChildInjector(modules);
|
||||||
|
manager.add(sshInjector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env.hasHttpModule()) {
|
||||||
|
List<Module> modules = Lists.newLinkedList();
|
||||||
|
if (getApiType() == ApiType.PLUGIN) {
|
||||||
|
modules.add(env.getHttpModule());
|
||||||
|
}
|
||||||
|
if (httpModule != null) {
|
||||||
|
modules.add(sysInjector.getInstance(httpModule));
|
||||||
|
httpInjector = sysInjector.createChildInjector(modules);
|
||||||
|
manager.add(httpInjector);
|
||||||
|
} else if (auto != null && auto.httpModule != null) {
|
||||||
|
modules.add(auto.httpModule);
|
||||||
|
httpInjector = sysInjector.createChildInjector(modules);
|
||||||
|
manager.add(httpInjector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Injector newRootInjector(final PluginGuiceEnvironment env) {
|
||||||
|
List<Module> modules = Lists.newArrayListWithCapacity(4);
|
||||||
|
if (getApiType() == ApiType.PLUGIN) {
|
||||||
|
modules.add(env.getSysModule());
|
||||||
|
}
|
||||||
|
modules.add(new AbstractModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(PluginUser.class).toInstance(getPluginUser());
|
||||||
|
bind(String.class)
|
||||||
|
.annotatedWith(PluginName.class)
|
||||||
|
.toInstance(getName());
|
||||||
|
|
||||||
|
bind(File.class)
|
||||||
|
.annotatedWith(PluginData.class)
|
||||||
|
.toProvider(new Provider<File>() {
|
||||||
|
private volatile boolean ready;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File get() {
|
||||||
|
if (!ready) {
|
||||||
|
synchronized (dataDir) {
|
||||||
|
if (!dataDir.exists() && !dataDir.mkdirs()) {
|
||||||
|
throw new ProvisionException(String.format(
|
||||||
|
"Cannot create %s for plugin %s",
|
||||||
|
dataDir.getAbsolutePath(), getName()));
|
||||||
|
}
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataDir;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Guice.createInjector(modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop(PluginGuiceEnvironment env) {
|
||||||
|
if (manager != null) {
|
||||||
|
RequestContext oldContext = env.enter(this);
|
||||||
|
try {
|
||||||
|
manager.stop();
|
||||||
|
} finally {
|
||||||
|
env.exit(oldContext);
|
||||||
|
}
|
||||||
|
manager = null;
|
||||||
|
sysInjector = null;
|
||||||
|
sshInjector = null;
|
||||||
|
httpInjector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarFile getJarFile() {
|
||||||
|
return jarFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Injector getSysInjector() {
|
||||||
|
return sysInjector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Injector getSshInjector() {
|
||||||
|
return sshInjector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Injector getHttpInjector() {
|
||||||
|
return httpInjector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(RegistrationHandle handle) {
|
||||||
|
if (manager != null) {
|
||||||
|
if (handle instanceof ReloadableRegistrationHandle) {
|
||||||
|
if (reloadableHandles == null) {
|
||||||
|
reloadableHandles = Lists.newArrayList();
|
||||||
|
}
|
||||||
|
reloadableHandles.add((ReloadableRegistrationHandle<?>) handle);
|
||||||
|
}
|
||||||
|
manager.add(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,19 +16,11 @@ package com.google.gerrit.server.plugins;
|
|||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.gerrit.extensions.annotations.PluginData;
|
|
||||||
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.lifecycle.LifecycleManager;
|
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||||
import com.google.gerrit.server.PluginUser;
|
import com.google.gerrit.server.PluginUser;
|
||||||
import com.google.gerrit.server.util.RequestContext;
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
import com.google.inject.ProvisionException;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
|
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
|
||||||
|
|
||||||
@@ -41,7 +33,7 @@ import java.util.jar.Manifest;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class Plugin {
|
public abstract class Plugin {
|
||||||
public static enum ApiType {
|
public static enum ApiType {
|
||||||
EXTENSION, PLUGIN, JS;
|
EXTENSION, PLUGIN, JS;
|
||||||
}
|
}
|
||||||
@@ -61,13 +53,6 @@ public class Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
|
||||||
// Guice logs warnings about multiple injectors being created.
|
|
||||||
// Silence this in case HTTP plugins are used.
|
|
||||||
java.util.logging.Logger.getLogger("com.google.inject.servlet.GuiceFilter")
|
|
||||||
.setLevel(java.util.logging.Level.OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ApiType getApiType(Manifest manifest) throws InvalidPluginException {
|
static ApiType getApiType(Manifest manifest) throws InvalidPluginException {
|
||||||
Attributes main = manifest.getMainAttributes();
|
Attributes main = manifest.getMainAttributes();
|
||||||
String v = main.getValue("Gerrit-ApiType");
|
String v = main.getValue("Gerrit-ApiType");
|
||||||
@@ -83,238 +68,72 @@ public class Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final CacheKey cacheKey;
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final PluginUser pluginUser;
|
private final File srcFile;
|
||||||
private final File srcJar;
|
|
||||||
private final FileSnapshot snapshot;
|
|
||||||
private final JarFile jarFile;
|
|
||||||
private final Manifest manifest;
|
|
||||||
private final File dataDir;
|
|
||||||
private final ApiType apiType;
|
private final ApiType apiType;
|
||||||
private final ClassLoader classLoader;
|
|
||||||
private final boolean disabled;
|
private final boolean disabled;
|
||||||
private Class<? extends Module> sysModule;
|
private final CacheKey cacheKey;
|
||||||
private Class<? extends Module> sshModule;
|
private final PluginUser pluginUser;
|
||||||
private Class<? extends Module> httpModule;
|
private final FileSnapshot snapshot;
|
||||||
|
|
||||||
|
protected LifecycleManager manager;
|
||||||
|
|
||||||
private Injector sysInjector;
|
|
||||||
private Injector sshInjector;
|
|
||||||
private Injector httpInjector;
|
|
||||||
private LifecycleManager manager;
|
|
||||||
private List<ReloadableRegistrationHandle<?>> reloadableHandles;
|
private List<ReloadableRegistrationHandle<?>> reloadableHandles;
|
||||||
|
|
||||||
public Plugin(String name,
|
public Plugin(String name,
|
||||||
|
File srcFile,
|
||||||
PluginUser pluginUser,
|
PluginUser pluginUser,
|
||||||
File srcJar,
|
|
||||||
FileSnapshot snapshot,
|
FileSnapshot snapshot,
|
||||||
JarFile jarFile,
|
ApiType apiType) {
|
||||||
Manifest manifest,
|
|
||||||
File dataDir,
|
|
||||||
ApiType apiType,
|
|
||||||
ClassLoader classLoader,
|
|
||||||
@Nullable Class<? extends Module> sysModule,
|
|
||||||
@Nullable Class<? extends Module> sshModule,
|
|
||||||
@Nullable Class<? extends Module> httpModule) {
|
|
||||||
this.cacheKey = new CacheKey(name);
|
|
||||||
this.pluginUser = pluginUser;
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.srcJar = srcJar;
|
this.srcFile = srcFile;
|
||||||
this.snapshot = snapshot;
|
|
||||||
this.jarFile = jarFile;
|
|
||||||
this.manifest = manifest;
|
|
||||||
this.dataDir = dataDir;
|
|
||||||
this.apiType = apiType;
|
this.apiType = apiType;
|
||||||
this.classLoader = classLoader;
|
this.snapshot = snapshot;
|
||||||
this.disabled = srcJar.getName().endsWith(".disabled");
|
this.pluginUser = pluginUser;
|
||||||
this.sysModule = sysModule;
|
this.cacheKey = new Plugin.CacheKey(name);
|
||||||
this.sshModule = sshModule;
|
this.disabled = srcFile.getName().endsWith(".disabled");
|
||||||
this.httpModule = httpModule;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File getSrcJar() {
|
File getSrcFile() {
|
||||||
return srcJar;
|
return srcFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginUser getPluginUser() {
|
PluginUser getPluginUser() {
|
||||||
return pluginUser;
|
return pluginUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CacheKey getCacheKey() {
|
|
||||||
return cacheKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getVersion() {
|
public abstract String getVersion();
|
||||||
Attributes main = manifest.getMainAttributes();
|
|
||||||
return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ApiType getApiType() {
|
public ApiType getApiType() {
|
||||||
return apiType;
|
return apiType;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean canReload() {
|
public Plugin.CacheKey getCacheKey() {
|
||||||
Attributes main = manifest.getMainAttributes();
|
return cacheKey;
|
||||||
String v = main.getValue("Gerrit-ReloadMode");
|
|
||||||
if (Strings.isNullOrEmpty(v) || "reload".equalsIgnoreCase(v)) {
|
|
||||||
return true;
|
|
||||||
} else if ("restart".equalsIgnoreCase(v)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
PluginLoader.log.warn(String.format(
|
|
||||||
"Plugin %s has invalid Gerrit-ReloadMode %s; assuming restart",
|
|
||||||
name, v));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isModified(File jar) {
|
|
||||||
return snapshot.lastModified() != jar.lastModified();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDisabled() {
|
public boolean isDisabled() {
|
||||||
return disabled;
|
return disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start(PluginGuiceEnvironment env) throws Exception {
|
abstract void start(PluginGuiceEnvironment env) throws Exception;
|
||||||
RequestContext oldContext = env.enter(this);
|
|
||||||
try {
|
|
||||||
startPlugin(env);
|
|
||||||
} finally {
|
|
||||||
env.exit(oldContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startPlugin(PluginGuiceEnvironment env) throws Exception {
|
abstract void stop(PluginGuiceEnvironment env);
|
||||||
Injector root = newRootInjector(env);
|
|
||||||
manager = new LifecycleManager();
|
|
||||||
|
|
||||||
AutoRegisterModules auto = null;
|
public abstract JarFile getJarFile();
|
||||||
if (sysModule == null && sshModule == null && httpModule == null) {
|
|
||||||
auto = new AutoRegisterModules(name, env, jarFile, classLoader);
|
|
||||||
auto.discover();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sysModule != null) {
|
public abstract Injector getSysInjector();
|
||||||
sysInjector = root.createChildInjector(root.getInstance(sysModule));
|
|
||||||
manager.add(sysInjector);
|
|
||||||
} else if (auto != null && auto.sysModule != null) {
|
|
||||||
sysInjector = root.createChildInjector(auto.sysModule);
|
|
||||||
manager.add(sysInjector);
|
|
||||||
} else {
|
|
||||||
sysInjector = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env.hasSshModule()) {
|
|
||||||
List<Module> modules = Lists.newLinkedList();
|
|
||||||
if (apiType == ApiType.PLUGIN) {
|
|
||||||
modules.add(env.getSshModule());
|
|
||||||
}
|
|
||||||
if (sshModule != null) {
|
|
||||||
modules.add(sysInjector.getInstance(sshModule));
|
|
||||||
sshInjector = sysInjector.createChildInjector(modules);
|
|
||||||
manager.add(sshInjector);
|
|
||||||
} else if (auto != null && auto.sshModule != null) {
|
|
||||||
modules.add(auto.sshModule);
|
|
||||||
sshInjector = sysInjector.createChildInjector(modules);
|
|
||||||
manager.add(sshInjector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env.hasHttpModule()) {
|
|
||||||
List<Module> modules = Lists.newLinkedList();
|
|
||||||
if (apiType == ApiType.PLUGIN) {
|
|
||||||
modules.add(env.getHttpModule());
|
|
||||||
}
|
|
||||||
if (httpModule != null) {
|
|
||||||
modules.add(sysInjector.getInstance(httpModule));
|
|
||||||
httpInjector = sysInjector.createChildInjector(modules);
|
|
||||||
manager.add(httpInjector);
|
|
||||||
} else if (auto != null && auto.httpModule != null) {
|
|
||||||
modules.add(auto.httpModule);
|
|
||||||
httpInjector = sysInjector.createChildInjector(modules);
|
|
||||||
manager.add(httpInjector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Injector newRootInjector(final PluginGuiceEnvironment env) {
|
|
||||||
List<Module> modules = Lists.newArrayListWithCapacity(4);
|
|
||||||
if (apiType == ApiType.PLUGIN) {
|
|
||||||
modules.add(env.getSysModule());
|
|
||||||
}
|
|
||||||
modules.add(new AbstractModule() {
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(PluginUser.class).toInstance(pluginUser);
|
|
||||||
bind(String.class)
|
|
||||||
.annotatedWith(PluginName.class)
|
|
||||||
.toInstance(name);
|
|
||||||
|
|
||||||
bind(File.class)
|
|
||||||
.annotatedWith(PluginData.class)
|
|
||||||
.toProvider(new Provider<File>() {
|
|
||||||
private volatile boolean ready;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public File get() {
|
|
||||||
if (!ready) {
|
|
||||||
synchronized (dataDir) {
|
|
||||||
if (!dataDir.exists() && !dataDir.mkdirs()) {
|
|
||||||
throw new ProvisionException(String.format(
|
|
||||||
"Cannot create %s for plugin %s",
|
|
||||||
dataDir.getAbsolutePath(), name));
|
|
||||||
}
|
|
||||||
ready = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dataDir;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return Guice.createInjector(modules);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop(PluginGuiceEnvironment env) {
|
|
||||||
if (manager != null) {
|
|
||||||
RequestContext oldContext = env.enter(this);
|
|
||||||
try {
|
|
||||||
manager.stop();
|
|
||||||
} finally {
|
|
||||||
env.exit(oldContext);
|
|
||||||
}
|
|
||||||
manager = null;
|
|
||||||
sysInjector = null;
|
|
||||||
sshInjector = null;
|
|
||||||
httpInjector = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public JarFile getJarFile() {
|
|
||||||
return jarFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Injector getSysInjector() {
|
|
||||||
return sysInjector;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Injector getSshInjector() {
|
public abstract Injector getSshInjector();
|
||||||
return sshInjector;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Injector getHttpInjector() {
|
public abstract Injector getHttpInjector();
|
||||||
return httpInjector;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(RegistrationHandle handle) {
|
public void add(RegistrationHandle handle) {
|
||||||
if (manager != null) {
|
if (manager != null) {
|
||||||
@@ -339,4 +158,10 @@ public class Plugin {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "Plugin [" + name + "]";
|
return "Plugin [" + name + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract boolean canReload();
|
||||||
|
|
||||||
|
boolean isModified(File jar) {
|
||||||
|
return snapshot.lastModified() != jar.lastModified();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
|
|
||||||
log.info(String.format("Disabling plugin %s", name));
|
log.info(String.format("Disabling plugin %s", name));
|
||||||
File off = new File(pluginsDir, active.getName() + ".jar.disabled");
|
File off = new File(pluginsDir, active.getName() + ".jar.disabled");
|
||||||
active.getSrcJar().renameTo(off);
|
active.getSrcFile().renameTo(off);
|
||||||
|
|
||||||
unloadPlugin(active);
|
unloadPlugin(active);
|
||||||
try {
|
try {
|
||||||
@@ -240,7 +240,7 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
|
|
||||||
log.info(String.format("Enabling plugin %s", name));
|
log.info(String.format("Enabling plugin %s", name));
|
||||||
File on = new File(pluginsDir, off.getName() + ".jar");
|
File on = new File(pluginsDir, off.getName() + ".jar");
|
||||||
off.getSrcJar().renameTo(on);
|
off.getSrcFile().renameTo(on);
|
||||||
|
|
||||||
disabled.remove(name);
|
disabled.remove(name);
|
||||||
runPlugin(name, on, null);
|
runPlugin(name, on, null);
|
||||||
@@ -303,7 +303,7 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
String name = active.getName();
|
String name = active.getName();
|
||||||
try {
|
try {
|
||||||
log.info(String.format("Reloading plugin %s", name));
|
log.info(String.format("Reloading plugin %s", name));
|
||||||
runPlugin(name, active.getSrcJar(), active);
|
runPlugin(name, active.getSrcFile(), active);
|
||||||
} catch (PluginInstallException e) {
|
} catch (PluginInstallException e) {
|
||||||
log.warn(String.format("Cannot reload plugin %s", name), e.getCause());
|
log.warn(String.format("Cannot reload plugin %s", name), e.getCause());
|
||||||
throw e;
|
throw e;
|
||||||
@@ -469,7 +469,7 @@ public class PluginLoader implements LifecycleListener {
|
|||||||
Class<? extends Module> sysModule = load(sysName, pluginLoader);
|
Class<? extends Module> sysModule = load(sysName, pluginLoader);
|
||||||
Class<? extends Module> sshModule = load(sshName, pluginLoader);
|
Class<? extends Module> sshModule = load(sshName, pluginLoader);
|
||||||
Class<? extends Module> httpModule = load(httpName, pluginLoader);
|
Class<? extends Module> httpModule = load(httpName, pluginLoader);
|
||||||
Plugin plugin = new Plugin(name, pluginUserFactory.create(name),
|
Plugin plugin = new JarPlugin(name, pluginUserFactory.create(name),
|
||||||
srcJar, snapshot,
|
srcJar, snapshot,
|
||||||
jarFile, manifest,
|
jarFile, manifest,
|
||||||
new File(dataDir, name), type, pluginLoader,
|
new File(dataDir, name), type, pluginLoader,
|
||||||
|
|||||||
Reference in New Issue
Block a user