changeset 1256:9f8cb76cec1d

Add a user-specific plugins directory Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-September/008215.html
author Omair Majid <omajid@redhat.com>
date Thu, 19 Sep 2013 16:18:08 -0400
parents ae64ab3629ca
children 264f429d2019
files config/src/main/java/com/redhat/thermostat/shared/config/Configuration.java config/src/test/java/com/redhat/thermostat/shared/config/ConfigurationTest.java integration-tests/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java integration-tests/src/test/java/com/redhat/thermostat/itest/PluginTest.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java
diffstat 8 files changed, 66 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/config/src/main/java/com/redhat/thermostat/shared/config/Configuration.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/config/src/main/java/com/redhat/thermostat/shared/config/Configuration.java	Thu Sep 19 16:18:08 2013 -0400
@@ -171,6 +171,10 @@
 
     /* Specific files and directories. All these methods should use the directories defined above */
 
+    public File getUserPluginRoot() throws InvalidConfigurationException {
+        return new File(getUserPersistentDataDirectory(), "plugins");
+    }
+
     public File getUserStorageDirectory() throws InvalidConfigurationException {
         return new File(getUserPersistentDataDirectory(), "db");
     }
--- a/config/src/test/java/com/redhat/thermostat/shared/config/ConfigurationTest.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/config/src/test/java/com/redhat/thermostat/shared/config/ConfigurationTest.java	Thu Sep 19 16:18:08 2013 -0400
@@ -102,6 +102,9 @@
                 config.getUserStoragePidFile().getCanonicalPath());
         Assert.assertEquals(userHome + s + "logs" + s + "db.log",
                 config.getUserStorageLogFile().getCanonicalPath());
+
+        Assert.assertEquals(userHome + s + "data" + s + "plugins",
+                config.getUserPluginRoot().getCanonicalPath());
     }
 
     @Test
@@ -120,6 +123,8 @@
         Assert.assertEquals("/var/lib/thermostat/db", config.getUserStorageDirectory().getCanonicalPath());
         Assert.assertEquals("/var/run/thermostat/db.pid", config.getUserStoragePidFile().getAbsolutePath());
         Assert.assertEquals("/var/log/thermostat/db.log", config.getUserStorageLogFile().getCanonicalPath());
+
+        Assert.assertEquals("/var/lib/thermostat/plugins", config.getUserPluginRoot().getCanonicalPath());
     }
 
     @Test
@@ -140,7 +145,10 @@
         Assert.assertEquals(prefix + "/var/lib/thermostat/db", config.getUserStorageDirectory().getCanonicalPath());
         Assert.assertEquals(prefix + "/var/run/thermostat/db.pid", config.getUserStoragePidFile().getAbsolutePath());
         Assert.assertEquals(prefix + "/var/log/thermostat/db.log", config.getUserStorageLogFile().getCanonicalPath());
+
+        Assert.assertEquals(prefix + "/var/lib/thermostat/plugins", config.getUserPluginRoot().getCanonicalPath());
     }
+
     @Test
     public void instantiationThrowsException() {
         try {
--- a/integration-tests/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java	Thu Sep 19 16:18:08 2013 -0400
@@ -93,7 +93,7 @@
         return "../distribution/target/image";
     }
 
-    public static String getPluginHome() {
+    public static String getSystemPluginHome() {
         return getThermostatHome() + "/plugins";
     }
 
--- a/integration-tests/src/test/java/com/redhat/thermostat/itest/PluginTest.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/PluginTest.java	Thu Sep 19 16:18:08 2013 -0400
@@ -51,21 +51,27 @@
 
 public class PluginTest extends IntegrationTest {
 
-    private static final String PLUGIN_HOME = getPluginHome();
+    private static final String PLUGIN_HOME = getSystemPluginHome();
 
-    private static NewCommandPlugin newPlugin = new NewCommandPlugin(PLUGIN_HOME + File.separator + "new");
+    private static NewCommandPlugin fooPlugin = new NewCommandPlugin("foo", "provides foo command", PLUGIN_HOME + File.separator + "new");
+    private static NewCommandPlugin userPlugin = new NewCommandPlugin(
+            "user",
+            "a plugin that is provided by the user",
+            getUserThermostatHome() + File.separator + "data" + File.separator + "plugins" + File.separator + "user");
     private static UnknownExtendsPlugin unknownExtension = new UnknownExtendsPlugin(PLUGIN_HOME + File.separator + "unknown");
 
     @BeforeClass
     public static void setUpOnce() {
-        newPlugin.install();
+        fooPlugin.install();
+        userPlugin.install();
         unknownExtension.install();
     }
 
     @AfterClass
     public static void tearDownOnce() {
         unknownExtension.uninstall();
-        newPlugin.uninstall();
+        userPlugin.uninstall();
+        fooPlugin.uninstall();
     }
 
     @Test
@@ -82,8 +88,10 @@
         assertTrue(stdOut.contains("ping"));
         assertTrue(stdOut.contains("shell"));
 
-        assertTrue(stdOut.contains(newPlugin.command));
-        assertTrue(stdOut.contains(newPlugin.description));
+        assertTrue(stdOut.contains(fooPlugin.command));
+        assertTrue(stdOut.contains(fooPlugin.description));
+
+        assertTrue(stdOut.contains(userPlugin.command));
 
         assertFalse(stdOut.contains(unknownExtension.command));
 
@@ -99,16 +107,16 @@
         private final String command;
         private final String description;
 
-        public NewCommandPlugin(String pluginLocation) {
+        public NewCommandPlugin(String command, String description, String pluginLocation) {
             this.pluginHome = pluginLocation;
 
-            this.command = "foo";
-            this.description = "foo plugin to foo bar";
+            this.command = command;
+            this.description = description;
         }
 
         private void install() {
             File home = new File(pluginHome);
-            if (!home.isDirectory() && !home.mkdir()) {
+            if (!home.isDirectory() && !home.mkdirs()) {
                 throw new AssertionError("could not create directory: " + pluginHome);
             }
 
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java	Thu Sep 19 16:18:08 2013 -0400
@@ -84,7 +84,8 @@
             CommandInfoSource builtInCommandSource =
                     new BuiltInCommandInfoSource(commandsDir, config.getSystemLibRoot().toString());
             CommandInfoSource pluginCommandSource = new PluginCommandInfoSource(
-                            config.getSystemLibRoot().toString(), config.getSystemPluginRoot().toString());
+                            config.getSystemLibRoot().toString(), config.getSystemPluginRoot().toString(),
+                            config.getUserPluginRoot().toString());
             CommandInfoSource commands = new CompoundCommandInfoSource(builtInCommandSource, pluginCommandSource);
 
             cmdInfoReg = context.registerService(CommandInfoSource.class, commands, null);
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java	Thu Sep 19 16:18:08 2013 -0400
@@ -39,6 +39,7 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -77,20 +78,19 @@
     private Map<String, BasicCommandInfo> allNewCommands = new HashMap<>();
     private Map<String, List<BundleInformation>> additionalBundlesForExistingCommands = new HashMap<>();
 
-    public PluginCommandInfoSource(String internalJarRoot, String pluginRootDir) {
-        this(new File(internalJarRoot), new File(pluginRootDir), new PluginConfigurationParser(), new UsageStringBuilder());
+    public PluginCommandInfoSource(String internalJarRoot, String systemPluginRootDir, String userPluginRootDir) {
+        this(new File(internalJarRoot), new File(systemPluginRootDir), new File(userPluginRootDir), new PluginConfigurationParser(), new UsageStringBuilder());
     }
 
-    PluginCommandInfoSource(File internalJarRoot, File pluginRootDir, PluginConfigurationParser parser, UsageStringBuilder usageBuilder) {
+    PluginCommandInfoSource(File internalJarRoot, File systemPluginRootDir, File userPluginRootDir, PluginConfigurationParser parser, UsageStringBuilder usageBuilder) {
         this.usageBuilder = usageBuilder;
 
-        File[] pluginDirs = pluginRootDir.listFiles();
-        if (pluginDirs == null) {
-            logger.log(Level.SEVERE, "plugin root dir " + pluginRootDir + " does not exist");
-            return;
-        }
+        List<File> pluginDirectories = new ArrayList<>();
 
-        for (File pluginDir : pluginDirs) {
+        addPluginDirectory(pluginDirectories, systemPluginRootDir);
+        addPluginDirectory(pluginDirectories, userPluginRootDir);
+
+        for (File pluginDir : pluginDirectories) {
             try {
                 File configurationFile = new File(pluginDir, PLUGIN_CONFIG_FILE);
                 PluginConfiguration pluginConfig = parser.parse(configurationFile);
@@ -111,8 +111,14 @@
         combineCommands();
     }
     
+    private void addPluginDirectory(List<File> allPluginDirectories, File aPluginRoot) {
+        File[] pluginDirs = aPluginRoot.listFiles();
+
+        if (pluginDirs != null) {
+            allPluginDirectories.addAll(Arrays.asList(pluginDirs));
+        }
+    }
    
-
     private void loadNewAndExtendedCommands(File coreJarRoot, File pluginDir,
             PluginConfiguration pluginConfig) {
 
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java	Thu Sep 19 16:18:08 2013 -0400
@@ -120,8 +120,8 @@
         PluginCommandInfoSource source2 = mock(PluginCommandInfoSource.class);
         when(source2.getCommandInfos()).thenReturn(new ArrayList<CommandInfo>());
         whenNew(PluginCommandInfoSource.class)
-                .withParameterTypes(String.class, String.class)
-                .withArguments(anyString(), anyString())
+                .withParameterTypes(String.class, String.class, String.class)
+                .withArguments(anyString(), anyString(), anyString())
                 .thenReturn(source2);
 
         CompoundCommandInfoSource commands = mock(CompoundCommandInfoSource.class);
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java	Wed Sep 18 10:17:35 2013 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java	Thu Sep 19 16:18:08 2013 -0400
@@ -72,7 +72,8 @@
 
     private Path testRoot;
     private Path jarRootDir;
-    private Path pluginRootDir;
+    private Path sysPluginRootDir;
+    private Path userPluginRootDir;
     private PluginConfigurationParser parser;
     private PluginConfiguration parserResult;
     private UsageStringBuilder usageBuilder;
@@ -85,8 +86,10 @@
         usageBuilder = mock(UsageStringBuilder.class);
 
         testRoot = Files.createTempDirectory("thermostat");
-        pluginRootDir = testRoot.resolve("plugins");
-        Files.createDirectory(pluginRootDir);
+        sysPluginRootDir = testRoot.resolve("plugins");
+        Files.createDirectory(sysPluginRootDir);
+        userPluginRootDir = testRoot.resolve("plugins-user");
+        Files.createDirectory(userPluginRootDir);
         jarRootDir = testRoot.resolve("libs");
         Files.createDirectories(jarRootDir);
     }
@@ -114,14 +117,14 @@
     @Test
     public void verifyParserIsInvokedOnAllConfigurationFiles() throws IOException, PluginConfigurationValidatorException {
         Path[] pluginDirs = new Path[] {
-                pluginRootDir.resolve("plugin1"),
-                pluginRootDir.resolve("plugin2"),
+                sysPluginRootDir.resolve("plugin1"),
+                sysPluginRootDir.resolve("plugin2"),
         };
         for (Path pluginDir : pluginDirs) {
             Files.createDirectory(pluginDir);
         }
 
-        new PluginCommandInfoSource(jarRootDir.toFile(), pluginRootDir.toFile(), parser, usageBuilder);
+        new PluginCommandInfoSource(jarRootDir.toFile(), sysPluginRootDir.toFile(), userPluginRootDir.toFile(), parser, usageBuilder);
 
         ArgumentCaptor<File> configFilesCaptor = ArgumentCaptor.forClass(File.class);
         verify(parser, times(pluginDirs.length)).parse(configFilesCaptor.capture());
@@ -137,12 +140,12 @@
     public void verifyMissingConfigurationFileIsHandledCorrectly() throws FileNotFoundException, PluginConfigurationValidatorException {
         when(parser.parse(isA(File.class))).thenThrow(new FileNotFoundException("test"));
 
-        new PluginCommandInfoSource(jarRootDir.toFile(), pluginRootDir.toFile(), parser, usageBuilder);
+        new PluginCommandInfoSource(jarRootDir.toFile(), sysPluginRootDir.toFile(), userPluginRootDir.toFile(), parser, usageBuilder);
     }
 
     @Test(expected = CommandInfoNotFoundException.class)
     public void verifyMissingCommandInfo() {
-        PluginCommandInfoSource source = new PluginCommandInfoSource(jarRootDir.toFile(), pluginRootDir.toFile(), parser, usageBuilder);
+        PluginCommandInfoSource source = new PluginCommandInfoSource(jarRootDir.toFile(), sysPluginRootDir.toFile(), userPluginRootDir.toFile(), parser, usageBuilder);
 
         source.getCommandInfo("TEST");
     }
@@ -151,7 +154,7 @@
     public void verifyCommandInfoObjectsToExtendExistingCommandsAreCreated() throws IOException {
         BundleInformation bundleInfo = new BundleInformation("plugin-bundle", "0.1");
 
-        Path pluginDir = pluginRootDir.resolve("plugin1");
+        Path pluginDir = sysPluginRootDir.resolve("plugin1");
         Files.createDirectory(pluginDir);
 
         CommandExtensions extensions = mock(CommandExtensions.class);
@@ -160,7 +163,7 @@
 
         when(parserResult.getExtendedCommands()).thenReturn(Arrays.asList(extensions));
 
-        PluginCommandInfoSource source = new PluginCommandInfoSource(jarRootDir.toFile(), pluginRootDir.toFile(), parser, usageBuilder);
+        PluginCommandInfoSource source = new PluginCommandInfoSource(jarRootDir.toFile(), sysPluginRootDir.toFile(), userPluginRootDir.toFile(), parser, usageBuilder);
 
         CommandInfo info = source.getCommandInfo("command-name");
         assertEquals("command-name", info.getName());
@@ -177,7 +180,7 @@
         final Set<Environment> ENVIRONMENTS = EnumSet.of(Environment.SHELL);
         BundleInformation bundleInfo = new BundleInformation("plugin-bundle", "0.1");
 
-        Path pluginDir = pluginRootDir.resolve("plugin1");
+        Path pluginDir = sysPluginRootDir.resolve("plugin1");
         Files.createDirectory(pluginDir);
 
         NewCommand cmd = mock(NewCommand.class);
@@ -190,7 +193,7 @@
 
         when(parserResult.getNewCommands()).thenReturn(Arrays.asList(cmd));
 
-        PluginCommandInfoSource source = new PluginCommandInfoSource(jarRootDir.toFile(), pluginRootDir.toFile(), parser, usageBuilder);
+        PluginCommandInfoSource source = new PluginCommandInfoSource(jarRootDir.toFile(), sysPluginRootDir.toFile(), userPluginRootDir.toFile(), parser, usageBuilder);
 
         CommandInfo result = source.getCommandInfo(NAME);