]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-1862:
authorGodin <mandrikov@gmail.com>
Sat, 16 Oct 2010 22:18:26 +0000 (22:18 +0000)
committerGodin <mandrikov@gmail.com>
Sat, 16 Oct 2010 22:18:26 +0000 (22:18 +0000)
* Upgrade to sonar-update-center-common 0.3-SNAPSHOT
* Add column 'child_first_classloader' to table 'plugins'
* Add possibility to use child-first classloader

16 files changed:
pom.xml
sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java
sonar-core/src/main/java/org/sonar/core/classloaders/ClassLoadersCollection.java
sonar-core/src/main/java/org/sonar/core/plugin/JpaPlugin.java
sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java
sonar-core/src/test/java/org/sonar/core/plugin/JpaPluginDaoTest.java
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/removePreviousFilesWhenRegisteringPlugin-result.xml
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/saveDeprecatedPlugin-result.xml
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/savePluginAndFiles-result.xml
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/shared.xml
sonar-server/src/main/java/org/sonar/server/plugins/PluginClassLoaders.java
sonar-server/src/main/java/org/sonar/server/plugins/PluginMetadata.java
sonar-server/src/main/webapp/WEB-INF/db/migrate/142_add_plugins_child_first_classloader_column.rb [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/plugins/PluginClassLoadersTest.java
sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java
sonar-server/src/test/java/org/sonar/server/plugins/PluginMetadataTest.java

diff --git a/pom.xml b/pom.xml
index a2b7336a357d3f1496fac8d3fb3af97732878bfb..7fefd90b14748fb305b62f6b36cac4b7ee213c5f 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -386,7 +386,7 @@ mmmm
       <dependency>
         <groupId>org.codehaus.sonar</groupId>
         <artifactId>sonar-update-center-common</artifactId>
-        <version>0.2</version>
+        <version>0.3-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>org.codehaus.sonar</groupId>
index e831faaee99b6f44b59b868f6e910f4294d13159..97e3393aa05f12f2655f51b8317dd0d746842872 100644 (file)
@@ -38,11 +38,11 @@ import org.sonar.core.plugin.JpaPlugin;
 import org.sonar.core.plugin.JpaPluginDao;
 import org.sonar.core.plugin.JpaPluginFile;
 
-import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Lists;
 
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.Set;
+import java.util.List;
 
 public class BatchPluginRepository extends AbstractPluginRepository {
 
@@ -66,30 +66,25 @@ public class BatchPluginRepository extends AbstractPluginRepository {
   }
 
   public void start() {
-    HashMultimap<String, URL> urlsByKey = HashMultimap.create();
-    for (JpaPluginFile pluginFile : dao.getPluginFiles()) {
-      try {
-        String key = pluginFile.getPluginKey();
-        URL url = new URL(baseUrl + pluginFile.getPath());
-        urlsByKey.put(key, url);
-
-      } catch (MalformedURLException e) {
-        throw new SonarException("Can not build the classloader of the plugin " + pluginFile.getPluginKey(), e);
-      }
-    }
-
     classLoaders = new ClassLoadersCollection(Thread.currentThread().getContextClassLoader());
-    for (String key : urlsByKey.keySet()) {
-      Set<URL> urls = urlsByKey.get(key);
-
+    for (JpaPlugin pluginMetadata : dao.getPlugins()) {
+      String key = pluginMetadata.getKey();
+      List<URL> urls = Lists.newArrayList();
+      for (JpaPluginFile pluginFile : pluginMetadata.getFiles()) {
+        try {
+          URL url = new URL(baseUrl + pluginFile.getPath());
+          urls.add(url);
+        } catch (MalformedURLException e) {
+          throw new SonarException("Can not build the classloader of the plugin " + pluginFile.getPluginKey(), e);
+        }
+      }
       if (LOG.isDebugEnabled()) {
         LOG.debug("Classloader of plugin " + key + ":");
         for (URL url : urls) {
           LOG.debug("   -> " + url);
         }
       }
-
-      classLoaders.createClassLoader(key, urls);
+      classLoaders.createClassLoader(key, urls, pluginMetadata.isUseChildFirstClassLoader() == Boolean.TRUE);
     }
     classLoaders.done();
   }
index 1279edc961ea87caf33c56cc898baab605766945..eed29008bf70f367f4f57de5d772b07ca35c457e 100644 (file)
@@ -39,18 +39,6 @@ public class ClassLoadersCollection {
     this.baseClassLoader = baseClassLoader;
   }
 
-  /**
-   * Generates URLClassLoader with parent-first delegation model.
-   * 
-   * @param key plugin key
-   * @param urls libraries
-   * @return created ClassLoader, but actually this method shouldn't return anything,
-   *         because dependencies must be established - see {@link #done()}.
-   */
-  public ClassLoader createClassLoader(String key, Collection<URL> urls) {
-    return createClassLoader(key, urls, false);
-  }
-
   /**
    * Generates URLClassLoader with specified delegation model.
    * 
index c178f59acaafeedf1c9c43e03ad488ca60568d16..27dfc80738d8fe24a2f8d438fef1ce2e488d3a87 100644 (file)
@@ -25,15 +25,21 @@ import org.apache.commons.lang.builder.ToStringStyle;
 import org.hibernate.annotations.Cascade;
 import org.sonar.api.database.BaseIdentifiable;
 
-import javax.persistence.*;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
 /**
  * Installed plugins
- *
+ * 
  * @since 2.2
  */
 @Entity
@@ -72,6 +78,9 @@ public class JpaPlugin extends BaseIdentifiable {
 
   @Column(name = "core", updatable = true, nullable = true)
   private Boolean core;
+  
+  @Column(name = "child_first_classloader", updatable = true, nullable = true)
+  private Boolean childFirstClassLoader;
 
   @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
             org.hibernate.annotations.CascadeType.DELETE,
@@ -200,6 +209,15 @@ public class JpaPlugin extends BaseIdentifiable {
     return this;
   }
 
+  public Boolean isUseChildFirstClassLoader() {
+    return childFirstClassLoader;
+  }
+
+  public JpaPlugin setUseChildFirstClassLoader(boolean use) {
+    this.childFirstClassLoader = use;
+    return this;
+  }
+
   public void createFile(String filename) {
     JpaPluginFile file = new JpaPluginFile(this, filename);
     this.files.add(file);
@@ -212,7 +230,7 @@ public class JpaPlugin extends BaseIdentifiable {
   public void removeFiles() {
     files.clear();
   }
-  
+
   @Override
   public boolean equals(Object o) {
     if (this == o) {
@@ -241,7 +259,6 @@ public class JpaPlugin extends BaseIdentifiable {
         .toString();
   }
 
-
   public static JpaPlugin create(String pluginKey) {
     return new JpaPlugin(pluginKey);
   }
index 532c7b72b6b701c7ac70d60fed548298da16cc13..c6d4e942160c935de0e90118bca07bf9ee4976db 100644 (file)
@@ -30,7 +30,7 @@ import java.sql.Statement;
 public class SchemaMigration {
 
   public final static int VERSION_UNKNOWN = -1;
-  public static final int LAST_VERSION = 141;
+  public static final int LAST_VERSION = 142;
 
   public final static String TABLE_NAME = "schema_migrations";
 
index ba4e26a322b917d72ed031f5fcd2b777faa236c4..878c492c89bebd2162573b4731dccc12b10d4517 100644 (file)
@@ -56,6 +56,7 @@ public class JpaPluginDaoTest extends AbstractDbUnitTestCase {
     setupData("shared");
     JpaPlugin pmd = JpaPlugin.create("pmd");
     pmd.setCore(false);
+    pmd.setUseChildFirstClassLoader(false);
     pmd.setName("PMD");
     pmd.setVersion("2.2");
     pmd.setPluginClass("org.sonar.pmd.Main");
@@ -73,6 +74,7 @@ public class JpaPluginDaoTest extends AbstractDbUnitTestCase {
     setupData("shared");
     JpaPlugin pmd = JpaPlugin.create("pmd");
     pmd.setCore(false);
+    pmd.setUseChildFirstClassLoader(false);
     pmd.setName("PMD");
     pmd.setPluginClass("org.sonar.pmd.Main");
 
index e7f3523119d705ed46e6c39916d95cf63b4f5269..579a381a7393e9432cba485e66ce5a9d55cc59ea 100644 (file)
@@ -1,6 +1,6 @@
 <dataset>
   <plugins id="1" name="Checkstyle" plugin_key="checkstyle" organization="[null]" organization_url="[null]" license="[null]" homepage="[null]"
-           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" version="2.2" />
+           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2" />
 
   <plugin_files id="3" plugin_id="1" filename="newfile.jar"/>
 </dataset>
\ No newline at end of file
index aa6e51ec2cd6caf28b56ee1a78856dc7f32307c5..38f8e3d72d1eb927792b20a65f31ec872cce98a1 100644 (file)
@@ -1,9 +1,9 @@
 <dataset>
   <plugins id="1" name="Checkstyle" plugin_key="checkstyle" organization="[null]" organization_url="[null]" license="[null]" homepage="[null]"
-           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" version="2.2"/>
+           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2"/>
 
   <plugins id="2" name="PMD" plugin_key="pmd" organization="[null]" organization_url="[null]" license="[null]" homepage="[null]"
-           description="[null]" installation_date="[null]" plugin_class="org.sonar.pmd.Main" core="false" version="[null]" />
+           description="[null]" installation_date="[null]" plugin_class="org.sonar.pmd.Main" core="false" child_first_classloader="false" version="[null]" />
 
   <plugin_files id="1" plugin_id="1" filename="checkstyle.jar"/>
   <plugin_files id="2" plugin_id="1" filename="checkstyle-extension.jar"/>
index 6c2159213575f26030fc6a9f5874e9fedf28d33a..2ca3c309e6df7fc1f7319cfb52efd34107e42b8c 100644 (file)
@@ -1,9 +1,9 @@
 <dataset>
   <plugins id="1" name="Checkstyle" plugin_key="checkstyle" organization="[null]" organization_url="[null]" license="[null]" homepage="[null]"
-           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" version="2.2"/>
+           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2"/>
 
   <plugins id="2" name="PMD" plugin_key="pmd" organization="[null]" organization_url="[null]" license="[null]" homepage="[null]"
-           description="[null]" installation_date="[null]" plugin_class="org.sonar.pmd.Main" core="false" version="2.2" />
+           description="[null]" installation_date="[null]" plugin_class="org.sonar.pmd.Main" core="false" child_first_classloader="false" version="2.2" />
 
   <plugin_files id="1" plugin_id="1" filename="checkstyle.jar"/>
   <plugin_files id="2" plugin_id="1" filename="checkstyle-extension.jar"/>
index 008610800674ca7553db36042f5097ddbb765ed9..57dfd1358d74233486fb5f8b1d252ec661713364 100644 (file)
@@ -1,6 +1,6 @@
 <dataset>
   <plugins id="1" name="Checkstyle" plugin_key="checkstyle" organization="[null]" organization_url="[null]" license="[null]" homepage="[null]"
-           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" version="2.2" />
+           description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2" />
 
   <plugin_files id="1" plugin_id="1" filename="checkstyle.jar"/>
   <plugin_files id="2" plugin_id="1" filename="checkstyle-extension.jar"/>
index c819bc3a623b570d0a8374eefab23db6137c8372..73f66de56187b72a61b159a561564935a0dc6ea5 100644 (file)
@@ -36,16 +36,16 @@ public class PluginClassLoaders implements ServerComponent {
   private ClassLoadersCollection classLoaders = new ClassLoadersCollection(getClass().getClassLoader());
 
   public ClassLoader create(PluginMetadata plugin) {
-    return create(plugin.getKey(), plugin.getDeployedFiles());
+    return create(plugin.getKey(), plugin.getDeployedFiles(), plugin.isUseChildFirstClassLoader());
   }
 
-  ClassLoader create(String pluginKey, Collection<File> classloaderFiles) {
+  ClassLoader create(String pluginKey, Collection<File> classloaderFiles, boolean useChildFirstClassLoader) {
     try {
       List<URL> urls = new ArrayList<URL>();
       for (File file : classloaderFiles) {
         urls.add(toUrl(file));
       }
-      return classLoaders.createClassLoader(pluginKey, urls);
+      return classLoaders.createClassLoader(pluginKey, urls, useChildFirstClassLoader);
     } catch (MalformedURLException e) {
       throw new RuntimeException("Fail to load the classloader of the plugin: " + pluginKey, e);
     }
index 834e3a630b0bc7e06061ddd5ed77430d1afff119..58410f2cbd88e3766c6f15dc3972e05e57ae5e45 100644 (file)
@@ -46,6 +46,7 @@ public class PluginMetadata {
   private String license;
   private String homepage;
   private boolean core;
+  private boolean useChildFirstClassLoader;
   private String[] dependencyPaths = new String[0];
   public List<File> deployedFiles = new ArrayList<File>();
 
@@ -158,6 +159,13 @@ public class PluginMetadata {
     return StringUtils.isNotBlank(mainClass);
   }
 
+  public void setUseChildFirstClassLoader(boolean use) {
+    this.useChildFirstClassLoader = use;
+  }
+
+  public boolean isUseChildFirstClassLoader() {
+    return useChildFirstClassLoader;
+  }
 
   public void setDependencyPaths(String[] paths) {
     this.dependencyPaths = paths;
@@ -181,7 +189,9 @@ public class PluginMetadata {
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
+    if (this == o) {
+      return true;
+    }
     if (o == null || getClass() != o.getClass()) {
       return false;
     }
@@ -218,6 +228,7 @@ public class PluginMetadata {
     metadata.setHomepage(manifest.getHomepage());
     metadata.setDependencyPaths(manifest.getDependencies());
     metadata.setCore(corePlugin);
+    metadata.setUseChildFirstClassLoader(manifest.isUseChildFirstClassLoader());
     return metadata;
   }
 
@@ -231,6 +242,7 @@ public class PluginMetadata {
     jpaPlugin.setVersion(getVersion());
     jpaPlugin.setHomepage(getHomepage());
     jpaPlugin.setCore(isCore());
+    jpaPlugin.setUseChildFirstClassLoader(isUseChildFirstClassLoader());
     jpaPlugin.removeFiles();
     for (File file : getDeployedFiles()) {
       jpaPlugin.createFile(file.getName());
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/142_add_plugins_child_first_classloader_column.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/142_add_plugins_child_first_classloader_column.rb
new file mode 100644 (file)
index 0000000..d14ca6f
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Sonar, entreprise quality control tool.
+# Copyright (C) 2009 SonarSource SA
+# mailto:contact AT sonarsource DOT com
+#
+# Sonar is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# Sonar 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Sonar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+#
+class AddPluginsChildFirstClassloaderColumn < ActiveRecord::Migration
+
+  def self.up
+    add_column 'plugins', 'child_first_classloader', :boolean, :null => true
+    Plugin.reset_column_information
+  end
+
+end
index ed4021ad6d95f398292419caeee363e21bbbb61f..d673767c872925e842b87f711d6c7aa2ef711bec 100644 (file)
  */
 package org.sonar.server.plugins;
 
-import com.google.common.collect.Lists;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+
 import org.junit.Test;
 import org.sonar.test.TestUtils;
 
+import com.google.common.collect.Lists;
+
 import java.io.File;
 import java.io.IOException;
 
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-
 public class PluginClassLoadersTest {
 
   @Test
@@ -38,7 +39,7 @@ public class PluginClassLoadersTest {
     File jar = getFile("foo-plugin.jar");
     PluginMetadata metadata = PluginMetadata.createFromJar(jar, false);
     metadata.addDeployedFile(jar);
-        
+
     assertNull(getClass().getClassLoader().getResource("foo.txt"));
 
     PluginClassLoaders classloaders = new PluginClassLoaders();
@@ -53,7 +54,7 @@ public class PluginClassLoadersTest {
     File jar = getFile("sonar-build-breaker-plugin-0.1.jar");
 
     PluginClassLoaders classloaders = new PluginClassLoaders();
-    classloaders.create("build-breaker", Lists.<File>newArrayList(jar));
+    classloaders.create("build-breaker", Lists.<File> newArrayList(jar), false);
 
     assertNotNull(classloaders.getClass("build-breaker", "org.sonar.plugins.buildbreaker.BuildBreakerPlugin"));
     assertNull(classloaders.getClass("build-breaker", "org.sonar.plugins.buildbreaker.Unknown"));
index 4087029435a0a09f89db90c5f95b720266d336db..57ec82a5136ddcf49242625cdeacd79a2eb73a21 100644 (file)
  */
 package org.sonar.server.plugins;
 
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
 import org.apache.commons.io.FileUtils;
 import org.junit.Before;
 import org.junit.Rule;
@@ -40,10 +44,6 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.List;
 
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-
 public class PluginDeployerTest extends AbstractDbUnitTestCase {
 
   private Server server;
@@ -80,6 +80,7 @@ public class PluginDeployerTest extends AbstractDbUnitTestCase {
     assertThat(plugin.getName(), is("Foo"));
     assertThat(plugin.getFiles().size(), is(1));
     assertThat(plugin.isCore(), is(false));
+    assertThat(plugin.isUseChildFirstClassLoader(), is(false));
     JpaPluginFile pluginFile = plugin.getFiles().get(0);
     assertThat(pluginFile.getFilename(), is("foo-plugin.jar"));
     assertThat(pluginFile.getPath(), is("foo/foo-plugin.jar"));
@@ -106,6 +107,7 @@ public class PluginDeployerTest extends AbstractDbUnitTestCase {
     assertThat(plugin.getKey(), is("build-breaker"));
     assertThat(plugin.getFiles().size(), is(1));
     assertThat(plugin.isCore(), is(false));
+    assertThat(plugin.isUseChildFirstClassLoader(), is(false));
     JpaPluginFile pluginFile = plugin.getFiles().get(0);
     assertThat(pluginFile.getFilename(), is("sonar-build-breaker-plugin-0.1.jar"));
     assertThat(pluginFile.getPath(), is("build-breaker/sonar-build-breaker-plugin-0.1.jar"));
index b715fa0e207e18966861b30a7a0800ba8fce93bb..c664d919f601a7eca2f482fdea4d7ea969d36316 100644 (file)
@@ -37,6 +37,7 @@ public class PluginMetadataTest {
     assertThat(metadata.getMainClass(), is("foo.Main"));
     assertThat(metadata.getVersion(), is("2.2-SNAPSHOT"));
     assertThat(metadata.getOrganization(), is("SonarSource"));
+    assertThat(metadata.isUseChildFirstClassLoader(), is(false));
     assertThat(metadata.getDependencyPaths().length, is(0));
     assertThat(metadata.isCore(), is(false));
   }