changeset 2283:bc41e22fcd76

Also look in user plugins dir for plugin jars. Reviewed-by: neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-May/018696.html PR2948
author Severin Gehwolf <sgehwolf@redhat.com>
date Tue, 03 May 2016 10:42:25 +0200
parents 3b3a9e977dd1
children 24356daad9c5
files launcher/src/main/java/com/redhat/thermostat/launcher/PluginDirFileVisitor.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java launcher/src/test/java/com/redhat/thermostat/launcher/PluginDirFileVisitorTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java
diffstat 4 files changed, 185 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/PluginDirFileVisitor.java	Tue May 03 10:42:25 2016 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * A simple file visitor for plugin directories. I.e. directories where
+ * Thermostat plugins are located.
+ *
+ */
+public class PluginDirFileVisitor extends SimpleFileVisitor<Path> {
+
+    private static final Path DONT_SCAN_DIR = Paths.get("plugin-libs");
+    
+    // package-private for testing
+    FileVisitResult previsitDir(Path file) {
+        Path fileName = file.getFileName();
+        if (fileName != null && fileName.equals(DONT_SCAN_DIR)) {
+            return FileVisitResult.SKIP_SUBTREE;
+        }
+        return FileVisitResult.CONTINUE;
+    }
+    
+    @Override
+    public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException {
+        return previsitDir(file);
+    }
+}
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java	Mon May 02 11:13:22 2016 +0200
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/BundleManagerImpl.java	Tue May 03 10:42:25 2016 +0200
@@ -42,8 +42,6 @@
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -66,14 +64,13 @@
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.launcher.BundleInformation;
 import com.redhat.thermostat.launcher.BundleManager;
+import com.redhat.thermostat.launcher.PluginDirFileVisitor;
 import com.redhat.thermostat.shared.config.CommonPaths;
 
 public class BundleManagerImpl extends BundleManager {
 
     private static final Logger logger = LoggingUtils.getLogger(BundleManagerImpl.class);
 
-    private static final Path DONT_SCAN_DIR = Paths.get("plugin-libs");
-
     // Bundle Name and version -> path (with symlinks resolved)
     // Match FrameworkProvider which uses canonical/symlink-resolved paths. If
     // there is a mismatch, there are going to be clashes with trying to load
@@ -82,7 +79,6 @@
     // http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1514
     private final Map<BundleInformation, Path> known;
     private CommonPaths paths;
-    private boolean printOSGiInfo = false;
     private boolean ignoreBundleVersions = false;
     private BundleLoader loader;
 
@@ -92,49 +88,53 @@
         this.paths = paths;
         loader = new BundleLoader();
 
-        scanForBundles();
+        scanForBundles(paths, known);
     }
 
-    private void scanForBundles() {
+    private static void scanForBundles(CommonPaths paths, Map<BundleInformation, Path> known) {
         long t1 = System.nanoTime();
 
         final FileInspector inspector = new FileInspector(known);
         try {
             // Don't scan libs folder recursively. We only do that for the
-            // plugins folder
+            // plugins folders
             for (File file: paths.getSystemLibRoot().listFiles()) {
                 inspector.inspectFile(file);
             }
-            Files.walkFileTree(paths.getSystemPluginRoot().toPath(), new SimpleFileVisitor<Path>() {
-                
-                @Override
-                public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException {
-                    // Don't visit directories with name "plugin-libs"
-                    return previsitDir(file);
-                }
-                
-                @Override
-                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-                    inspector.inspectFile(file.toFile());
-                    return FileVisitResult.CONTINUE;
-                }
-
-            });
+            Path[] pluginsFolders = getPluginRoots(paths);
+            for (Path p: pluginsFolders) {
+                Files.walkFileTree(p, new PluginDirFileVisitor() {
+                    
+                    @Override
+                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                        inspector.inspectFile(file.toFile());
+                        return FileVisitResult.CONTINUE;
+                    }
+    
+                });
+            }
         } catch (IOException e) {
             logger.log(Level.WARNING, "Error scanning bundles for metadata", e);
         }
 
         long t2 = System.nanoTime();
-        if (printOSGiInfo) {
-            logger.fine("Found: " + known.size() + " bundles");
-            logger.fine("Took " + (t2 -t1) + "ns");
-        }
+        logger.fine("Found: " + known.size() + " bundles");
+        logger.fine("Took " + (t2 -t1) + "ns");
 
         for (Entry<BundleInformation, Path> bundles : known.entrySet()) {
             logger.finest(bundles.getKey().toString() + " is at " + bundles.getValue().toString());
         }
     }
 
+    /** For TESTS only */
+    static Path[] getPluginRoots(CommonPaths paths) {
+        Path[] pluginsFolders = new Path[] {
+                paths.getSystemPluginRoot().toPath(),
+                paths.getUserPluginRoot().toPath()
+        };
+        return pluginsFolders;
+    }
+
     /** For TESTS only: explicitly specify known bundles */
     void setKnownBundles(Map<BundleInformation,Path> knownData) {
         known.clear();
@@ -142,19 +142,9 @@
             known.put(entry.getKey(), entry.getValue());
         }
     }
-    
-    // package-private for testing
-    FileVisitResult previsitDir(Path file) {
-        Path fileName = file.getFileName();
-        if (fileName != null && fileName.equals(DONT_SCAN_DIR)) {
-            return FileVisitResult.SKIP_SUBTREE;
-        }
-        return FileVisitResult.CONTINUE;
-    }
 
     /* Used via reflection from launcher */
     public void setPrintOSGiInfo(boolean printOSGiInfo) {
-        this.printOSGiInfo = printOSGiInfo;
         loader.setPrintOSGiInfo(printOSGiInfo);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/PluginDirFileVisitorTest.java	Tue May 03 10:42:25 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.Test;
+
+public class PluginDirFileVisitorTest {
+
+    @Test
+    public void verifyDontScanDirIsNotVisited() throws FileNotFoundException, IOException {
+        PluginDirFileVisitor visitor = new PluginDirFileVisitor();
+        Path skipMe = Paths.get("plugin-libs");
+        FileVisitResult result = visitor.previsitDir(skipMe);
+        assertEquals(FileVisitResult.SKIP_SUBTREE, result);
+    }
+    
+    @Test
+    public void verifyRegularDirIsVisited() throws FileNotFoundException, IOException {
+        PluginDirFileVisitor visitor = new PluginDirFileVisitor();
+        Path pathNotToSkip = Paths.get("/path/to/plugins/vm-byteman");
+        FileVisitResult result = visitor.previsitDir(pathNotToSkip);
+        assertEquals(FileVisitResult.CONTINUE, result);
+    }
+}
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java	Mon May 02 11:13:22 2016 +0200
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/BundleManagerImplTest.java	Tue May 03 10:42:25 2016 +0200
@@ -46,7 +46,6 @@
 import static org.powermock.api.mockito.PowerMockito.whenNew;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.nio.file.FileVisitResult;
@@ -58,8 +57,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.junit.After;
 import org.junit.Before;
@@ -105,6 +106,7 @@
         paths = mock(CommonPaths.class);
         when(paths.getSystemLibRoot()).thenReturn(jarRootDir.toFile());
         when(paths.getSystemPluginRoot()).thenReturn(pluginRootDir.toFile());
+        when(paths.getUserPluginRoot()).thenReturn(pluginRootDir.toFile());
 
         theContext = mock(BundleContext.class);
         theFramework = mock(Framework.class);
@@ -292,19 +294,27 @@
     }
     
     @Test
-    public void verifyDontScanDirIsNotVisited() throws FileNotFoundException, IOException {
-        BundleManagerImpl manager = new BundleManagerImpl(paths);
-        Path skipMe = Paths.get("plugin-libs");
-        FileVisitResult result = manager.previsitDir(skipMe);
-        assertEquals(FileVisitResult.SKIP_SUBTREE, result);
-    }
-    
-    @Test
-    public void verifyRegularDirIsVisited() throws FileNotFoundException, IOException {
-        BundleManagerImpl manager = new BundleManagerImpl(paths);
-        Path pathNotToSkip = Paths.get("/path/to/plugins/vm-byteman");
-        FileVisitResult result = manager.previsitDir(pathNotToSkip);
-        assertEquals(FileVisitResult.CONTINUE, result);
+    public void verifyUserPluginsAreUsedForDepScanning() throws Exception {
+        CommonPaths customPaths = mock(CommonPaths.class);
+        File systemPluginsFile = mock(File.class);
+        Path systemPluginsPath = mock(Path.class);
+        when(systemPluginsFile.toPath()).thenReturn(systemPluginsPath);
+        File userPluginsFile = mock(File.class);
+        Path userPluginsPath = mock(Path.class);
+        when(userPluginsFile.toPath()).thenReturn(userPluginsPath);
+        when(customPaths.getSystemPluginRoot()).thenReturn(systemPluginsFile);
+        when(customPaths.getUserPluginRoot()).thenReturn(userPluginsFile);
+        
+        Path[] paths = BundleManagerImpl.getPluginRoots(customPaths);
+        assertEquals(2, paths.length);
+        
+        Set<Path> expected = new HashSet<>();
+        expected.add(systemPluginsPath);
+        expected.add(userPluginsPath);
+        
+        Set<Path> actual = new HashSet<>();
+        actual.addAll(Arrays.asList(paths));
+        assertEquals(expected, actual);
     }
 
 }