Skip to content

Commit

Permalink
feat(plugin): Allow to load plugin from multiple registries
Browse files Browse the repository at this point in the history
  • Loading branch information
brasseld committed May 12, 2017
1 parent ad922cc commit 4cf1c34
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 21 deletions.
@@ -0,0 +1,69 @@
/**
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* 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 io.gravitee.plugin.core.internal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
* @author David BRASSELY (david.brassely at graviteesource.com)
* @author GraviteeSource Team
*/
public class PluginRegistryConfiguration {

private final static String PLUGIN_PATH_PROPERTY = "plugins.path[%s]";

@Value("${plugins.path:${gravitee.home}/plugins}")
private String defaultPluginPath;

private String [] pluginsPath;

@Autowired
private Environment environment;

@PostConstruct
public void init() {
String key = String.format(PLUGIN_PATH_PROPERTY, 0);
List<String> paths = new ArrayList<>();

while (environment.containsProperty(key)) {
String pathProperty = environment.getProperty(key);
paths.add(pathProperty);

key = String.format(PLUGIN_PATH_PROPERTY, paths.size());
}

// Use default host if required
if(paths.isEmpty()){
paths.add(defaultPluginPath);
}

pluginsPath = paths.toArray(new String []{});
}

public String[] getPluginsPath() {
return pluginsPath;
}

public void setPluginsPath(String[] pluginsPath) {
this.pluginsPath = pluginsPath;
}
}
Expand Up @@ -23,7 +23,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.io.File;
import java.io.IOException;
Expand All @@ -49,8 +48,8 @@ public class PluginRegistryImpl extends AbstractService implements PluginRegistr

private final static String PLUGIN_MANIFEST_FILE = "plugin.properties";

@Value("${plugins.path:${gravitee.home}/plugins}")
private String workspacePath;
@Autowired
private PluginRegistryConfiguration configuration;

private boolean init = false;

Expand All @@ -59,6 +58,8 @@ public class PluginRegistryImpl extends AbstractService implements PluginRegistr
@Autowired
private EventManager eventManager;

private String [] workspacesPath;

/**
* Empty constructor is used to use a workspace directory defined from @Value annotation
* on workspacePath field.
Expand All @@ -67,7 +68,7 @@ public PluginRegistryImpl() {
}

public PluginRegistryImpl(String workspacePath) {
this.workspacePath = workspacePath;
this.workspacesPath = new String []{ workspacePath };
}

@Override
Expand All @@ -84,25 +85,40 @@ protected void doStart() throws Exception {
}

public void init() throws Exception {
if (workspacePath == null || workspacePath.isEmpty()) {
LOGGER.error("Plugin registry path is not specified.");
throw new RuntimeException("Plugin registry path is not specified.");
String [] pluginsPath = configuration.getPluginsPath();
if ((pluginsPath == null || pluginsPath.length == 0) && workspacesPath == null) {
LOGGER.error("No plugin registry configured.");
throw new RuntimeException("No plugin registry configured.");
}

// Use override configuration
if (workspacesPath != null) {
pluginsPath = workspacesPath;
}

File workspaceDir = new File(workspacePath);
for (String aWorkspacePath : pluginsPath) {
loadPluginsFromRegistry(aWorkspacePath);
}

printPlugins();
eventManager.publishEvent(PluginEvent.ENDED, null);
}

private void loadPluginsFromRegistry(String registryPath) throws Exception {
File registryDir = new File(registryPath);

// Quick sanity check on the install root
if (! workspaceDir.isDirectory()) {
LOGGER.error("Invalid registry directory, {} is not a directory.", workspaceDir.getAbsolutePath());
if (! registryDir.isDirectory()) {
LOGGER.error("Invalid registry directory, {} is not a directory.", registryDir.getAbsolutePath());
throw new RuntimeException("Invalid registry directory. Not a directory: "
+ workspaceDir.getAbsolutePath());
+ registryDir.getAbsolutePath());
}

loadPlugins(workspaceDir.getAbsolutePath());
loadPlugins(registryDir);
}

private void loadPlugins(String registryDir) throws Exception {
Path registryPath = FileSystems.getDefault().getPath(registryDir);
private void loadPlugins(File registryDir) throws Exception {
Path registryPath = registryDir.toPath();
LOGGER.info("Loading plugins from {}",registryDir);

try {
Expand All @@ -111,11 +127,8 @@ private void loadPlugins(String registryDir) throws Exception {

if (archiveIte.hasNext()) {
while (archiveIte.hasNext()) {
loadPlugin(archiveIte.next());
loadPlugin(registryDir, archiveIte.next());
}

printPlugins();
eventManager.publishEvent(PluginEvent.ENDED, null);
} else {
LOGGER.warn("No plugin has been found in {}", registryDir);
}
Expand Down Expand Up @@ -151,16 +164,17 @@ private void printPluginByType(PluginType pluginType) {
* dependency01.jar
* dependency02.jar
*
* @param registryDir The directory containing plugins
* @param pluginArchivePath The directory containing the plugin definition
*/
private void loadPlugin(Path pluginArchivePath) {
private void loadPlugin(File registryDir, Path pluginArchivePath) {
LOGGER.info("Loading plugin from {}", pluginArchivePath);

try {
// 1_ Extract plugin into a temporary working folder
String sPluginFile = pluginArchivePath.toFile().getName();
sPluginFile = sPluginFile.substring(0, sPluginFile.lastIndexOf(".zip"));
Path workDir = FileSystems.getDefault().getPath(workspacePath, ".work", sPluginFile);
Path workDir = FileSystems.getDefault().getPath(registryDir.getAbsolutePath(), ".work", sPluginFile);
FileUtils.delete(workDir);

FileUtils.unzip(pluginArchivePath.toString(), workDir);
Expand Down Expand Up @@ -370,4 +384,8 @@ public Path getPluginManifest() {
return pluginManifest;
}
}

public void setConfiguration(PluginRegistryConfiguration configuration) {
this.configuration = configuration;
}
}
Expand Up @@ -24,11 +24,17 @@
import org.springframework.context.annotation.Configuration;

/**
* @author David BRASSELY (brasseld at gmail.com)
* @author David BRASSELY (david.brassely at graviteesource.com)
* @author GraviteeSource Team
*/
@Configuration
public class PluginConfiguration {

@Bean
public PluginRegistryConfiguration pluginRegistryConfiguration() {
return new PluginRegistryConfiguration();
}

@Bean
public PluginRegistry pluginRegistry() {
return new PluginRegistryImpl();
Expand Down
Expand Up @@ -17,6 +17,7 @@

import io.gravitee.common.event.EventManager;
import io.gravitee.plugin.core.api.Plugin;
import io.gravitee.plugin.core.internal.PluginRegistryConfiguration;
import io.gravitee.plugin.core.internal.PluginRegistryImpl;
import org.junit.Assert;
import org.junit.Test;
Expand Down Expand Up @@ -49,6 +50,8 @@ public void startWithInexistantWorkspace() throws Exception {
public void startWithEmptyWorkspace() throws Exception {
URL dir = PluginRegistryTest.class.getResource("/io/gravitee/plugin/empty-workspace/");
PluginRegistryImpl pluginRegistry = new PluginRegistryImpl(URLDecoder.decode(dir.getPath(), "UTF-8"));
pluginRegistry.setConfiguration(mock(PluginRegistryConfiguration.class));
pluginRegistry.setEventManager(mock(EventManager.class));
pluginRegistry.start();

Assert.assertTrue(pluginRegistry.plugins().isEmpty());
Expand All @@ -59,6 +62,7 @@ public void startTwiceWorkspace() throws Exception {
URL dir = PluginRegistryTest.class.getResource("/io/gravitee/plugin/workspace/");
PluginRegistryImpl pluginRegistry = Mockito.spy(new PluginRegistryImpl(URLDecoder.decode(dir.getPath(), "UTF-8")));
pluginRegistry.setEventManager(mock(EventManager.class));
pluginRegistry.setConfiguration(mock(PluginRegistryConfiguration.class));
pluginRegistry.start();
verify(pluginRegistry, atMost(1)).init();

Expand All @@ -70,6 +74,8 @@ public void startTwiceWorkspace() throws Exception {
public void startWithWorkspace_noJar() throws Exception {
URL dir = PluginRegistryTest.class.getResource("/io/gravitee/plugin/invalid-workspace-nojar/");
PluginRegistryImpl pluginRegistry = new PluginRegistryImpl(URLDecoder.decode(dir.getPath(), "UTF-8"));
pluginRegistry.setConfiguration(mock(PluginRegistryConfiguration.class));
pluginRegistry.setEventManager(mock(EventManager.class));
pluginRegistry.start();

Assert.assertTrue(pluginRegistry.plugins().isEmpty());
Expand All @@ -80,6 +86,7 @@ public void startWithValidWorkspace_onePolicyDefinition() throws Exception {
URL dir = PluginRegistryTest.class.getResource("/io/gravitee/plugin/workspace/");
PluginRegistryImpl pluginRegistry = new PluginRegistryImpl(URLDecoder.decode(dir.getPath(), "UTF-8"));
pluginRegistry.setEventManager(mock(EventManager.class));
pluginRegistry.setConfiguration(mock(PluginRegistryConfiguration.class));
pluginRegistry.start();

Assert.assertEquals(1, pluginRegistry.plugins().size());
Expand All @@ -90,6 +97,7 @@ public void startWithValidWorkspace_checkPluginDescriptor() throws Exception {
URL dir = PluginRegistryTest.class.getResource("/io/gravitee/plugin/workspace/");
PluginRegistryImpl pluginRegistry = new PluginRegistryImpl(URLDecoder.decode(dir.getPath(), "UTF-8"));
pluginRegistry.setEventManager(mock(EventManager.class));
pluginRegistry.setConfiguration(mock(PluginRegistryConfiguration.class));
pluginRegistry.start();

Assert.assertEquals(1, pluginRegistry.plugins().size());
Expand Down

0 comments on commit 4cf1c34

Please sign in to comment.