Browse Source

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
tags/2.6
Godin 13 years ago
parent
commit
6636cf363e

+ 1
- 1
pom.xml View File

@@ -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>

+ 14
- 19
sonar-batch/src/main/java/org/sonar/batch/BatchPluginRepository.java View 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();
}

+ 0
- 12
sonar-core/src/main/java/org/sonar/core/classloaders/ClassLoadersCollection.java View 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.
*

+ 21
- 4
sonar-core/src/main/java/org/sonar/core/plugin/JpaPlugin.java View 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);
}

+ 1
- 1
sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java View 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";


+ 2
- 0
sonar-core/src/test/java/org/sonar/core/plugin/JpaPluginDaoTest.java View 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");


+ 1
- 1
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/removePreviousFilesWhenRegisteringPlugin-result.xml View 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>

+ 2
- 2
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/saveDeprecatedPlugin-result.xml View 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"/>

+ 2
- 2
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/savePluginAndFiles-result.xml View 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"/>

+ 1
- 1
sonar-core/src/test/resources/org/sonar/core/plugin/JpaPluginDaoTest/shared.xml View 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"/>

+ 3
- 3
sonar-server/src/main/java/org/sonar/server/plugins/PluginClassLoaders.java View 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);
}

+ 13
- 1
sonar-server/src/main/java/org/sonar/server/plugins/PluginMetadata.java View 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());

+ 27
- 0
sonar-server/src/main/webapp/WEB-INF/db/migrate/142_add_plugins_child_first_classloader_column.rb View File

@@ -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

+ 7
- 6
sonar-server/src/test/java/org/sonar/server/plugins/PluginClassLoadersTest.java View File

@@ -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.<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"));

+ 6
- 4
sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java View File

@@ -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"));

+ 1
- 0
sonar-server/src/test/java/org/sonar/server/plugins/PluginMetadataTest.java View 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));
}

Loading…
Cancel
Save