From 6636cf363ef274e817efec8885a183cf6e0fc3e2 Mon Sep 17 00:00:00 2001 From: Godin Date: Sat, 16 Oct 2010 22:18:26 +0000 Subject: [PATCH] SONAR-1862: * Upgrade to sonar-update-center-common 0.3-SNAPSHOT * Add column 'child_first_classloader' to table 'plugins' * Add possibility to use child-first classloader --- pom.xml | 2 +- .../sonar/batch/BatchPluginRepository.java | 33 ++++++++----------- .../classloaders/ClassLoadersCollection.java | 12 ------- .../java/org/sonar/core/plugin/JpaPlugin.java | 25 +++++++++++--- .../org/sonar/jpa/entity/SchemaMigration.java | 2 +- .../sonar/core/plugin/JpaPluginDaoTest.java | 2 ++ ...viousFilesWhenRegisteringPlugin-result.xml | 2 +- .../saveDeprecatedPlugin-result.xml | 4 +-- .../savePluginAndFiles-result.xml | 4 +-- .../core/plugin/JpaPluginDaoTest/shared.xml | 2 +- .../server/plugins/PluginClassLoaders.java | 6 ++-- .../sonar/server/plugins/PluginMetadata.java | 14 +++++++- ..._plugins_child_first_classloader_column.rb | 27 +++++++++++++++ .../plugins/PluginClassLoadersTest.java | 13 ++++---- .../server/plugins/PluginDeployerTest.java | 10 +++--- .../server/plugins/PluginMetadataTest.java | 1 + 16 files changed, 102 insertions(+), 57 deletions(-) create mode 100644 sonar-server/src/main/webapp/WEB-INF/db/migrate/142_add_plugins_child_first_classloader_column.rb diff --git a/pom.xml b/pom.xml index a2b7336a357..7fefd90b147 100644 --- a/pom.xml +++ b/pom.xml @@ -386,7 +386,7 @@ mmmm org.codehaus.sonar sonar-update-center-common - 0.2 + 0.3-SNAPSHOT org.codehaus.sonar diff --git a/sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java b/sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java index e831faaee99..97e3393aa05 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java +++ b/sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java @@ -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 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 urls = urlsByKey.get(key); - + for (JpaPlugin pluginMetadata : dao.getPlugins()) { + String key = pluginMetadata.getKey(); + List 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(); } diff --git a/sonar-core/src/main/java/org/sonar/core/classloaders/ClassLoadersCollection.java b/sonar-core/src/main/java/org/sonar/core/classloaders/ClassLoadersCollection.java index 1279edc961e..eed29008bf7 100644 --- a/sonar-core/src/main/java/org/sonar/core/classloaders/ClassLoadersCollection.java +++ b/sonar-core/src/main/java/org/sonar/core/classloaders/ClassLoadersCollection.java @@ -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 urls) { - return createClassLoader(key, urls, false); - } - /** * Generates URLClassLoader with specified delegation model. * diff --git a/sonar-core/src/main/java/org/sonar/core/plugin/JpaPlugin.java b/sonar-core/src/main/java/org/sonar/core/plugin/JpaPlugin.java index c178f59acaa..27dfc80738d 100644 --- a/sonar-core/src/main/java/org/sonar/core/plugin/JpaPlugin.java +++ b/sonar-core/src/main/java/org/sonar/core/plugin/JpaPlugin.java @@ -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); } diff --git a/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java b/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java index 532c7b72b6b..c6d4e942160 100644 --- a/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java +++ b/sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java @@ -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"; diff --git a/sonar-core/src/test/java/org/sonar/core/plugin/JpaPluginDaoTest.java b/sonar-core/src/test/java/org/sonar/core/plugin/JpaPluginDaoTest.java index ba4e26a322b..878c492c89b 100644 --- a/sonar-core/src/test/java/org/sonar/core/plugin/JpaPluginDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/plugin/JpaPluginDaoTest.java @@ -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"); diff --git a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/removePreviousFilesWhenRegisteringPlugin-result.xml b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/removePreviousFilesWhenRegisteringPlugin-result.xml index e7f3523119d..579a381a739 100644 --- a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/removePreviousFilesWhenRegisteringPlugin-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/removePreviousFilesWhenRegisteringPlugin-result.xml @@ -1,6 +1,6 @@ + description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2" /> \ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/saveDeprecatedPlugin-result.xml b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/saveDeprecatedPlugin-result.xml index aa6e51ec2cd..38f8e3d72d1 100644 --- a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/saveDeprecatedPlugin-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/saveDeprecatedPlugin-result.xml @@ -1,9 +1,9 @@ + description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2"/> + description="[null]" installation_date="[null]" plugin_class="org.sonar.pmd.Main" core="false" child_first_classloader="false" version="[null]" /> diff --git a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/savePluginAndFiles-result.xml b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/savePluginAndFiles-result.xml index 6c215921357..2ca3c309e6d 100644 --- a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/savePluginAndFiles-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/savePluginAndFiles-result.xml @@ -1,9 +1,9 @@ + description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2"/> + description="[null]" installation_date="[null]" plugin_class="org.sonar.pmd.Main" core="false" child_first_classloader="false" version="2.2" /> diff --git a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/shared.xml index 00861080067..57dfd1358d7 100644 --- a/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/shared.xml +++ b/sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/shared.xml @@ -1,6 +1,6 @@ + description="[null]" installation_date="[null]" plugin_class="[null]" core="true" child_first_classloader="false" version="2.2" /> diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/PluginClassLoaders.java b/sonar-server/src/main/java/org/sonar/server/plugins/PluginClassLoaders.java index c819bc3a623..73f66de5618 100644 --- a/sonar-server/src/main/java/org/sonar/server/plugins/PluginClassLoaders.java +++ b/sonar-server/src/main/java/org/sonar/server/plugins/PluginClassLoaders.java @@ -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 classloaderFiles) { + ClassLoader create(String pluginKey, Collection classloaderFiles, boolean useChildFirstClassLoader) { try { List urls = new ArrayList(); 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); } diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/PluginMetadata.java b/sonar-server/src/main/java/org/sonar/server/plugins/PluginMetadata.java index 834e3a630b0..58410f2cbd8 100644 --- a/sonar-server/src/main/java/org/sonar/server/plugins/PluginMetadata.java +++ b/sonar-server/src/main/java/org/sonar/server/plugins/PluginMetadata.java @@ -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 deployedFiles = new ArrayList(); @@ -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 index 00000000000..d14ca6faedf --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/142_add_plugins_child_first_classloader_column.rb @@ -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 diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/PluginClassLoadersTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/PluginClassLoadersTest.java index ed4021ad6d9..d673767c872 100644 --- a/sonar-server/src/test/java/org/sonar/server/plugins/PluginClassLoadersTest.java +++ b/sonar-server/src/test/java/org/sonar/server/plugins/PluginClassLoadersTest.java @@ -19,16 +19,17 @@ */ 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.newArrayList(jar)); + classloaders.create("build-breaker", Lists. newArrayList(jar), false); assertNotNull(classloaders.getClass("build-breaker", "org.sonar.plugins.buildbreaker.BuildBreakerPlugin")); assertNull(classloaders.getClass("build-breaker", "org.sonar.plugins.buildbreaker.Unknown")); diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java index 4087029435a..57ec82a5136 100644 --- a/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java +++ b/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java @@ -19,6 +19,10 @@ */ 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")); diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/PluginMetadataTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/PluginMetadataTest.java index b715fa0e207..c664d919f60 100644 --- a/sonar-server/src/test/java/org/sonar/server/plugins/PluginMetadataTest.java +++ b/sonar-server/src/test/java/org/sonar/server/plugins/PluginMetadataTest.java @@ -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)); } -- 2.39.5