aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2010-09-06 14:08:06 +0000
committersimonbrandhof <simon.brandhof@gmail.com>2010-09-06 14:08:06 +0000
commitaeadc1f9129274949daaa57738c7c4550bdfbc7b (patch)
tree08dadf5ef7474fc41d1d48f74648f1ba8b55f34d /subprojects
downloadsonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.tar.gz
sonarqube-aeadc1f9129274949daaa57738c7c4550bdfbc7b.zip
SONAR-236 remove deprecated code from checkstyle plugin + display default value of rule parameters in Q profile console
Diffstat (limited to 'subprojects')
-rw-r--r--subprojects/sonar-dev-maven-plugin/RELEASE_NOTES.txt13
-rw-r--r--subprojects/sonar-dev-maven-plugin/pom.xml426
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/java/org/sonar/dev/TrimMojo.java157
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-db.sql0
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-user.sql0
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-db.sql0
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-user.sql0
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-db.sql3
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-user.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-db.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-user.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-db.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-user.sql3
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-db.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-user.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-db.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-user.sql5
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-db.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-user.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-db.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-user.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-db.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-user.sql1
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/license/AL2.txt14
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/license/LGPL3.txt17
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/server/sonar.properties103
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/resources/server/wrapper.conf121
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.build.xml451
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.mojos.xml362
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/test/java/org/sonar/dev/TrimMojoTest.java106
-rw-r--r--subprojects/sonar-dev-maven-plugin/src/test/resources/org/sonar/dev/TrimMojoTest/whitespace-indented.txt9
-rw-r--r--subprojects/sonar-update-center/pom.xml346
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml132
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/invoker.properties0
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/pom.xml61
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleMetrics.java26
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SamplePlugin.java45
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleSensor.java30
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/verify.bsh7
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/invoker.properties0
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/pom.xml46
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/src/main/java/org/sonar/plugins/sample/SamplePlugin.java30
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/verify.bsh22
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/invoker.properties0
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/pom.xml44
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/src/main/java/org/sonar/plugins/sample/SamplePlugin.java30
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/verify.bsh16
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/invoker.properties0
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/pom.xml45
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/src/main/java/org/sonar/plugins/sample/SamplePlugin.java30
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/verify.bsh17
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/invoker.properties1
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/pom.xml40
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleMetrics.java26
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SamplePlugin.java45
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleSensor.java30
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/invoker.properties1
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/pom.xml41
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/settings.xml35
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/invoker.properties1
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/pom.xml42
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/src/main/java/org/sonar/plugins/sample/SamplePlugin.java30
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java251
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/CheckDependenciesMojo.java88
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java337
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/META-INF/plexus/components.xml43
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/AL2.txt14
-rw-r--r--subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/LGPL3.txt17
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/pom.xml36
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Artifact.java146
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/FormatUtils.java55
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Plugin.java134
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java251
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Release.java165
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Sonar.java37
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenter.java84
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterDeserializer.java111
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterSerializer.java112
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Version.java138
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ArtifactTest.java76
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/FormatUtilsTest.java41
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginManifestTest.java59
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ReleaseTest.java38
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterDeserializerTest.java56
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterSerializerTest.java61
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterTest.java44
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/VersionTest.java102
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/checkstyle-plugin.jarbin0 -> 1524 bytes
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/old-plugin.jarbin0 -> 1551 bytes
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/UpdateCenterDeserializerTest/updates.properties17
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/pom.xml134
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/History.java56
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Plugin.java206
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Sonar.java58
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateCenter.java318
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateInfo.java42
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Versioned.java27
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Configuration.java94
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/HttpDownloader.java102
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/MetadataFile.java72
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Server.java83
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/log4j.properties6
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugin-info-widget-template.html46
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugins.txt38
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/style.css29
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/HistoryTest.java53
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/PluginTest.java60
-rw-r--r--subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/SonarTest.java41
108 files changed, 7000 insertions, 0 deletions
diff --git a/subprojects/sonar-dev-maven-plugin/RELEASE_NOTES.txt b/subprojects/sonar-dev-maven-plugin/RELEASE_NOTES.txt
new file mode 100644
index 00000000000..5f15a84a3d0
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/RELEASE_NOTES.txt
@@ -0,0 +1,13 @@
+Temporary release notes - waiting for a dedicated project/component in JIRA
+
+-------------------------------------------------------------------------------
+Upgrade from sonar-dev-mojo 2.2-SNAPSHOT to sonar-dev-maven-plugin 1.0-SNAPSHOT
+-------------------------------------------------------------------------------
+* Remove the parameter 'environment'
+* The goal 'stop' requires the parameter 'sonar.runtimeVersion'
+* The goals 'start' and 'stop' now use the standalone mode (Jetty)
+* Add the goals 'start-war' and 'stop-war' to use the WAR mode (Tomcat)
+* Increase allocated memory (needed for Derby tests)
+* Add predefined database profiles. For example selecting database=mysql sets default url and driver for MySQL.
+* Add the goal "analyze" with required parameter "sonar.projectsDir". It replaces the parameters "mavenProjectsDir" and "analyzeProjects"
+
diff --git a/subprojects/sonar-dev-maven-plugin/pom.xml b/subprojects/sonar-dev-maven-plugin/pom.xml
new file mode 100644
index 00000000000..c3352e46636
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/pom.xml
@@ -0,0 +1,426 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-dev-maven-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>maven-plugin</packaging>
+ <name>Sonar :: Development Maven Plugin</name>
+ <description>Maven plugin for Sonar development environment</description>
+
+ <repositories>
+ <repository>
+ <id>sonar</id>
+ <url>http://repository.sonarsource.org/content/repositories/sonar</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <inceptionYear>2010</inceptionYear>
+ <organization>
+ <name>SonarSource</name>
+ <url>http://www.sonarsource.com</url>
+ </organization>
+ <licenses>
+ <license>
+ <name>GNU Lesser General Public License (LGPL), v.3</name>
+ <url>http://www.gnu.org/licenses/lgpl.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <developers>
+ <developer>
+ <id>simon.brandhof</id>
+ <name>Simon Brandhof</name>
+ <email>simon.brandhof@sonarsource.com</email>
+ <organization>SonarSource</organization>
+ <roles>
+ <role>developer</role>
+ </roles>
+ <timezone>+1</timezone>
+ </developer>
+ <developer>
+ <id>godin</id>
+ <name>Evgeny Mandrikov</name>
+ <email>mandrikov@gmail.com</email>
+ <roles>
+ <role>developer</role>
+ </roles>
+ <timezone>+3</timezone>
+ </developer>
+ </developers>
+
+ <scm>
+ <connection>scm:svn:http://svn.codehaus.org/sonar/trunk/subprojects/sonar-dev-maven-plugin</connection>
+ <developerConnection>scm:svn:https://svn.codehaus.org/sonar/trunk/subprojects/sonar-dev-maven-plugin</developerConnection>
+ <url>https://svn.codehaus.org/sonar/trunk/subprojects/sonar-dev-maven-plugin</url>
+ </scm>
+
+ <issueManagement>
+ <system>jira</system>
+ <url>http://jira.codehaus.org/browse/SONAR</url>
+ </issueManagement>
+ <ciManagement>
+ <system>bamboo</system>
+ <url>http://bamboo.ci.codehaus.org/browse/SONAR</url>
+ </ciManagement>
+ <distributionManagement>
+ <repository>
+ <id>codehaus.org</id>
+ <url>dav:https://dav.codehaus.org/repository/sonar</url>
+ <uniqueVersion>false</uniqueVersion>
+ </repository>
+ <snapshotRepository>
+ <id>codehaus.org</id>
+ <url>dav:https://dav.codehaus.org/snapshots.repository/sonar</url>
+ <uniqueVersion>false</uniqueVersion>
+ </snapshotRepository>
+ </distributionManagement>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.min.version>2.0</maven.min.version>
+ <jdk.min.version>1.5</jdk.min.version>
+ <mavenVersion>2.0.9</mavenVersion>
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <!-- Plugins ordered by shortname (archetype, assembly ...) -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <version>1.0-beta-1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-invoker-plugin</artifactId>
+ <version>1.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.6.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>2.6</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-tools-ant</artifactId>
+ <version>2.6</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.0</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.4.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>2.0-beta-7</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.1.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <requireMavenVersion>
+ <message>To build this project Maven ${maven.min.version} (or upper) is required. Please install it.
+ </message>
+ <version>${maven.min.version}</version>
+ </requireMavenVersion>
+ <requireJavaVersion>
+ <message>To build this project JDK ${jdk.min.version} (or upper) is required. Please install it.
+ </message>
+ <version>${jdk.min.version}</version>
+ </requireJavaVersion>
+ <requirePluginVersions>
+ <!-- TODO
+ This rule produces warning under maven-3.0-beta-1 :
+ "This rule is not compatible with the current version of Maven."
+ -->
+ <message>Build reproducibility : always define plugin versions</message>
+ <banLatest>true</banLatest>
+ <banRelease>true</banRelease>
+ <phases>clean,deploy</phases>
+ </requirePluginVersions>
+ <!--bannedDependencies>
+ <message>Don't use banned dependencies</message>
+ <searchTransitive>true</searchTransitive>
+ <excludes>
+ <exclude>commons-logging:commons-logging</exclude>
+ </excludes>
+ </bannedDependencies-->
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>${jdk.min.version}</source>
+ <target>${jdk.min.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-maven-plugin</artifactId>
+ <version>1.6</version>
+ <executions>
+ <execution>
+ <id>check-java-version</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <signature>
+ <groupId>org.codehaus.mojo.signature</groupId>
+ <artifactId>java15</artifactId>
+ <version>1.0</version>
+ </signature>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <tagBase>https://svn.codehaus.org/sonar/tags</tagBase>
+ <autoVersionSubmodules>true</autoVersionSubmodules>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>fikin</groupId>
+ <artifactId>fikin-ant</artifactId>
+ <version>1.7.3</version>
+ </dependency>
+ <dependency>
+ <groupId>ant-contrib</groupId>
+ <artifactId>ant-contrib</artifactId>
+ <version>1.0b3</version>
+ <exclusions>
+ <exclusion>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- maven -->
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-archiver</artifactId>
+ <version>2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-script-ant</artifactId>
+ <version>2.0.10</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>1.5.6</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-ant</artifactId>
+ <version>1.0-beta-2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- JDBC drivers are used when the database is created (property dropDatabase is true) -->
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.1.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derbyclient</artifactId>
+ <version>10.4.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>8.3-603.jdbc3</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.jtds</groupId>
+ <artifactId>jtds</artifactId>
+ <version>1.2.2</version>
+ </dependency>
+
+ <!-- fikin dependencies -->
+ <dependency>
+ <groupId>commons-httpclient</groupId>
+ <artifactId>commons-httpclient</artifactId>
+ <version>3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.3</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.9.1</version>
+ </dependency>
+
+ <!-- unit tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <version>1.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/java/org/sonar/dev/TrimMojo.java b/subprojects/sonar-dev-maven-plugin/src/main/java/org/sonar/dev/TrimMojo.java
new file mode 100644
index 00000000000..abe8e8df8bb
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/java/org/sonar/dev/TrimMojo.java
@@ -0,0 +1,157 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.dev;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.LineIterator;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.codehaus.plexus.util.DirectoryScanner;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @goal trim
+ */
+public class TrimMojo extends AbstractMojo {
+
+ /**
+ * @parameter
+ * @required
+ */
+ private File directory;
+
+ /**
+ * List of ant-style patterns. If
+ * this is not specified, allfiles in the project source directories are included.
+ *
+ * @parameter
+ */
+ private String[] includes;
+
+ /**
+ * @parameter
+ */
+ private String[] excludes;
+
+
+ /**
+ * Specifies the encoding of the source files.
+ *
+ * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
+ */
+ private String sourceEncoding;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (shouldExecute()) {
+ trimDirectory();
+ }
+ }
+
+ private void trimDirectory() throws MojoExecutionException {
+ File[] files = scanFiles();
+ for (File file : files) {
+ StringBuilder sb = new StringBuilder();
+ try {
+ LineIterator lines = FileUtils.lineIterator(file, sourceEncoding);
+ while (lines.hasNext()) {
+ String line = lines.nextLine();
+ if (StringUtils.isNotBlank(line)) {
+ sb.append(StringUtils.trim(line));
+ sb.append(IOUtils.LINE_SEPARATOR);
+ }
+ }
+ FileUtils.writeStringToFile(file, sb.toString(), sourceEncoding);
+
+ } catch (IOException e) {
+ throw new MojoExecutionException("Can not trim the file " + file, e);
+ }
+ }
+ getLog().info("Trimmed files: " + files.length);
+ }
+
+ private boolean shouldExecute() {
+ return directory != null && directory.exists();
+ }
+
+ /**
+ * gets a list of all files in the source directory.
+ *
+ * @return the list of all files in the source directory;
+ */
+ private File[] scanFiles() {
+ String[] defaultIncludes = {"**\\*"};
+ DirectoryScanner ds = new DirectoryScanner();
+ if (includes == null) {
+ ds.setIncludes(defaultIncludes);
+ } else {
+ ds.setIncludes(includes);
+ }
+ ds.addDefaultExcludes(); // .svn, ...
+ if (excludes != null) {
+ ds.setExcludes(excludes);
+ }
+ ds.setBasedir(directory);
+ getLog().info("Scanning directory " + directory);
+ ds.scan();
+ int maxFiles = ds.getIncludedFiles().length;
+ File[] result = new File[maxFiles];
+ for (int i = 0; i < maxFiles; i++) {
+ result[i] = new File(directory, ds.getIncludedFiles()[i]);
+ }
+ return result;
+ }
+
+ public File getDirectory() {
+ return directory;
+ }
+
+ public void setDirectory(File directory) {
+ this.directory = directory;
+ }
+
+ public String[] getIncludes() {
+ return includes;
+ }
+
+ public void setIncludes(String[] includes) {
+ this.includes = includes;
+ }
+
+ public String[] getExcludes() {
+ return excludes;
+ }
+
+ public void setExcludes(String[] excludes) {
+ this.excludes = excludes;
+ }
+
+ public String getSourceEncoding() {
+ return sourceEncoding;
+ }
+
+ public void setSourceEncoding(String sourceEncoding) {
+ this.sourceEncoding = sourceEncoding;
+ }
+}
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-db.sql
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-db.sql
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-user.sql
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/create-user.sql
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-db.sql
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-db.sql
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-user.sql
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/derby/drop-user.sql
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-db.sql
new file mode 100644
index 00000000000..fc12f2a622e
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-db.sql
@@ -0,0 +1,3 @@
+create database ${sonar.jdbc.username};
+USE ${sonar.jdbc.username};
+sp_addalias ${sonar.jdbc.username}, dbo;
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-user.sql
new file mode 100644
index 00000000000..66a82965dc4
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/create-user.sql
@@ -0,0 +1 @@
+CREATE LOGIN ${sonar.jdbc.username} WITH PASSWORD = '${sonar.jdbc.password}', CHECK_POLICY=OFF;
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-db.sql
new file mode 100644
index 00000000000..ad92da2ded4
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-db.sql
@@ -0,0 +1 @@
+drop database ${sonar.jdbc.username}; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-user.sql
new file mode 100644
index 00000000000..e5fa30a9a26
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mssql/drop-user.sql
@@ -0,0 +1 @@
+drop login ${sonar.jdbc.username}; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-db.sql
new file mode 100644
index 00000000000..e3a1eca1e38
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-db.sql
@@ -0,0 +1 @@
+create database ${sonar.jdbc.username} character set utf8; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-user.sql
new file mode 100644
index 00000000000..de353c36070
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/create-user.sql
@@ -0,0 +1,3 @@
+create user '${sonar.jdbc.username}' IDENTIFIED BY '${sonar.jdbc.password}';
+GRANT ALL ON ${sonar.jdbc.username}.* TO '${sonar.jdbc.username}'@'%' IDENTIFIED BY '${sonar.jdbc.password}';
+GRANT ALL ON ${sonar.jdbc.username}.* TO '${sonar.jdbc.username}'@'localhost' IDENTIFIED BY '${sonar.jdbc.password}'; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-db.sql
new file mode 100644
index 00000000000..9f97c9ae458
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-db.sql
@@ -0,0 +1 @@
+drop database IF EXISTS ${sonar.jdbc.username}; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-user.sql
new file mode 100644
index 00000000000..aaf18e4eaad
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/mysql/drop-user.sql
@@ -0,0 +1 @@
+drop user '${sonar.jdbc.username}'@'%'; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-db.sql
new file mode 100644
index 00000000000..eef971b76be
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-db.sql
@@ -0,0 +1 @@
+// nothing to do under oracle \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-user.sql
new file mode 100644
index 00000000000..49b09decb97
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/create-user.sql
@@ -0,0 +1,5 @@
+CREATE USER ${sonar.jdbc.username} IDENTIFIED BY ${sonar.jdbc.password} DEFAULT TABLESPACE USERS ACCOUNT UNLOCK;
+GRANT CONNECT TO ${sonar.jdbc.username};
+GRANT RESOURCE TO ${sonar.jdbc.username};
+GRANT CREATE TABLE to ${sonar.jdbc.username};
+GRANT CREATE SEQUENCE to ${sonar.jdbc.username}; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-db.sql
new file mode 100644
index 00000000000..eef971b76be
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-db.sql
@@ -0,0 +1 @@
+// nothing to do under oracle \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-user.sql
new file mode 100644
index 00000000000..299ec925be6
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/oracle/drop-user.sql
@@ -0,0 +1 @@
+DROP USER ${sonar.jdbc.username} CASCADE; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-db.sql
new file mode 100644
index 00000000000..2cdda76defc
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-db.sql
@@ -0,0 +1 @@
+CREATE DATABASE ${sonar.jdbc.username}; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-user.sql
new file mode 100644
index 00000000000..d3cf35a438d
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/create-user.sql
@@ -0,0 +1 @@
+CREATE USER ${sonar.jdbc.username} WITH PASSWORD '${sonar.jdbc.password}' CREATEDB; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-db.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-db.sql
new file mode 100644
index 00000000000..12cca84099b
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-db.sql
@@ -0,0 +1 @@
+DROP DATABASE IF EXISTS ${sonar.jdbc.username}; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-user.sql b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-user.sql
new file mode 100644
index 00000000000..319856fac78
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/database/postgresql/drop-user.sql
@@ -0,0 +1 @@
+DROP USER IF EXISTS ${sonar.jdbc.username}; \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/license/AL2.txt b/subprojects/sonar-dev-maven-plugin/src/main/resources/license/AL2.txt
new file mode 100644
index 00000000000..2550cc485b1
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/license/AL2.txt
@@ -0,0 +1,14 @@
+Copyright (C) ${year} ${name}
+mailto: ${mail}
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/license/LGPL3.txt b/subprojects/sonar-dev-maven-plugin/src/main/resources/license/LGPL3.txt
new file mode 100644
index 00000000000..e7f3cc3e5ad
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/license/LGPL3.txt
@@ -0,0 +1,17 @@
+Sonar, open source software quality management tool.
+Copyright (C) ${year} ${name}
+mailto: ${mail}
+
+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
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/server/sonar.properties b/subprojects/sonar-dev-maven-plugin/src/main/resources/server/sonar.properties
new file mode 100644
index 00000000000..2dd5f5fca27
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/server/sonar.properties
@@ -0,0 +1,103 @@
+#--------------------------------------------------------
+# To use an environment variable, use the following syntax : ${env:NAME_OF_ENV_VARIABLE}
+# For example :
+# sonar.jdbc.url: ${env:SONAR_JDBC_URL}
+#
+#
+# See also the file conf/wrapper.conf for JVM advanced settings
+#---------------------------------------------------------
+
+
+#---------------------------------------------------------
+# WEB
+#---------------------------------------------------------
+# Listen host/port and context path (for example / or /sonar). Default values are 0.0.0.0:9000/
+# ONLY IF STANDALONE MODE. NOT USED IF DEPLOYED AS A WAR.
+#sonar.web.host: 0.0.0.0
+#sonar.web.port: 9000
+#sonar.web.context: /
+
+# Apache mod_jk connector. Supported only in standalone mode.
+# Uncomment to activate AJP13 connector.
+#sonar.ajp13.port: 8009
+
+#---------------------------------------------------------
+# DATABASE
+#---------------------------------------------------------
+
+#----- Embedded database
+# Comment the following lines to deactivate the default embedded database (used only for tests and demos)
+#sonar.jdbc.url: jdbc:derby://localhost:1527/sonar;create=true
+#sonar.jdbc.driverClassName: org.apache.derby.jdbc.ClientDriver
+#sonar.jdbc.validationQuery: values(1)
+# data directory, autodetected : /data if standalone application, /WEB-INF/classes/data if WAR deployement (exploded mode)
+#sonar.embeddedDatabase.dataDir:
+# derby embedded database server listening port, defaults to 1527
+#sonar.derby.drda.portNumber: 1527
+
+#----- MySQL 5.x/6.x
+# Comment the embedded database and uncomment the following lines to use MySQL
+#sonar.jdbc.url: jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8
+#sonar.jdbc.driverClassName: com.mysql.jdbc.Driver
+#sonar.jdbc.validationQuery: select 1
+
+
+#----- Oracle 10g/11g
+# Comment the embedded database and uncomment the following lines to use Oracle
+#sonar.jdbc.url: jdbc:oracle:thin:@localhost/XE
+#sonar.jdbc.driverClassName: oracle.jdbc.driver.OracleDriver
+#sonar.jdbc.validationQuery: select 1 from dual
+
+# Activate if more than one Sonar Oracle schemas on the data server (for example different versions installed).
+# In that case, use the same property during maven analysis (-Dsonar.hibernate.default_schema=xxx)
+#sonar.hibernate.default_schema: sonar
+
+#----- PostgreSQL 8.x
+# uncomment the 3 following lines to use PostgreSQL
+#sonar.jdbc.url: jdbc:postgresql://localhost/sonar
+#sonar.jdbc.driverClassName: org.postgresql.Driver
+#sonar.jdbc.validationQuery: select 1
+
+
+#----- Microsoft SQLServer - NOT TESTED and NOT SUPPORTED.
+# The Jtds open source driver is available in extensions/jdbc-driver/mssql. More details on http://jtds.sourceforge.
+#sonar.jdbc.url: jdbc:jtds:sqlserver://localhost;databaseName=SONAR;SelectMethod=Cursor
+#sonar.jdbc.driverClassName: net.sourceforge.jtds.jdbc.Driver
+#sonar.jdbc.validationQuery: select 1
+
+
+#----- Global database settings
+#sonar.jdbc.username: sonar
+#sonar.jdbc.password: sonar
+sonar.jdbc.maxActive: 10
+sonar.jdbc.maxIdle: 5
+sonar.jdbc.minIdle: 2
+sonar.jdbc.maxWait: 5000
+sonar.jdbc.minEvictableIdleTimeMillis: 600000
+sonar.jdbc.timeBetweenEvictionRunsMillis: 30000
+
+# Transaction isolation level. Default driver setting is used by default.
+# Values : 1 (TRANSACTION_READ_UNCOMMITED), 2 (TRANSACTION_READ_COMMITTED), 4 (TRANSACTION_REPEATABLE_READ), 8 (TRANSACTION_SERIALIZABLE)
+#sonar.jdbc.defaultTransactionIsolation: 2
+
+
+# When packaged in a WAR, JDBC datasource can be configured into the application server then registered to JNDI.
+# In such a case Sonar uses this datasource to connect to database, else if binds itself its own datasource.
+# Note : Jonas does not accept to bind subcontexts, so name should be something like 'jdbc-sonar', without slashes.
+#sonar.jdbc.jndiName: jdbc/sonar
+
+# If you don't use the default JDBC drivers, as listed above, then you have to explicitly set the dialect to use.
+# Values are : mysql, derby, oracle, postgresql
+#sonar.jdbc.dialect=
+
+
+#---------------------------------------------------------
+# EXTENSIONS
+#---------------------------------------------------------
+# Absolute path of coding rules extensions (custom rules that are not provided with tools like Checkstyle or PMD).
+# This parameter is useful when Sonar is deployed as a WAR. It avoids from packaging the WAR file each time extensions JARs are updated.
+# The directory contains subdirectories like checkstyle/ and pmd/
+# Example :
+# sonar.rules.extensionsPath: /user/home/jdoe/sonar/extensions
+# Example for windows platform (backslash char must be escaped) :
+# sonar.rules.extensionsPath: D:\\softwares\\sonar-1.8\\extensions
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/resources/server/wrapper.conf b/subprojects/sonar-dev-maven-plugin/src/main/resources/server/wrapper.conf
new file mode 100644
index 00000000000..232e2fb8d02
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/resources/server/wrapper.conf
@@ -0,0 +1,121 @@
+wrapper.java.additional.1=-Djava.awt.headless=true
+wrapper.java.additional.2=-XX:MaxPermSize=256m
+wrapper.java.additional.3=-server
+wrapper.java.initmemory=256
+wrapper.java.maxmemory=1024
+
+#********************************************************************
+# Wrapper Java Properties
+#********************************************************************
+# JVM
+# Can be an absolute path, for example:
+#wrapper.java.command=/path/to/my/jdk/bin/java
+wrapper.java.command=java
+
+# Java Main class. This class must implement the WrapperListener interface
+# or guarantee that the WrapperManager class is initialized. Helper
+# classes are provided to do this for you. See the Integration section
+# of the documentation for details.
+wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
+
+# Java Classpath (include wrapper.jar) Add class path elements as
+# needed starting from 1
+wrapper.java.classpath.1=../../lib/*.jar
+wrapper.java.classpath.2=../../
+wrapper.java.classpath.3=../../extensions/jdbc-driver/derby/*.jar
+wrapper.java.classpath.4=../../extensions/jdbc-driver/mysql/*.jar
+wrapper.java.classpath.5=../../extensions/jdbc-driver/oracle/*.jar
+wrapper.java.classpath.6=../../extensions/jdbc-driver/postgresql/*.jar
+wrapper.java.classpath.7=../../extensions/jdbc-driver/mssql/*.jar
+wrapper.java.classpath.8=../../conf/
+
+# Java Library Path (location of Wrapper.DLL or libwrapper.so)
+wrapper.java.library.path.1=./lib
+
+# Application parameters. Add parameters as needed starting from 1
+wrapper.app.parameter.1=org.sonar.application.StartServer
+
+#********************************************************************
+# Profiling and debbuging - for development only
+# If wrapper.java.additional.3=-server is not commented, parameter ids should start from 4 instead of 3.
+#********************************************************************
+# Java remote debugging
+#wrapper.java.additional.3=-agentlib:jdwp=transport=dt_socket,server=y,address=8000
+
+# JProfiler 5
+#wrapper.java.additional.3=-Xint
+#wrapper.java.additional.4=-agentlib:jprofilerti=port=8849
+#wrapper.java.additional.5=-Xbootclasspath/a:/Applications/jprofiler5/bin/agent.jar
+
+# JMX remote monitoring on Sun JVM (warning, security is disabled)
+#wrapper.java.additional.3=-Dcom.sun.management.jmxremote
+#wrapper.java.additional.4=-Dcom.sun.management.jmxremote.port=9005
+#wrapper.java.additional.5=-Dcom.sun.management.jmxremote.authenticate=false
+#wrapper.java.additional.6=-Dcom.sun.management.jmxremote.ssl=false
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console. (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output. (See docs for log levels)
+wrapper.console.loglevel=NONE
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=../../logs/sonar.log
+
+# Format of output for the log file. (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output. (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+# the log is rolled. Size is specified in bytes. The default value
+# of 0, disables log rolling. May abbreviate with the 'k' (kb) or
+# 'm' (mb) suffix. For example: 10m = 10 megabytes.
+#wrapper.logfile.maxsize=0
+
+# Maximum number of rolled log files which will be allowed before old
+# files are deleted. The default value of 0 implies no limit.
+#wrapper.logfile.maxfiles=0
+
+# Log Level for sys/event log output. (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=Sonar
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+# using this configuration file has been installed as a service.
+# Please uninstall the service before modifying this section. The
+# service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=Sonar
+
+# Display name of the service
+wrapper.ntservice.displayname=Sonar
+
+# Description of the service
+wrapper.ntservice.description=Sonar
+
+# Service dependencies. Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed. AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=AUTO_START
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false
+
+#********************************************************************
+# restart the process if CPU is heavily loaded during 240 seconds.
+wrapper.ping.timeout=240 \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.build.xml b/subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.build.xml
new file mode 100644
index 00000000000..1b6344b1cf6
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.build.xml
@@ -0,0 +1,451 @@
+<project>
+ <property name="tmpdir" value="${java.io.tmpdir}/sonar"/>
+ <property name="tomcat6.home" value="${tmpdir}/tomcat6"/>
+
+ <taskdef resource="cargo.tasks"/>
+ <taskdef name="httpmpost" classname="net.sf.fikin.ant.httpclientanttask.AntMultipartPostMethod"/>
+ <taskdef name="httppost" classname="net.sf.fikin.ant.httpclientanttask.AntPostMethod"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <!-- entry points : start and stop -->
+ <target name="start" depends="expand-database-profile,prepare-standalone-configuration,drop-database,configure-sonar">
+ <parallel>
+ <antcall target="start-standalone"/>
+ <antcall target="setup"/>
+ </parallel>
+ </target>
+
+ <target name="stop" depends="prepare-standalone-configuration,stop-standalone"/>
+
+ <target name="prepare-standalone-configuration">
+ <condition property="sonar.bin.path" value="bin/macosx-universal-64/sonar.sh">
+ <os family="mac"/>
+ </condition>
+ <condition property="sonar.bin.path" value="bin/windows-x86-32/StartSonar.bat">
+ <os family="windows"/>
+ </condition>
+ <condition property="sonar.bin.path" value="bin/linux-x86-32/sonar.sh">
+ <os family="unix"/>
+ </condition>
+ </target>
+
+ <!--
+
+ DATABASE PROFILES
+
+ -->
+ <target name="expand-database-profile">
+ <!-- derby -->
+ <condition property="sonar.jdbc.url" value="jdbc:derby://localhost:1527/sonar;create=true">
+ <and>
+ <equals arg1="${sonar.database}" arg2="derby"/>
+ <not>
+ <isset property="sonar.jdbc.url"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="sonar.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver">
+ <and>
+ <equals arg1="${sonar.database}" arg2="derby"/>
+ <not>
+ <isset property="sonar.jdbc.driver"/>
+ </not>
+ </and>
+ </condition>
+
+ <!-- mysql -->
+ <condition property="sonar.jdbc.url"
+ value="jdbc:mysql://localhost:3306/sonar?useUnicode=true&amp;characterEncoding=utf8">
+ <and>
+ <equals arg1="${sonar.database}" arg2="mysql"/>
+ <not>
+ <isset property="sonar.jdbc.url"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="sonar.jdbc.driver" value="com.mysql.jdbc.Driver">
+ <and>
+ <equals arg1="${sonar.database}" arg2="mysql"/>
+ <not>
+ <isset property="sonar.jdbc.driver"/>
+ </not>
+ </and>
+ </condition>
+
+ <!-- postgresql -->
+ <condition property="sonar.jdbc.url" value="jdbc:postgresql://localhost/sonar">
+ <and>
+ <equals arg1="${sonar.database}" arg2="postgresql"/>
+ <not>
+ <isset property="sonar.jdbc.url"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="sonar.jdbc.driver" value="org.postgresql.Driver">
+ <and>
+ <equals arg1="${sonar.database}" arg2="postgresql"/>
+ <not>
+ <isset property="sonar.jdbc.driver"/>
+ </not>
+ </and>
+ </condition>
+
+ <!-- oracle -->
+ <condition property="sonar.jdbc.url" value="jdbc:oracle:thin:@localhost/XE">
+ <and>
+ <equals arg1="${sonar.database}" arg2="oracle"/>
+ <not>
+ <isset property="sonar.jdbc.url"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="sonar.jdbc.driver" value="oracle.jdbc.driver.OracleDriver">
+ <and>
+ <equals arg1="${sonar.database}" arg2="oracle"/>
+ <not>
+ <isset property="sonar.jdbc.driver"/>
+ </not>
+ </and>
+ </condition>
+
+ <!-- SQLServer -->
+ <condition property="sonar.jdbc.url" value="jdbc:jtds:sqlserver://localhost;databaseName=SONAR;SelectMethod=Cursor">
+ <and>
+ <equals arg1="${sonar.database}" arg2="mssql"/>
+ <not>
+ <isset property="sonar.jdbc.url"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="sonar.jdbc.driver" value="net.sourceforge.jtds.jdbc.Driver">
+ <and>
+ <equals arg1="${sonar.database}" arg2="mssql"/>
+ <not>
+ <isset property="sonar.jdbc.driver"/>
+ </not>
+ </and>
+ </condition>
+ </target>
+
+
+ <target name="start-war" depends="expand-database-profile,drop-database,configure-sonar">
+ <parallel>
+ <antcall target="start-tomcat"/>
+ <antcall target="setup"/>
+ </parallel>
+ </target>
+
+ <target name="stop-war" depends="stop-tomcat"/>
+
+ <!-- STEP 1 : initialize the database -->
+ <target name="drop-database">
+ <condition property="execute.drop.database">
+ <istrue value="${sonar.dropDatabase}"/>
+ </condition>
+ <antcall target="do-drop-database"/>
+ </target>
+
+ <target name="do-drop-database" if="execute.drop.database">
+ <sql driver="${sonar.jdbc.driver}"
+ url="${sonar.jdbc.rootUrl}"
+ userid="${sonar.jdbc.rootUsername}"
+ password="${sonar.jdbc.rootPassword}"
+ onerror="continue"
+ autocommit="true"
+ expandProperties="true">
+ <resources>
+ <javaresource name="database/${sonar.database}/drop-db.sql"/>
+ <javaresource name="database/${sonar.database}/drop-user.sql"/>
+ <javaresource name="database/${sonar.database}/create-user.sql"/>
+ <javaresource name="database/${sonar.database}/create-db.sql"/>
+ </resources>
+ </sql>
+
+ <echo>Database is ready</echo>
+ </target>
+
+
+ <!-- STEP 2 : install Sonar -->
+ <target name="clean-sonar-home" if="execute.sonar.clean">
+ <delete dir="${tmpdir}/sonar-${sonar.runtimeVersion}"/>
+ <mkdir dir="${tmpdir}"/>
+ </target>
+
+
+ <target name="prepare-sonar-home" unless="is.installed">
+ <copy tofile="${tmpdir}/sonar-${sonar.runtimeVersion}.zip" overwrite="true" verbose="true" flatten="true"
+ failonerror="false"
+ file="${settings.localRepository}/org/codehaus/sonar/sonar-application/${sonar.runtimeVersion}/sonar-application-${sonar.runtimeVersion}.zip">
+ </copy>
+ <condition property="execute.download-sonar">
+ <not>
+ <available file="${tmpdir}/sonar-${sonar.runtimeVersion}.zip"/>
+ </not>
+ </condition>
+ <antcall target="download-sonar"/>
+ <unzip src="${tmpdir}/sonar-${sonar.runtimeVersion}.zip" dest="${tmpdir}"/>
+ </target>
+
+
+ <target name="download-sonar" if="execute.download-sonar">
+ <echo>Downloading sonar</echo>
+ <get src="http://dist.sonar.codehaus.org/sonar-${sonar.runtimeVersion}.zip"
+ dest="${tmpdir}/sonar-${sonar.runtimeVersion}.zip"/>
+ <echo>Installing to local maven repo</echo>
+ <mvninstall groupId="org.codehaus.sonar"
+ artifactId="sonar-application"
+ version="${sonar.runtimeVersion}"
+ packaging="zip"
+ file="${tmpdir}/sonar-${sonar.runtimeVersion}.zip"/>
+ </target>
+
+ <target name="copy-extensions" if="has.extensions">
+ <echo>Copy extensions...</echo>
+ <copy todir="${tmpdir}/sonar-${sonar.runtimeVersion}/extensions" overwrite="true" verbose="true" flatten="false">
+ <fileset dir="${sonar.extensionsDir}"/>
+ </copy>
+ </target>
+
+
+ <target name="copy-plugin-artifact" if="has.plugin.artifact">
+ <echo>Copy plugin artifact...</echo>
+ <copy todir="${tmpdir}/sonar-${sonar.runtimeVersion}/extensions/plugins" overwrite="true" verbose="true"
+ flatten="true"
+ file="${sonar.pluginArtifact}">
+ </copy>
+ </target>
+
+
+ <target name="configure-sonar">
+ <condition property="execute.sonar.clean" value="true">
+ <istrue value="${sonar.clean}"/>
+ </condition>
+ <antcall target="clean-sonar-home" />
+
+ <available property="is.installed" file="${tmpdir}/sonar-${sonar.runtimeVersion}/conf/sonar.properties"/>
+ <antcall target="prepare-sonar-home"/>
+
+ <copy todir="${tmpdir}/sonar-${sonar.runtimeVersion}/conf/" overwrite="true" verbose="true" flatten="true">
+ <resources>
+ <javaresource name="server/sonar.properties"/>
+ <javaresource name="server/wrapper.conf"/>
+ </resources>
+ </copy>
+
+ <available property="has.extensions" file="${sonar.extensionsDir}"/>
+ <antcall target="copy-extensions"/>
+
+ <available file="${sonar.pluginArtifact}" property="has.plugin.artifact"/>
+ <antcall target="copy-plugin-artifact"/>
+
+ </target>
+
+
+ <!-- STEP 3 : start web server -->
+ <target name="start-standalone">
+ <echo>Start server</echo>
+
+ <chmod perm="777" type="file">
+ <fileset dir="${tmpdir}/sonar-${sonar.runtimeVersion}/bin">
+ <include name="**/*"/>
+ </fileset>
+ </chmod>
+
+ <condition property="windows">
+ <os family="windows"/>
+ </condition>
+
+ <antcall target="start-standalone-windows" />
+ <antcall target="start-standalone-unix" />
+ </target>
+
+ <target name="start-standalone-windows" if="windows">
+<!-- <condition property="sonar.command" value="restart" else="console">
+ <istrue value="${sonar.background}"/>
+ </condition>-->
+ <exec executable="${tmpdir}/sonar-${sonar.runtimeVersion}/${sonar.bin.path}">
+ <env key="sonar.jdbc.url" value="${sonar.jdbc.url}"/>
+ <env key="sonar.jdbc.driverClassName" value="${sonar.jdbc.driver}"/>
+ <env key="sonar.jdbc.username" value="${sonar.jdbc.username}"/>
+ <env key="sonar.jdbc.password" value="${sonar.jdbc.password}"/>
+ </exec>
+ </target>
+
+ <target name="start-standalone-unix" unless="windows">
+ <condition property="sonar.command" value="restart" else="console">
+ <istrue value="${sonar.background}"/>
+ </condition>
+ <exec executable="${tmpdir}/sonar-${sonar.runtimeVersion}/${sonar.bin.path}">
+ <arg line="${sonar.command}"/>
+ <env key="sonar.jdbc.url" value="${sonar.jdbc.url}"/>
+ <env key="sonar.jdbc.driverClassName" value="${sonar.jdbc.driver}"/>
+ <env key="sonar.jdbc.username" value="${sonar.jdbc.username}"/>
+ <env key="sonar.jdbc.password" value="${sonar.jdbc.password}"/>
+ </exec>
+ </target>
+
+ <target name="stop-standalone">
+ <exec executable="${tmpdir}/sonar-${sonar.runtimeVersion}/${sonar.bin.path}">
+ <arg line="stop"/>
+ </exec>
+ </target>
+
+
+ <target name="start-tomcat">
+ <echo>Build WAR</echo>
+ <ant dir="${tmpdir}/sonar-${sonar.runtimeVersion}/war/" inheritAll="false"/>
+
+ <mkdir dir="${tomcat6.home}"/>
+ <mkdir dir="${tmpdir}/sonar-${sonar.runtimeVersion}/logs"/>
+
+ <condition property="sonar.wait" value="true" else="false">
+ <isfalse value="${sonar.background}"/>
+ </condition>
+ <echo>Start tomcat, background mode: ${sonar.background}</echo>
+
+ <cargo containerId="tomcat6x" action="start" wait="${sonar.wait}" id="tmptmct6-${sonar.runtimeVersion}"
+ output="${tmpdir}/sonar-${sonar.runtimeVersion}/logs/output.log"
+ log="${tmpdir}/sonar-${sonar.runtimeVersion}/logs/cargo.log">
+ <zipurlinstaller
+ installurl="http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.zip"/>
+ <configuration type="standalone" home="${tomcat6.home}">
+ <property name="cargo.jvmargs"
+ value="-Xmx1024m -XX:MaxPermSize=256m -server -Dsonar.jdbc.url=${sonar.jdbc.url} -Dsonar.jdbc.driverClassName=${sonar.jdbc.driver} -Dsonar.jdbc.username=${sonar.jdbc.username} -Dsonar.jdbc.password=${sonar.jdbc.password}"/>
+ <property name="cargo.servlet.port" value="9000"/>
+ <property name="cargo.remote.username" value="admin"/>
+ <property name="cargo.remote.password" value=""/>
+ <deployable type="war" file="${tmpdir}/sonar-${sonar.runtimeVersion}/war/sonar.war">
+ <property name="context" value="ROOT"/>
+ </deployable>
+ </configuration>
+ </cargo>
+ <antcall target="wait-for-server"/>
+ </target>
+
+ <target name="stop-tomcat">
+ <echo>Stopping tomcat</echo>
+ <cargo containerId="tomcat6x" action="stop" wait="true" id="tmptmct6-${sonar.runtimeVersion}">
+ <zipurlinstaller
+ installurl="http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.zip"/>
+ <configuration type="standalone" home="${tomcat6.home}">
+ <property name="cargo.jvmargs" value="-Xmx512m -server"/>
+ <property name="cargo.servlet.port" value="9000"/>
+ <property name="cargo.remote.username" value="admin"/>
+ <property name="cargo.remote.password" value=""/>
+ </configuration>
+ </cargo>
+ </target>
+
+ <!-- STEP 4 : setup sonar -->
+
+ <target name="wait-for-server">
+ <waitfor maxwait="5" maxwaitunit="minute" checkevery="10" checkeveryunit="second">
+ <http url="http://localhost:9000"/>
+ </waitfor>
+ </target>
+
+ <target name="setup" depends="wait-for-server">
+ <httppost url="http://localhost:9000/setup/setup_database" logLevel="none"/>
+ <echo message="Database is up."/>
+
+ <condition property="execute.restore.backup" value="true">
+ <isset property="sonar.configBackup"/>
+ </condition>
+ <antcall target="restore-backup"/>
+ </target>
+
+
+ <target name="restore-backup" if="execute.restore.backup">
+ <echo message="Restoring sonar backup"/>
+
+ <httppost url="http://localhost:9000/sessions/login" logLevel="none">
+ <post name="login" value="admin"/>
+ <post name="password" value="admin"/>
+ </httppost>
+ <echo message="Logged in."/>
+
+ <httpmpost url="http://localhost:9000/backup/import" logLevel="none">
+ <postFile name="file" file="${sonar.configBackup}"/>
+ </httpmpost>
+ <echo message="Backup is restored."/>
+ </target>
+
+
+ <!-- STEP 5 : analyze projects -->
+
+ <target name="analyze" depends="expand-database-profile">
+ <for param="pom">
+ <path>
+ <fileset dir="${sonar.projectsDir}" includes="*/pom.xml"/>
+ </path>
+ <sequential>
+ <mvn pom="@{pom}" failonerror="false" args="clean install -DskipTests"/>
+ <mvnsonar pom="@{pom}"/>
+ </sequential>
+ </for>
+ </target>
+
+
+ <macrodef name="mvn">
+ <attribute name="failonerror" default="true"/>
+ <attribute name="pom"/>
+ <attribute name="args" default=""/>
+
+ <sequential>
+ <exec failonerror="@{failonerror}" executable="mvn.bat" osfamily="Windows">
+ <arg line="-f @{pom}"/>
+ <arg line="@{args}"/>
+ </exec>
+ <exec failonerror="@{failonerror}" executable="mvn" osfamily="unix">
+ <arg line="-f @{pom}"/>
+ <arg line="@{args} "/>
+ </exec>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="mvnsonar">
+ <attribute name="failonerror" default="true"/>
+ <attribute name="args" default=""/>
+ <attribute name="pom"/>
+
+ <sequential>
+ <exec failonerror="@{failonerror}" executable="${maven.home}/bin/mvn.bat" osfamily="Windows">
+ <arg line="org.codehaus.mojo:sonar-maven-plugin:1.0-beta-1:sonar @{args} -B -e"/>
+ <arg line="-f @{pom}"/>
+ <arg value='-Dsonar.jdbc.url="${sonar.jdbc.url}"'/>
+ <!-- double quotes for windows -->
+ <arg value="-Dsonar.jdbc.driver=${sonar.jdbc.driver}"/>
+ <arg value="-Dsonar.jdbc.username=${sonar.jdbc.username}"/>
+ <arg value="-Dsonar.jdbc.password=${sonar.jdbc.password}"/>
+ </exec>
+ <exec failonerror="@{failonerror}" executable="${maven.home}/bin/mvn" osfamily="unix">
+ <arg line="org.codehaus.mojo:sonar-maven-plugin:1.0-beta-1:sonar @{args} -B -e"/>
+ <arg line="-f @{pom}"/>
+ <arg value='-Dsonar.jdbc.url=${sonar.jdbc.url}'/>
+ <arg value="-Dsonar.jdbc.driver=${sonar.jdbc.driver}"/>
+ <arg value="-Dsonar.jdbc.username=${sonar.jdbc.username}"/>
+ <arg value="-Dsonar.jdbc.password=${sonar.jdbc.password}"/>
+ </exec>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="mvninstall">
+ <attribute name="failonerror" default="false"/>
+ <attribute name="groupId"/>
+ <attribute name="artifactId"/>
+ <attribute name="version"/>
+ <attribute name="packaging" default="jar"/>
+ <attribute name="file"/>
+
+ <sequential>
+ <exec failonerror="@{failonerror}" executable="mvn.bat" osfamily="Windows">
+ <arg
+ line="install:install-file -DgroupId=@{groupId} -DartifactId=@{artifactId} -Dversion=@{version} -Dpackaging=@{packaging} -Dfile=@{file}"/>
+ </exec>
+ <exec failonerror="@{failonerror}" executable="mvn" osfamily="unix">
+ <arg
+ line="install:install-file -DgroupId=@{groupId} -DartifactId=@{artifactId} -Dversion=@{version} -Dpackaging=@{packaging} -Dfile=@{file}"/>
+ </exec>
+ </sequential>
+ </macrodef>
+</project>
diff --git a/subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.mojos.xml b/subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.mojos.xml
new file mode 100644
index 00000000000..ee9d8f8c41f
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/main/scripts/start-stop.mojos.xml
@@ -0,0 +1,362 @@
+<pluginMetadata>
+ <mojos>
+ <mojo>
+ <goal>start</goal>
+ <call>start</call>
+ <requiresProject>false</requiresProject>
+ <parameters>
+ <parameter>
+ <name>sonar.runtimeVersion</name>
+ <property>sonar.runtimeVersion</property>
+ <expression>${sonar.runtimeVersion}</expression>
+ <required>true</required>
+ <type>java.lang.String</type>
+ <description>Sonar version</description>
+ <defaultValue>2.2</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.database</name>
+ <property>sonar.database</property>
+ <required>false</required>
+ <expression>${sonar.database}</expression>
+ <type>java.lang.String</type>
+ <description>Database profile: [derby, mssql, mysql, oracle, postgresql]</description>
+ <defaultValue>derby</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.dropDatabase</name>
+ <property>sonar.dropDatabase</property>
+ <expression>${sonar.dropDatabase}</expression>
+ <required>false</required>
+ <type>java.lang.Boolean</type>
+ <defaultValue>false</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.url</name>
+ <property>sonar.jdbc.url</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.url}</expression>
+ <type>java.lang.String</type>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.driver</name>
+ <property>sonar.jdbc.driver</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.driver}</expression>
+ <type>java.lang.String</type>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.rootUsername</name>
+ <property>sonar.jdbc.rootUsername</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.rootUsername}</expression>
+ <type>java.lang.String</type>
+ <description>Used when dropDatabase is true</description>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.rootPassword</name>
+ <property>sonar.jdbc.rootPassword</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.rootPassword}</expression>
+ <type>java.lang.String</type>
+ <description>Used when dropDatabase is true</description>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.rootUrl</name>
+ <property>sonar.jdbc.rootUrl</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.rootUrl}</expression>
+ <type>java.lang.String</type>
+ <description>Used when dropDatabase is true</description>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.username</name>
+ <property>sonar.jdbc.username</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.username}</expression>
+ <type>java.lang.String</type>
+ <defaultValue>sonar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.password</name>
+ <property>sonar.jdbc.password</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.password}</expression>
+ <type>java.lang.String</type>
+ <defaultValue>sonar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.pluginArtifact</name>
+ <property>sonar.pluginArtifact</property>
+ <expression>${sonar.pluginArtifact}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ <defaultValue>${project.build.directory}/${project.build.finalName}.jar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.extensionsDir</name>
+ <property>sonar.extensionsDir</property>
+ <expression>${sonar.extensionsDir}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ <defaultValue>${project.build.directory}/extensions</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.background</name>
+ <property>sonar.background</property>
+ <expression>${sonar.background}</expression>
+ <required>false</required>
+ <type>java.lang.Boolean</type>
+ <defaultValue>false</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.clean</name>
+ <property>sonar.clean</property>
+ <expression>${sonar.clean}</expression>
+ <required>false</required>
+ <type>java.lang.Boolean</type>
+ <defaultValue>true</defaultValue>
+ </parameter>
+ <parameter>
+ <name>settings.localRepository</name>
+ <property>settings.localRepository</property>
+ <expression>${settings.localRepository}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ </parameter>
+ <parameter>
+ <name>sonar.configBackup</name>
+ <property>sonar.configBackup</property>
+ <expression>${sonar.configBackup}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ </parameter>
+ </parameters>
+ </mojo>
+
+ <mojo>
+ <goal>stop</goal>
+ <call>stop</call>
+ <requiresProject>false</requiresProject>
+ <parameters>
+ <parameter>
+ <name>sonar.runtimeVersion</name>
+ <property>sonar.runtimeVersion</property>
+ <required>true</required>
+ <type>java.lang.String</type>
+ <description>Sonar version</description>
+ <expression>${sonar.runtimeVersion}</expression>
+ <defaultValue>2.2</defaultValue>
+ </parameter>
+ </parameters>
+ </mojo>
+
+ <mojo>
+ <goal>start-war</goal>
+ <call>start-war</call>
+ <requiresProject>false</requiresProject>
+ <parameters>
+ <parameter>
+ <name>sonar.runtimeVersion</name>
+ <property>sonar.runtimeVersion</property>
+ <required>true</required>
+ <type>java.lang.String</type>
+ <description>Sonar version</description>
+ <expression>${sonar.runtimeVersion}</expression>
+ <defaultValue>2.2</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.database</name>
+ <property>sonar.database</property>
+ <required>false</required>
+ <expression>${sonar.database}</expression>
+ <type>java.lang.String</type>
+ <description>Database profile: [derby, mssql, mysql, oracle, postgresql]</description>
+ <defaultValue>derby</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.dropDatabase</name>
+ <property>sonar.dropDatabase</property>
+ <expression>${sonar.dropDatabase}</expression>
+ <required>false</required>
+ <type>java.lang.Boolean</type>
+ <defaultValue>false</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.url</name>
+ <property>sonar.jdbc.url</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.url}</expression>
+ <type>java.lang.String</type>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.driver</name>
+ <property>sonar.jdbc.driver</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.driver}</expression>
+ <type>java.lang.String</type>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.rootUsername</name>
+ <property>sonar.jdbc.rootUsername</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.rootUsername}</expression>
+ <type>java.lang.String</type>
+ <description>Used when dropDatabase is true</description>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.rootPassword</name>
+ <property>sonar.jdbc.rootPassword</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.rootPassword}</expression>
+ <type>java.lang.String</type>
+ <description>Used when dropDatabase is true</description>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.rootUrl</name>
+ <property>sonar.jdbc.rootUrl</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.rootUrl}</expression>
+ <type>java.lang.String</type>
+ <description>Used when dropDatabase is true</description>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.username</name>
+ <property>sonar.jdbc.username</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.username}</expression>
+ <type>java.lang.String</type>
+ <defaultValue>sonar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.password</name>
+ <property>sonar.jdbc.password</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.password}</expression>
+ <type>java.lang.String</type>
+ <defaultValue>sonar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.pluginArtifact</name>
+ <property>sonar.pluginArtifact</property>
+ <expression>${sonar.pluginArtifact}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ <defaultValue>${project.build.directory}/${project.build.finalName}.jar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.extensionsDir</name>
+ <property>sonar.extensionsDir</property>
+ <expression>${sonar.extensionsDir}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ <defaultValue>${project.build.directory}/extensions</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.background</name>
+ <property>sonar.background</property>
+ <expression>${sonar.background}</expression>
+ <required>false</required>
+ <type>java.lang.Boolean</type>
+ <defaultValue>false</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.clean</name>
+ <property>sonar.clean</property>
+ <expression>${sonar.clean}</expression>
+ <required>false</required>
+ <type>java.lang.Boolean</type>
+ <defaultValue>true</defaultValue>
+ </parameter>
+ <parameter>
+ <name>settings.localRepository</name>
+ <property>settings.localRepository</property>
+ <expression>${settings.localRepository}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ </parameter>
+ <parameter>
+ <name>sonar.configBackup</name>
+ <property>sonar.configBackup</property>
+ <expression>${sonar.configBackup}</expression>
+ <required>false</required>
+ <type>java.lang.File</type>
+ </parameter>
+ </parameters>
+ </mojo>
+
+ <mojo>
+ <goal>stop-war</goal>
+ <call>stop-war</call>
+ <requiresProject>false</requiresProject>
+ <parameters>
+ <parameter>
+ <name>sonar.runtimeVersion</name>
+ <property>sonar.runtimeVersion</property>
+ <required>true</required>
+ <type>java.lang.String</type>
+ <description>Sonar version</description>
+ <expression>${sonar.runtimeVersion}</expression>
+ <defaultValue>2.2</defaultValue>
+ </parameter>
+ </parameters>
+ </mojo>
+
+
+ <mojo>
+ <goal>analyze</goal>
+ <call>analyze</call>
+ <requiresProject>false</requiresProject>
+ <parameters>
+ <parameter>
+ <name>sonar.database</name>
+ <property>sonar.database</property>
+ <required>false</required>
+ <expression>${sonar.database}</expression>
+ <type>java.lang.String</type>
+ <description>Database profile: [derby, mssql, mysql, oracle, postgresql]</description>
+ <defaultValue>derby</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.url</name>
+ <property>sonar.jdbc.url</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.url}</expression>
+ <type>java.lang.String</type>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.driver</name>
+ <property>sonar.jdbc.driver</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.driver}</expression>
+ <type>java.lang.String</type>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.username</name>
+ <property>sonar.jdbc.username</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.username}</expression>
+ <type>java.lang.String</type>
+ <defaultValue>sonar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.jdbc.password</name>
+ <property>sonar.jdbc.password</property>
+ <required>false</required>
+ <expression>${sonar.jdbc.password}</expression>
+ <type>java.lang.String</type>
+ <defaultValue>sonar</defaultValue>
+ </parameter>
+ <parameter>
+ <name>sonar.projectsDir</name>
+ <property>sonar.projectsDir</property>
+ <expression>${sonar.projectsDir}</expression>
+ <required>true</required>
+ <type>java.lang.File</type>
+ <defaultValue>${basedir}</defaultValue>
+ </parameter>
+ </parameters>
+ </mojo>
+
+ </mojos>
+</pluginMetadata> \ No newline at end of file
diff --git a/subprojects/sonar-dev-maven-plugin/src/test/java/org/sonar/dev/TrimMojoTest.java b/subprojects/sonar-dev-maven-plugin/src/test/java/org/sonar/dev/TrimMojoTest.java
new file mode 100644
index 00000000000..92dd604d7ca
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/test/java/org/sonar/dev/TrimMojoTest.java
@@ -0,0 +1,106 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.dev;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertThat;
+import org.junit.Test;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import java.io.File;
+import java.io.IOException;
+
+public class TrimMojoTest {
+
+ @Test
+ public void trimFilesFromDirectory() throws IOException, MojoFailureException, MojoExecutionException {
+ File dir = newDir("trimFilesFromDirectory");
+ File file1 = copyResourceToDir(1, dir);
+ File file2 = copyResourceToDir(2, dir);
+
+ TrimMojo mojo = new TrimMojo();
+ mojo.setDirectory(dir);
+ mojo.execute();
+
+ assertTrimmed(file1);
+ assertTrimmed(file2);
+ }
+
+ @Test
+ public void excludeSomeFiles() throws IOException, MojoFailureException, MojoExecutionException {
+ File dir = newDir("excludeSomeFiles");
+ File file1 = copyResourceToDir(1, dir);
+ File file2 = copyResourceToDir(2, dir);
+
+ TrimMojo mojo = new TrimMojo();
+ mojo.setDirectory(dir);
+ mojo.setExcludes(new String[]{"**/*-1.txt"});
+ mojo.execute();
+
+ assertNotTrimmed(file1);
+ assertTrimmed(file2);
+ }
+
+ @Test
+ public void trimOnlySomeFiles() throws IOException, MojoFailureException, MojoExecutionException {
+ File dir = newDir("trimOnlySomeFiles");
+ File file1 = copyResourceToDir(1, dir);
+ File file2 = copyResourceToDir(2, dir);
+
+ TrimMojo mojo = new TrimMojo();
+ mojo.setDirectory(dir);
+ mojo.setIncludes(new String[]{"**/*-1.txt"});
+ mojo.execute();
+
+ assertTrimmed(file1);
+ assertNotTrimmed(file2);
+ }
+
+ private void assertNotTrimmed(File file) throws IOException {
+ String content = FileUtils.readFileToString(file);
+ assertThat(content, startsWith(" "));
+ assertThat(content, containsString(" "));
+ }
+
+ private void assertTrimmed(File file) throws IOException {
+ String content = FileUtils.readFileToString(file);
+ assertThat(content, startsWith("many spaces"));
+ assertThat(content, not(containsString(" ")));
+ assertThat(content, containsString("white spaces should be kept in the line"));
+ }
+
+
+ private File copyResourceToDir(int index, File dir) throws IOException {
+ File file = new File(dir, "whitespace-indented-" + index + ".txt");
+ FileUtils.copyURLToFile(getClass().getResource("/org/sonar/dev/TrimMojoTest/whitespace-indented.txt"), file);
+ return file;
+ }
+
+ private File newDir(String name) throws IOException {
+ File dir = new File("target/tmp/org/sonar/dev/TrimMojoTest/" + name);
+ FileUtils.forceMkdir(dir);
+ FileUtils.cleanDirectory(dir);
+ return dir;
+ }
+}
diff --git a/subprojects/sonar-dev-maven-plugin/src/test/resources/org/sonar/dev/TrimMojoTest/whitespace-indented.txt b/subprojects/sonar-dev-maven-plugin/src/test/resources/org/sonar/dev/TrimMojoTest/whitespace-indented.txt
new file mode 100644
index 00000000000..5ee36296681
--- /dev/null
+++ b/subprojects/sonar-dev-maven-plugin/src/test/resources/org/sonar/dev/TrimMojoTest/whitespace-indented.txt
@@ -0,0 +1,9 @@
+ many spaces
+ before and after
+ white spaces should be kept in the line
+
+
+
+
+
+ \ No newline at end of file
diff --git a/subprojects/sonar-update-center/pom.xml b/subprojects/sonar-update-center/pom.xml
new file mode 100644
index 00000000000..34b183df758
--- /dev/null
+++ b/subprojects/sonar-update-center/pom.xml
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-update-center</artifactId>
+ <version>0.3-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Sonar :: Update Center</name>
+ <url>http://www.sonarsource.org</url>
+ <inceptionYear>2010</inceptionYear>
+
+ <organization>
+ <name>SonarSource</name>
+ <url>http://www.sonarsource.com</url>
+ </organization>
+
+ <licenses>
+ <license>
+ <name>LGPL v.3</name>
+ <url>http://www.gnu.org/licenses/lgpl.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <developers>
+ <developer>
+ <id>simon.brandhof</id>
+ <name>Simon Brandhof</name>
+ <email>simon.brandhof@sonarsource.com</email>
+ <organization>SonarSource</organization>
+ <roles>
+ <role>developer</role>
+ </roles>
+ <timezone>+1</timezone>
+ </developer>
+ <developer>
+ <id>godin</id>
+ <name>Evgeny Mandrikov</name>
+ <email>mandrikov@gmail.com</email>
+ <roles>
+ <role>developer</role>
+ </roles>
+ <timezone>+3</timezone>
+ </developer>
+ </developers>
+
+ <modules>
+ <module>sonar-update-center-common</module>
+ <module>sonar-update-center-server</module>
+ <module>sonar-packaging-maven-plugin</module>
+ </modules>
+
+ <scm>
+ <connection>scm:svn:http://svn.codehaus.org/sonar/trunk/subprojects/sonar-update-center</connection>
+ <developerConnection>scm:svn:https://svn.codehaus.org/sonar/trunk/subprojects/sonar-update-center</developerConnection>
+ <url>https://svn.codehaus.org/sonar/trunk/subprojects/sonar-update-center</url>
+ </scm>
+
+ <issueManagement>
+ <system>jira</system>
+ <url>http://jira.codehaus.org/browse/SONAR</url>
+ </issueManagement>
+
+ <ciManagement>
+ <system>bamboo</system>
+ <url>http://ci.codehaus.org/browse/SONAR-UPD</url>
+ </ciManagement>
+
+ <distributionManagement>
+ <repository>
+ <id>codehaus.org</id>
+ <url>dav:https://dav.codehaus.org/repository/sonar</url>
+ <uniqueVersion>false</uniqueVersion>
+ </repository>
+ <snapshotRepository>
+ <id>codehaus.org</id>
+ <url>dav:https://dav.codehaus.org/snapshots.repository/sonar</url>
+ <uniqueVersion>false</uniqueVersion>
+ </snapshotRepository>
+ </distributionManagement>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.min.version>2.0</maven.min.version>
+ <jdk.min.version>1.5</jdk.min.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-update-center-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ <version>1.3.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>xpp3</groupId>
+ <artifactId>xpp3_min</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.5.6</version>
+ </dependency>
+ <dependency>
+ <groupId>xpp3</groupId>
+ <artifactId>xpp3</artifactId>
+ <version>1.1.3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <version>1.1</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <!-- Plugins ordered by shortname (archetype, assembly ...) -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <version>1.0-beta-1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-invoker-plugin</artifactId>
+ <version>1.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.6.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>2.5.1</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-tools-ant</artifactId>
+ <version>2.5.1</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.0</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.4.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>2.0-beta-7</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.1.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>wagon-maven-plugin</artifactId>
+ <version>1.0-beta-3</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <requireMavenVersion>
+ <message>To build this project Maven ${maven.min.version} (or upper) is required. Please install it.
+ </message>
+ <version>${maven.min.version}</version>
+ </requireMavenVersion>
+ <requireJavaVersion>
+ <message>To build this project JDK ${jdk.min.version} (or upper) is required. Please install it.
+ </message>
+ <version>${jdk.min.version}</version>
+ </requireJavaVersion>
+ <requirePluginVersions>
+ <!-- TODO
+ This rule produces warning under maven-3.0-beta-1 :
+ "This rule is not compatible with the current version of Maven."
+ -->
+ <message>Build reproducibility : always define plugin versions</message>
+ <banLatest>true</banLatest>
+ <banRelease>true</banRelease>
+ <phases>clean,deploy</phases>
+ </requirePluginVersions>
+ <!--bannedDependencies>
+ <message>Don't use banned dependencies</message>
+ <searchTransitive>true</searchTransitive>
+ <excludes>
+ <exclude>commons-logging:commons-logging</exclude>
+ </excludes>
+ </bannedDependencies-->
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>${jdk.min.version}</source>
+ <target>${jdk.min.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-maven-plugin</artifactId>
+ <version>1.6</version>
+ <executions>
+ <execution>
+ <id>check-java-version</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <signature>
+ <groupId>org.codehaus.mojo.signature</groupId>
+ <artifactId>java15</artifactId>
+ <version>1.0</version>
+ </signature>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <tagBase>https://svn.codehaus.org/sonar/tags</tagBase>
+ <autoVersionSubmodules>true</autoVersionSubmodules>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project> \ No newline at end of file
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml
new file mode 100644
index 00000000000..05a30c9925d
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-update-center</artifactId>
+ <version>0.3-SNAPSHOT</version>
+ </parent>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <name>Sonar :: Update Center :: Maven Plugin</name>
+
+ <properties>
+ <mavenVersion>2.0.9</mavenVersion>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-update-center-common</artifactId>
+ </dependency>
+
+ <!-- maven -->
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-archiver</artifactId>
+ <version>2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-dependency-tree</artifactId>
+ <version>1.2</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>1.5.6</version>
+ </dependency>
+
+
+ <!-- unit tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generated-helpmojo</id>
+ <goals>
+ <goal>helpmojo</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>run-its</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-invoker-plugin</artifactId>
+ <configuration>
+ <projectsDirectory>src/it</projectsDirectory>
+ <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
+ <pomIncludes>
+ <pomInclude>*/pom.xml</pomInclude>
+ </pomIncludes>
+ <postBuildHookScript>verify</postBuildHookScript>
+ <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
+ <goals>
+ <goal>clean</goal>
+ <goal>install</goal>
+ </goals>
+ <settingsFile>src/it/settings.xml</settingsFile>
+ <!--<debug>true</debug>-->
+ </configuration>
+ <executions>
+ <execution>
+ <id>integration-test</id>
+ <goals>
+ <goal>install</goal>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/invoker.properties
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/invoker.properties
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/pom.xml
new file mode 100644
index 00000000000..5d84396b8d8
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0</version>
+ <packaging>sonar-plugin</packaging>
+
+ <name>Basic</name>
+ <description>Plugin description.</description>
+ <url>http://sonar-plugins.codehaus.org</url>
+ <organization>
+ <name>SonarSource</name>
+ <url>http://www.sonarsource.com</url>
+ </organization>
+
+ <properties>
+ <sonar.version>2.1</sonar.version>
+
+ <!-- sonar.pluginKey = project.artifactId by default -->
+ <sonar.pluginKey>test</sonar.pluginKey>
+ <!-- sonar.pluginName = project.name by default -->
+ <sonar.pluginName>Test Plugin</sonar.pluginName>
+ <sonar.pluginCategory>Test</sonar.pluginCategory>
+ <sonar.pluginClass>org.sonar.plugins.sample.SamplePlugin</sonar.pluginClass>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>${sonar.version}</version>
+ </dependency>
+
+ <!-- unit tests -->
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-testing-harness</artifactId>
+ <version>${sonar.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <extensions>true</extensions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleMetrics.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleMetrics.java
new file mode 100644
index 00000000000..f5481527763
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleMetrics.java
@@ -0,0 +1,26 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SampleMetrics implements Metrics {
+
+ public static final Metric MESSAGE = new Metric("message_key", "Message",
+ "This is a metric to store a well known message", Metric.ValueType.STRING, -1, false,
+ CoreMetrics.DOMAIN_GENERAL);
+
+
+ public static final Metric RANDOM = new Metric("random", "Random",
+ "Random value", Metric.ValueType.FLOAT, Metric.DIRECTION_BETTER, false,
+ CoreMetrics.DOMAIN_GENERAL);
+
+ // getMetrics() method is defined in the Metrics interface and is used by
+ // Sonar to retrieve the list of new Metric
+ public List<Metric> getMetrics() {
+ return Arrays.asList(MESSAGE, RANDOM);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
new file mode 100644
index 00000000000..adabe49c0bf
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
@@ -0,0 +1,45 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.Extension;
+import org.sonar.api.Plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is the container for all others extensions
+ */
+public class SamplePlugin implements Plugin {
+
+ // The key which uniquely identifies your plugin among all others Sonar plugins
+
+ public String getKey() {
+ return "sample";
+ }
+
+ public String getName() {
+ return "My first Sonar plugin";
+ }
+
+ // This description will be displayed in the Configuration > Settings web page
+
+ public String getDescription() {
+ return "You shouldn't expect too much from this plugin except displaying the Hello World message.";
+ }
+
+ // This is where you're going to declare all your Sonar extensions
+
+ public List<Class<? extends Extension>> getExtensions() {
+ List<Class<? extends Extension>> list = new ArrayList<Class<? extends Extension>>();
+
+ list.add(SampleMetrics.class);
+ list.add(SampleSensor.class);
+
+ return list;
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleSensor.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleSensor.java
new file mode 100644
index 00000000000..6e0deb74656
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/src/main/java/org/sonar/plugins/sample/SampleSensor.java
@@ -0,0 +1,30 @@
+package org.sonar.plugins.sample;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Project;
+
+public class SampleSensor implements Sensor {
+
+ public boolean shouldExecuteOnProject(Project project) {
+ // this sensor is executed on any type of project
+ return true;
+ }
+
+ public void analyse(Project project, SensorContext sensorContext) {
+ saveLabelMeasure(sensorContext);
+ saveNumericMeasure(sensorContext);
+ }
+
+ private void saveNumericMeasure(SensorContext context) {
+ // Sonar API includes many libraries like commons-lang and google-collections
+ context.saveMeasure(SampleMetrics.RANDOM, RandomUtils.nextDouble());
+ }
+
+ private void saveLabelMeasure(SensorContext context) {
+ Measure measure = new Measure(SampleMetrics.MESSAGE, "Hello World!");
+ context.saveMeasure(measure);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/verify.bsh b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/verify.bsh
new file mode 100644
index 00000000000..6e3cd1b3f83
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/basic/verify.bsh
@@ -0,0 +1,7 @@
+import java.io.*;
+
+File file = new File( basedir, "target/test-1.0.jar" );
+if ( !file.isFile() )
+{
+ throw new FileNotFoundException( "Could not find generated JAR: " + file );
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/invoker.properties
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/invoker.properties
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/pom.xml
new file mode 100644
index 00000000000..b81734eab6c
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0</version>
+ <packaging>sonar-plugin</packaging>
+
+ <name>Do Not Add Maven Description</name>
+
+ <properties>
+ <sonar.version>2.1</sonar.version>
+ <sonar.pluginKey>test</sonar.pluginKey>
+ <sonar.pluginClass>org.sonar.plugins.sample.SamplePlugin</sonar.pluginClass>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>${sonar.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <extensions>true</extensions>
+ <configuration>
+ <addMavenDescriptor>false</addMavenDescriptor>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
new file mode 100644
index 00000000000..31710c3a0e6
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
@@ -0,0 +1,30 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.Extension;
+import org.sonar.api.Plugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SamplePlugin implements Plugin {
+ public String getKey() {
+ return "sample";
+ }
+
+ public String getName() {
+ return "My first Sonar plugin";
+ }
+
+ public String getDescription() {
+ return "You shouldn't expect too much from this plugin.";
+ }
+
+ public List<Class<? extends Extension>> getExtensions() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/verify.bsh b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/verify.bsh
new file mode 100644
index 00000000000..57c863aa7e9
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotAddMavenDescriptor/verify.bsh
@@ -0,0 +1,22 @@
+import java.io.*;
+import java.util.zip.*;
+
+File file = new File( basedir, "target/test-1.0.jar" );
+if (!file.isFile()) {
+ throw new FileNotFoundException( "Could not find generated JAR: " + file );
+}
+
+ZipFile zipFile = new ZipFile(file);
+try {
+ if (zipFile.getEntry("META-INF/MANIFEST.MF")==null) {
+ throw new FileNotFoundException("Could not find manifest");
+ }
+ if (zipFile.getEntry("META-INF/maven/org.codehaus.sonar/test/pom.xml")!=null) {
+ throw new FileNotFoundException("The maven descriptor (pom.xml) has not been removed");
+ }
+ if (zipFile.getEntry("META-INF/maven/org.codehaus.sonar/test/pom.properties")!=null) {
+ throw new FileNotFoundException("The maven descriptor (pom.properties) has not been removed");
+ }
+} finally {
+ zipFile.close();
+} \ No newline at end of file
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/invoker.properties
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/invoker.properties
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/pom.xml
new file mode 100644
index 00000000000..f794a50f99e
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0</version>
+ <packaging>sonar-plugin</packaging>
+
+ <name>Do not package dependencies provided by Sonar</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.5</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginClass>org.sonar.plugins.sample.SamplePlugin</pluginClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
new file mode 100644
index 00000000000..31710c3a0e6
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
@@ -0,0 +1,30 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.Extension;
+import org.sonar.api.Plugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SamplePlugin implements Plugin {
+ public String getKey() {
+ return "sample";
+ }
+
+ public String getName() {
+ return "My first Sonar plugin";
+ }
+
+ public String getDescription() {
+ return "You shouldn't expect too much from this plugin.";
+ }
+
+ public List<Class<? extends Extension>> getExtensions() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/verify.bsh b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/verify.bsh
new file mode 100644
index 00000000000..13993b92ccd
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/doNotPackageDepsProvidedBySonar/verify.bsh
@@ -0,0 +1,16 @@
+import java.io.*;
+import java.util.zip.*;
+
+File file = new File( basedir, "target/test-1.0.jar" );
+if (!file.isFile()) {
+ throw new FileNotFoundException( "Could not find generated JAR: " + file );
+}
+
+ZipFile zipFile = new ZipFile(file);
+try {
+ if (zipFile.getEntry("META-INF/lib/commons-lang-2.5.jar")!=null) {
+ throw new FileNotFoundException("The dependency commons-lang must not be copied in the plugin");
+ }
+} finally {
+ zipFile.close();
+} \ No newline at end of file
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/invoker.properties
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/invoker.properties
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/pom.xml
new file mode 100644
index 00000000000..2c7c1af0bd7
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Package dependencies</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>1.12</version>
+ </dependency>
+
+ <!-- Should be included into jar -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-email</artifactId>
+ <version>1.2</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginClass>org.sonar.plugins.sample.SamplePlugin</pluginClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
new file mode 100644
index 00000000000..31710c3a0e6
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
@@ -0,0 +1,30 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.Extension;
+import org.sonar.api.Plugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SamplePlugin implements Plugin {
+ public String getKey() {
+ return "sample";
+ }
+
+ public String getName() {
+ return "My first Sonar plugin";
+ }
+
+ public String getDescription() {
+ return "You shouldn't expect too much from this plugin.";
+ }
+
+ public List<Class<? extends Extension>> getExtensions() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/verify.bsh b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/verify.bsh
new file mode 100644
index 00000000000..8847454f986
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/packageDependencies/verify.bsh
@@ -0,0 +1,17 @@
+import java.io.*;
+import java.util.zip.*;
+
+File file = new File( basedir, "target/test-1.0.jar" );
+if ( !file.isFile() )
+{
+ throw new FileNotFoundException( "Could not find generated JAR: " + file );
+}
+
+ZipFile zipFile = new ZipFile(file);
+try {
+ if (zipFile.getEntry("META-INF/lib/commons-email-1.2.jar")!=null) {
+ throw new FileNotFoundException("The dependency commons-email must be copied in JAR");
+ }
+} finally {
+ zipFile.close();
+} \ No newline at end of file
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/invoker.properties
new file mode 100644
index 00000000000..c21e972fc6b
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/invoker.properties
@@ -0,0 +1 @@
+invoker.buildResult = failure
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/pom.xml
new file mode 100644
index 00000000000..58915369b4b
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0</version>
+ <packaging>sonar-plugin</packaging>
+
+ <name>PluginClass not defined</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>1.12</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <extensions>true</extensions>
+ <configuration>
+ <!-- MISSING <pluginClass>org.sonar.plugins.sample.SamplePlugin</pluginClass> -->
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleMetrics.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleMetrics.java
new file mode 100644
index 00000000000..f5481527763
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleMetrics.java
@@ -0,0 +1,26 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SampleMetrics implements Metrics {
+
+ public static final Metric MESSAGE = new Metric("message_key", "Message",
+ "This is a metric to store a well known message", Metric.ValueType.STRING, -1, false,
+ CoreMetrics.DOMAIN_GENERAL);
+
+
+ public static final Metric RANDOM = new Metric("random", "Random",
+ "Random value", Metric.ValueType.FLOAT, Metric.DIRECTION_BETTER, false,
+ CoreMetrics.DOMAIN_GENERAL);
+
+ // getMetrics() method is defined in the Metrics interface and is used by
+ // Sonar to retrieve the list of new Metric
+ public List<Metric> getMetrics() {
+ return Arrays.asList(MESSAGE, RANDOM);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
new file mode 100644
index 00000000000..adabe49c0bf
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
@@ -0,0 +1,45 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.Extension;
+import org.sonar.api.Plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is the container for all others extensions
+ */
+public class SamplePlugin implements Plugin {
+
+ // The key which uniquely identifies your plugin among all others Sonar plugins
+
+ public String getKey() {
+ return "sample";
+ }
+
+ public String getName() {
+ return "My first Sonar plugin";
+ }
+
+ // This description will be displayed in the Configuration > Settings web page
+
+ public String getDescription() {
+ return "You shouldn't expect too much from this plugin except displaying the Hello World message.";
+ }
+
+ // This is where you're going to declare all your Sonar extensions
+
+ public List<Class<? extends Extension>> getExtensions() {
+ List<Class<? extends Extension>> list = new ArrayList<Class<? extends Extension>>();
+
+ list.add(SampleMetrics.class);
+ list.add(SampleSensor.class);
+
+ return list;
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleSensor.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleSensor.java
new file mode 100644
index 00000000000..6e0deb74656
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotDefined/src/main/java/org/sonar/plugins/sample/SampleSensor.java
@@ -0,0 +1,30 @@
+package org.sonar.plugins.sample;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Project;
+
+public class SampleSensor implements Sensor {
+
+ public boolean shouldExecuteOnProject(Project project) {
+ // this sensor is executed on any type of project
+ return true;
+ }
+
+ public void analyse(Project project, SensorContext sensorContext) {
+ saveLabelMeasure(sensorContext);
+ saveNumericMeasure(sensorContext);
+ }
+
+ private void saveNumericMeasure(SensorContext context) {
+ // Sonar API includes many libraries like commons-lang and google-collections
+ context.saveMeasure(SampleMetrics.RANDOM, RandomUtils.nextDouble());
+ }
+
+ private void saveLabelMeasure(SensorContext context) {
+ Measure measure = new Measure(SampleMetrics.MESSAGE, "Hello World!");
+ context.saveMeasure(measure);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/invoker.properties
new file mode 100644
index 00000000000..c21e972fc6b
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/invoker.properties
@@ -0,0 +1 @@
+invoker.buildResult = failure
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/pom.xml
new file mode 100644
index 00000000000..31d3b0efa2c
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/pluginClassNotFound/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0</version>
+ <packaging>sonar-plugin</packaging>
+
+ <name>PluginClass not found</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>1.12</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginClass>org.sonar.plugins.sample.SamplePlugin</pluginClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/settings.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/settings.xml
new file mode 100644
index 00000000000..8890c85392c
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/settings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<settings>
+ <profiles>
+ <profile>
+ <id>it-repo</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <repositories>
+ <repository>
+ <id>local.central</id>
+ <url>@localRepositoryUrl@</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>local.central</id>
+ <url>@localRepositoryUrl@</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+ </profile>
+ </profiles>
+</settings>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/invoker.properties
new file mode 100644
index 00000000000..c21e972fc6b
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/invoker.properties
@@ -0,0 +1 @@
+invoker.buildResult = failure
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/pom.xml
new file mode 100644
index 00000000000..9b4704a142a
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0</version>
+ <packaging>sonar-plugin</packaging>
+
+ <name>sonar-plugin-api not found</name>
+
+ <dependencies>
+ <!-- MISSING
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>1.12</version>
+ </dependency>
+ -->
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginClass>org.sonar.plugins.sample.SamplePlugin</pluginClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
new file mode 100644
index 00000000000..31710c3a0e6
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/sonarPluginApiNotFound/src/main/java/org/sonar/plugins/sample/SamplePlugin.java
@@ -0,0 +1,30 @@
+package org.sonar.plugins.sample;
+
+import org.sonar.api.Extension;
+import org.sonar.api.Plugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SamplePlugin implements Plugin {
+ public String getKey() {
+ return "sample";
+ }
+
+ public String getName() {
+ return "My first Sonar plugin";
+ }
+
+ public String getDescription() {
+ return "You shouldn't expect too much from this plugin.";
+ }
+
+ public List<Class<? extends Extension>> getExtensions() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String toString() {
+ return getKey();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java
new file mode 100644
index 00000000000..fe6f4733348
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java
@@ -0,0 +1,251 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.mavenplugin;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectHelper;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Base class for Sonar-plugin-packaging related tasks.
+ *
+ * @author Evgeny Mandrikov
+ */
+public abstract class AbstractSonarPluginMojo extends AbstractMojo {
+ public static final String SONAR_GROUPID = "org.codehaus.sonar";
+ public static final String SONAR_PLUGIN_API_ARTIFACTID = "sonar-plugin-api";
+ public static final String SONAR_PLUGIN_API_TYPE = "jar";
+
+ /**
+ * The Maven project.
+ *
+ * @parameter expression="${project}"
+ * @required
+ * @readonly
+ */
+ private MavenProject project;
+
+ /**
+ * Directory containing the generated JAR.
+ *
+ * @parameter expression="${project.build.directory}"
+ * @required
+ */
+ private File outputDirectory;
+
+ /**
+ * Directory containing the classes and resource files that should be packaged into the JAR.
+ *
+ * @parameter expression="${project.build.outputDirectory}"
+ * @required
+ */
+ private File classesDirectory;
+
+ /**
+ * The directory where the app is built.
+ *
+ * @parameter expression="${project.build.directory}/${project.build.finalName}"
+ * @required
+ */
+ private File appDirectory;
+
+ /**
+ * Name of the generated JAR.
+ *
+ * @parameter alias="jarName" expression="${jar.finalName}" default-value="${project.build.finalName}"
+ * @required
+ */
+ private String finalName;
+
+ /**
+ * Classifier to add to the artifact generated. If given, the artifact will be an attachment instead.
+ *
+ * @parameter
+ */
+ private String classifier;
+
+ /**
+ * @component
+ */
+ protected MavenProjectHelper projectHelper;
+
+ /**
+ * Plugin key.
+ *
+ * @parameter expression="${sonar.pluginKey}" default-value="${project.artifactId}"
+ */
+ private String pluginKey;
+
+ /**
+ * @parameter expression="${sonar.pluginTermsConditionsUrl}"
+ */
+ private String pluginTermsConditionsUrl;
+
+ /**
+ * Name of plugin class.
+ *
+ * @parameter expression="${sonar.pluginClass}"
+ * @required
+ */
+ private String pluginClass;
+
+ /**
+ * @parameter expression="${sonar.pluginName}" default-value="${project.name}"
+ */
+ private String pluginName;
+
+ /**
+ * @parameter default-value="${project.description}"
+ */
+ private String pluginDescription;
+
+ /**
+ * @parameter default-value="${project.url}"
+ */
+ private String pluginUrl;
+
+ /**
+ * @parameter default-value="${project.issueManagement.url}"
+ */
+ private String pluginIssueTrackerUrl;
+
+ /**
+ * @parameter expression="${sonar.skipDependenciesPackaging}"
+ */
+ private boolean skipDependenciesPackaging = false;
+
+ protected final MavenProject getProject() {
+ return project;
+ }
+
+ protected final File getOutputDirectory() {
+ return outputDirectory;
+ }
+
+ /**
+ * @return the main classes directory, so it's used as the root of the jar.
+ */
+ protected final File getClassesDirectory() {
+ return classesDirectory;
+ }
+
+ public File getAppDirectory() {
+ return appDirectory;
+ }
+
+ protected final String getFinalName() {
+ return finalName;
+ }
+
+ protected final String getClassifier() {
+ return classifier;
+ }
+
+ public String getPluginKey() {
+ return pluginKey;
+ }
+
+ protected final String getPluginClass() {
+ return pluginClass;
+ }
+
+ protected final String getPluginName() {
+ return pluginName;
+ }
+
+ protected final String getPluginDescription() {
+ return pluginDescription;
+ }
+
+ protected final String getPluginUrl() {
+ return pluginUrl;
+ }
+
+ protected String getPluginTermsConditionsUrl() {
+ return pluginTermsConditionsUrl;
+ }
+
+ protected String getPluginIssueTrackerUrl() {
+ return pluginIssueTrackerUrl;
+ }
+
+ protected boolean isSkipDependenciesPackaging() {
+ return skipDependenciesPackaging;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected Set<Artifact> getDependencyArtifacts() {
+ return getProject().getDependencyArtifacts();
+ }
+
+ protected Set<Artifact> getDependencyArtifacts(String scope) {
+ Set<Artifact> result = new HashSet<Artifact>();
+ for (Artifact dep : getDependencyArtifacts()) {
+ if (scope.equals(dep.getScope())) {
+ result.add(dep);
+ }
+ }
+ return result;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected Set<Artifact> getIncludedArtifacts() {
+ Set<Artifact> result = new HashSet<Artifact>();
+ Set<Artifact> artifacts = getProject().getArtifacts();
+ ScopeArtifactFilter filter = new ScopeArtifactFilter(Artifact.SCOPE_RUNTIME);
+ for (Artifact artifact : artifacts) {
+ if (filter.include(artifact)) {
+ result.add(artifact);
+ }
+ }
+ return result;
+ }
+
+ protected final Artifact getSonarPluginApiArtifact() {
+ Set<Artifact> dependencies = getDependencyArtifacts();
+ if (dependencies != null) {
+ for (Artifact dep : dependencies) {
+ if (SONAR_GROUPID.equals(dep.getGroupId())
+ && SONAR_PLUGIN_API_ARTIFACTID.equals(dep.getArtifactId())
+ && SONAR_PLUGIN_API_TYPE.equals(dep.getType())) {
+ return dep;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected String getMessage(String title, List<String> ids) {
+ StringBuilder message = new StringBuilder();
+ message.append(title);
+ message.append("\n\n");
+ for (String id : ids) {
+ message.append("\t").append(id).append("\n");
+ }
+ return message.toString();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/CheckDependenciesMojo.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/CheckDependenciesMojo.java
new file mode 100644
index 00000000000..d6051802ea0
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/CheckDependenciesMojo.java
@@ -0,0 +1,88 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.mavenplugin;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Evgeny Mandrikov
+ * @goal check-dependencies
+ * @requiresDependencyResolution runtime
+ * @phase initialize
+ */
+public class CheckDependenciesMojo extends AbstractSonarPluginMojo {
+
+ private static final String[] GWT_ARTIFACT_IDS = {"gwt-user", "gwt-dev", "sonar-gwt-api"};
+ private static final String[] LOG_GROUP_IDS = {"log4j", "commons-logging"};
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (!isSkipDependenciesPackaging()) {
+ checkApiDependency();
+ checkLogDependencies();
+ checkGwtDependencies();
+ }
+ }
+
+ private void checkApiDependency() throws MojoExecutionException {
+ Artifact sonarApi = getSonarPluginApiArtifact();
+
+ if (sonarApi == null) {
+ throw new MojoExecutionException(
+ SONAR_GROUPID + ":" + SONAR_PLUGIN_API_ARTIFACTID + " should be declared in dependencies"
+ );
+ }
+ }
+
+ private void checkLogDependencies() throws MojoExecutionException {
+ List<String> ids = new ArrayList<String>();
+ for (Artifact dep : getIncludedArtifacts()) {
+ if (ArrayUtils.contains(LOG_GROUP_IDS, dep.getGroupId())) {
+ ids.add(dep.getDependencyConflictId());
+ }
+ }
+ if (!ids.isEmpty()) {
+ StringBuilder message = new StringBuilder();
+ message.append("Dependencies on the following log libraries should be excluded or declared with scope 'provided':")
+ .append("\n\t")
+ .append(StringUtils.join(ids, ", "))
+ .append('\n');
+ getLog().warn(message.toString());
+ }
+ }
+
+ private void checkGwtDependencies() {
+ List<String> ids = new ArrayList<String>();
+ for (Artifact dep : getDependencyArtifacts(Artifact.SCOPE_COMPILE)) {
+ if (ArrayUtils.contains(GWT_ARTIFACT_IDS, dep.getArtifactId())) {
+ ids.add(dep.getDependencyConflictId());
+ }
+ }
+ if (!ids.isEmpty()) {
+ getLog().warn(getMessage("GWT dependencies should be defined with scope 'provided':", ids));
+ }
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java
new file mode 100644
index 00000000000..2caa56b4582
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java
@@ -0,0 +1,337 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.mavenplugin;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.maven.archiver.MavenArchiveConfiguration;
+import org.apache.maven.archiver.MavenArchiver;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactCollector;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
+import org.apache.maven.model.License;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.shared.dependency.tree.DependencyNode;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
+import org.apache.maven.shared.dependency.tree.traversal.BuildingDependencyNodeVisitor;
+import org.codehaus.plexus.archiver.jar.JarArchiver;
+import org.codehaus.plexus.util.FileUtils;
+import org.sonar.updatecenter.common.FormatUtils;
+import org.sonar.updatecenter.common.PluginManifest;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Build a Sonar Plugin from the current project.
+ *
+ * @author Evgeny Mandrikov
+ * @goal sonar-plugin
+ * @phase package
+ * @requiresProject
+ * @requiresDependencyResolution runtime
+ */
+public class SonarPluginMojo extends AbstractSonarPluginMojo {
+ private static final String LIB_DIR = "META-INF/lib/";
+ private static final String[] DEFAULT_EXCLUDES = new String[]{"**/package.html"};
+ private static final String[] DEFAULT_INCLUDES = new String[]{"**/**"};
+
+ /**
+ * List of files to include. Specified as fileset patterns which are relative to the input directory whose contents
+ * is being packaged into the JAR.
+ *
+ * @parameter
+ */
+ private String[] includes;
+
+ /**
+ * List of files to exclude. Specified as fileset patterns which are relative to the input directory whose contents
+ * is being packaged into the JAR.
+ *
+ * @parameter
+ */
+ private String[] excludes;
+
+ /**
+ * The Jar archiver.
+ *
+ * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="jar"
+ */
+ protected JarArchiver jarArchiver;
+
+ /**
+ * The archive configuration to use.
+ * See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver Reference</a>.
+ *
+ * @parameter
+ */
+ private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
+
+ /**
+ * @component
+ * @required
+ * @readonly
+ */
+ private DependencyTreeBuilder dependencyTreeBuilder;
+
+ /**
+ * The artifact repository to use.
+ *
+ * @parameter expression="${localRepository}"
+ * @required
+ * @readonly
+ */
+ private ArtifactRepository localRepository;
+
+ /**
+ * The artifact factory to use.
+ *
+ * @component
+ * @required
+ * @readonly
+ */
+ private ArtifactFactory artifactFactory;
+
+ /**
+ * The artifact metadata source to use.
+ *
+ * @component
+ * @required
+ * @readonly
+ */
+ private ArtifactMetadataSource artifactMetadataSource;
+
+ /**
+ * The artifact collector to use.
+ *
+ * @component
+ * @required
+ * @readonly
+ */
+ private ArtifactCollector artifactCollector;
+
+ /**
+ * @parameter expression="${sonar.addMavenDescriptor}"
+ */
+ private boolean addMavenDescriptor = true;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ File jarFile = createArchive();
+ String classifier = getClassifier();
+ if (classifier != null) {
+ projectHelper.attachArtifact(getProject(), "jar", classifier, jarFile);
+ } else {
+ getProject().getArtifact().setFile(jarFile);
+ }
+ }
+
+ public File createArchive() throws MojoExecutionException {
+ checkPluginClass();
+
+ File jarFile = getJarFile(getOutputDirectory(), getFinalName(), getClassifier());
+ MavenArchiver archiver = new MavenArchiver();
+ archiver.setArchiver(jarArchiver);
+ archiver.setOutputFile(jarFile);
+
+ try {
+ archiver.getArchiver().addDirectory(getClassesDirectory(), getIncludes(), getExcludes());
+ archive.setAddMavenDescriptor(addMavenDescriptor);
+ getLog().info("-------------------------------------------------------");
+ getLog().info("Plugin definition in update center");
+ addManifestProperty("Key", PluginManifest.KEY, getPluginKey());
+ addManifestProperty("Name", PluginManifest.NAME, getPluginName());
+ addManifestProperty("Description", PluginManifest.DESCRIPTION, getPluginDescription());
+ addManifestProperty("Version", PluginManifest.VERSION, getProject().getVersion());
+ addManifestProperty("Main class", PluginManifest.MAIN_CLASS, getPluginClass());
+ addManifestProperty("Homepage", PluginManifest.HOMEPAGE, getPluginUrl());
+ addManifestProperty("Sonar version", PluginManifest.SONAR_VERSION, getSonarPluginApiArtifact().getVersion());
+ addManifestProperty("License", PluginManifest.LICENSE, getPluginLicense());
+ addManifestProperty("Organization", PluginManifest.ORGANIZATION, getPluginOrganization());
+ addManifestProperty("Organization URL", PluginManifest.ORGANIZATION_URL, getPluginOrganizationUrl());
+ addManifestProperty("Terms & Conditions URL", PluginManifest.TERMS_CONDITIONS_URL, getPluginTermsConditionsUrl());
+ addManifestProperty("Issue Tracker URL", PluginManifest.ISSUE_TRACKER_URL, getPluginIssueTrackerUrl());
+ addManifestProperty("Build date", PluginManifest.BUILD_DATE, FormatUtils.toString(new Date(), true));
+ getLog().info("-------------------------------------------------------");
+
+ if (isSkipDependenciesPackaging()) {
+ getLog().info("Skip packaging of dependencies");
+
+ } else {
+ List<String> libs = copyDependencies();
+ if (!libs.isEmpty()) {
+ archiver.getArchiver().addDirectory(getAppDirectory(), getIncludes(), getExcludes());
+ archive.addManifestEntry(PluginManifest.DEPENDENCIES, StringUtils.join(libs, " "));
+ }
+ }
+
+ archiver.createArchive(getProject(), archive);
+ return jarFile;
+
+ } catch (Exception e) {
+ throw new MojoExecutionException("Error assembling Sonar-plugin: " + e.getMessage(), e);
+ }
+ }
+
+ private void addManifestProperty(String label, String key, String value) {
+ getLog().info(" " + label + ": " + StringUtils.defaultString(value));
+ archive.addManifestEntry(key, value);
+ }
+
+ private String getPluginLicense() {
+ List<String> licenses = new ArrayList<String>();
+ if (getProject().getLicenses() != null) {
+ for (Object license : getProject().getLicenses()) {
+ License l = (License) license;
+ if (l.getName() != null) {
+ licenses.add(l.getName());
+ }
+ }
+ }
+ return StringUtils.join(licenses, " ");
+ }
+
+ private String getPluginOrganization() {
+ if (getProject().getOrganization() != null) {
+ return getProject().getOrganization().getName();
+ }
+ return null;
+ }
+
+ private String getPluginOrganizationUrl() {
+ if (getProject().getOrganization() != null) {
+ return getProject().getOrganization().getUrl();
+ }
+ return null;
+ }
+
+
+ private void checkPluginClass() throws MojoExecutionException {
+ if (!new File(getClassesDirectory(), getPluginClass().replace('.', '/') + ".class").exists()) {
+ throw new MojoExecutionException("Error assembling Sonar-plugin: Plugin-Class '" + getPluginClass() + "' not found");
+ }
+ }
+
+ protected static File getJarFile(File basedir, String finalName, String classifier) {
+ if (classifier == null) {
+ classifier = "";
+ } else if (classifier.trim().length() > 0 && !classifier.startsWith("-")) {
+ classifier = "-" + classifier;
+ }
+ return new File(basedir, finalName + classifier + ".jar");
+ }
+
+
+ private List<String> copyDependencies() throws IOException, DependencyTreeBuilderException {
+ List<String> ids = new ArrayList<String>();
+ List<String> libs = new ArrayList<String>();
+ File libDirectory = new File(getAppDirectory(), LIB_DIR);
+ Set<Artifact> artifacts = getNotProvidedDependencies();
+ for (Artifact artifact : artifacts) {
+ String targetFileName = getDefaultFinalName(artifact);
+ FileUtils.copyFileIfModified(artifact.getFile(), new File(libDirectory, targetFileName));
+ libs.add(LIB_DIR + targetFileName);
+ ids.add(artifact.getDependencyConflictId());
+ }
+
+ if (!ids.isEmpty()) {
+ getLog().info(getMessage("Following dependencies are packaged in the plugin:", ids));
+ getLog().info(new StringBuilder()
+ .append("See following page for more details about plugin dependencies:\n")
+ .append("\n\thttp://docs.codehaus.org/display/SONAR/Coding+a+plugin\n")
+ .toString()
+ );
+ }
+ return libs;
+ }
+
+ private String getDefaultFinalName(Artifact artifact) {
+ return artifact.getArtifactId() + "-" + artifact.getVersion() + "." + artifact.getArtifactHandler().getExtension();
+ }
+
+
+ private Set<Artifact> getNotProvidedDependencies() throws DependencyTreeBuilderException {
+ Set<Artifact> result = new HashSet<Artifact>();
+ Set<Artifact> providedArtifacts = getSonarProvidedArtifacts();
+ for (Artifact artifact : getIncludedArtifacts()) {
+ if (!Artifact.SCOPE_PROVIDED.equals(artifact.getScope()) && !Artifact.SCOPE_TEST.equals(artifact.getScope()) && !containsArtifact(providedArtifacts, artifact)) {
+ result.add(artifact);
+ }
+ }
+ return result;
+ }
+
+ private boolean containsArtifact(Set<Artifact> artifacts, Artifact artifact) {
+ for (Artifact a : artifacts) {
+ if (StringUtils.equals(a.getGroupId(), artifact.getGroupId()) &&
+ StringUtils.equals(a.getArtifactId(), artifact.getArtifactId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private Set<Artifact> getSonarProvidedArtifacts() throws DependencyTreeBuilderException {
+ Set<Artifact> result = new HashSet<Artifact>();
+ ArtifactFilter artifactFilter = new ScopeArtifactFilter(Artifact.SCOPE_RUNTIME);
+ DependencyNode rootNode = dependencyTreeBuilder.buildDependencyTree(getProject(), localRepository, artifactFactory,
+ artifactMetadataSource, artifactFilter, artifactCollector);
+ rootNode.accept(new BuildingDependencyNodeVisitor());
+ searchForSonarProvidedArtifacts(rootNode, result, false);
+ return result;
+ }
+
+ private void searchForSonarProvidedArtifacts(DependencyNode dependency, Set<Artifact> sonarArtifacts, boolean isProvidedBySonar) {
+ if (dependency != null) {
+ isProvidedBySonar = isProvidedBySonar || ("org.codehaus.sonar".equals(dependency.getArtifact().getGroupId()) && !Artifact.SCOPE_TEST.equals(dependency.getArtifact().getScope()));
+
+ if (isProvidedBySonar) {
+ sonarArtifacts.add(dependency.getArtifact());
+ }
+
+ if (!Artifact.SCOPE_TEST.equals(dependency.getArtifact().getScope())) {
+ for (Object childDep : dependency.getChildren()) {
+ searchForSonarProvidedArtifacts((DependencyNode) childDep, sonarArtifacts, isProvidedBySonar);
+ }
+ }
+ }
+ }
+
+ private String[] getIncludes() {
+ if (includes != null && includes.length > 0) {
+ return includes;
+ }
+ return DEFAULT_INCLUDES;
+ }
+
+ private String[] getExcludes() {
+ if (excludes != null && excludes.length > 0) {
+ return excludes;
+ }
+ return DEFAULT_EXCLUDES;
+ }
+
+}
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/META-INF/plexus/components.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 00000000000..cd580be9914
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,43 @@
+<component-set>
+ <components>
+ <component>
+ <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
+ <role-hint>sonar-plugin</role-hint>
+ <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
+ <configuration>
+ <lifecycles>
+ <lifecycle>
+ <id>default</id>
+ <phases>
+ <!-- Sonar specific step -->
+ <initialize>org.codehaus.sonar:sonar-packaging-maven-plugin:check-dependencies</initialize>
+
+ <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
+ <compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
+ <process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
+ <test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
+ <test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
+
+ <!-- Sonar specific step -->
+ <package>org.codehaus.sonar:sonar-packaging-maven-plugin:sonar-plugin</package>
+
+ <install>org.apache.maven.plugins:maven-install-plugin:install</install>
+ <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
+ </phases>
+ </lifecycle>
+ </lifecycles>
+ </configuration>
+ </component>
+ <component>
+ <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
+ <role-hint>sonar-plugin</role-hint>
+ <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
+ <configuration>
+ <type>sonar-plugin</type>
+ <extension>jar</extension>
+ <language>java</language>
+ <addedToClasspath>true</addedToClasspath>
+ </configuration>
+ </component>
+ </components>
+</component-set>
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/AL2.txt b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/AL2.txt
new file mode 100644
index 00000000000..2550cc485b1
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/AL2.txt
@@ -0,0 +1,14 @@
+Copyright (C) ${year} ${name}
+mailto: ${mail}
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/LGPL3.txt b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/LGPL3.txt
new file mode 100644
index 00000000000..e7f3cc3e5ad
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/resources/license/LGPL3.txt
@@ -0,0 +1,17 @@
+Sonar, open source software quality management tool.
+Copyright (C) ${year} ${name}
+mailto: ${mail}
+
+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
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/pom.xml b/subprojects/sonar-update-center/sonar-update-center-common/pom.xml
new file mode 100644
index 00000000000..eb5da80b7bf
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-update-center</artifactId>
+ <version>0.3-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sonar-update-center-common</artifactId>
+ <name>Sonar :: Update Center :: Common</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <!-- unit tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Artifact.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Artifact.java
new file mode 100644
index 00000000000..0043705db60
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Artifact.java
@@ -0,0 +1,146 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import java.util.*;
+
+public abstract class Artifact implements Comparable<Artifact> {
+
+ protected String key;
+ protected SortedSet<Release> releases = new TreeSet<Release>();
+
+ protected Artifact(String key) {
+ this.key = key;
+ }
+
+ public final String getKey() {
+ return key;
+ }
+
+ public final Artifact setKey(String key) {
+ this.key = key;
+ return this;
+ }
+
+ public final Artifact setReleases(Collection<Release> releases) {
+ this.releases.clear();
+ if (releases != null) {
+ for (Release release : releases) {
+ addRelease(release);
+ }
+ }
+ return this;
+ }
+
+ public final Release addRelease(Release release) {
+ releases.add(release);
+ return release;
+ }
+
+ public final Release addRelease(Version version) {
+ return addRelease(new Release(this, version));
+ }
+
+ public final Release getRelease(Version version) {
+ for (Release release : getReleases()) {
+ if (release.getVersion().equals(version)) {
+ return release;
+ }
+ }
+ return null;
+ }
+
+ public final SortedSet<Release> getReleases() {
+ return releases;
+ }
+
+ /**
+ * Shortcut for Ruby code
+ */
+ public final SortedSet<Release> getReleasesGreaterThan(String version) {
+ return getReleasesGreaterThan(Version.create(version));
+ }
+
+ public final SortedSet<Release> getReleasesGreaterThan(Version version) {
+ TreeSet<Release> result = new TreeSet<Release>();
+ for (Release release : releases) {
+ if (release.getVersion().compareTo(version)>0) {
+ result.add(release);
+ }
+ }
+ return result;
+ }
+
+ public final SortedSet<Version> getVersions() {
+ SortedSet<Version> versions = new TreeSet<Version>();
+ for (Release release : releases) {
+ versions.add(release.getVersion());
+ }
+ return versions;
+ }
+
+ public final Release getLastRelease() {
+ return releases.isEmpty() ? null : releases.last();
+ }
+
+ public final Release getLastCompatibleRelease(Version sonarVersion) {
+ Release result = null;
+ for (Release r : releases) {
+ if (r.supportSonarVersion(sonarVersion)) {
+ result = r;
+ }
+ }
+ return result;
+ }
+
+ public final Release getLastCompatibleReleaseIfUpgrade(Version sonarVersion) {
+ Release result = null;
+ for (Release r : releases) {
+ if (r.getLastRequiredSonarVersion()!=null && r.getLastRequiredSonarVersion().compareTo(sonarVersion)>=0) {
+ result = r;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Artifact)) {
+ return false;
+ }
+ Artifact artifact = (Artifact) o;
+ return key.equals(artifact.key);
+ }
+
+ @Override
+ public final int hashCode() {
+ return key.hashCode();
+ }
+
+ public final int compareTo(Artifact other) {
+ if (key == null) {
+ return -1;
+ }
+ return key.compareTo(other.key);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/FormatUtils.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/FormatUtils.java
new file mode 100644
index 00000000000..c22dfdb94f1
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/FormatUtils.java
@@ -0,0 +1,55 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public final class FormatUtils {
+ public static final String DATE_PATTERN = "yyyy-MM-dd";
+ public static final String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ";
+
+ private FormatUtils() {
+ // only static methods
+ }
+
+ public static Date toDate(String s, boolean includeTime) {
+ String pattern = includeTime ? DATETIME_PATTERN : DATE_PATTERN;
+ try {
+ if (StringUtils.isNotBlank(s)) {
+ return new SimpleDateFormat(pattern).parse(s);
+ }
+ return null;
+
+ } catch (ParseException e) {
+ throw new RuntimeException("The following value does not respect the date pattern " + pattern + ": " + s, e);
+ }
+ }
+
+ public static String toString(Date d, boolean includeTime) {
+ if (d != null) {
+ return new SimpleDateFormat(includeTime ? DATETIME_PATTERN : DATE_PATTERN).format(d);
+ }
+ return null;
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Plugin.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Plugin.java
new file mode 100644
index 00000000000..d028b949ce2
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Plugin.java
@@ -0,0 +1,134 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.lang.StringUtils;
+
+public final class Plugin extends Artifact {
+
+ private String name;
+ private String description;
+ private String homepageUrl;
+ private String license;
+ private String organization;
+ private String organizationUrl;
+ private String termsConditionsUrl;
+ private String category;
+ private String issueTrackerUrl;
+
+ public Plugin(String key) {
+ super(key);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Plugin setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Plugin setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public String getHomepageUrl() {
+ return homepageUrl;
+ }
+
+ public Plugin setHomepageUrl(String s) {
+ this.homepageUrl = s;
+ return this;
+ }
+
+ public String getLicense() {
+ return license;
+ }
+
+ public Plugin setLicense(String license) {
+ this.license = license;
+ return this;
+ }
+
+ public String getOrganization() {
+ return organization;
+ }
+
+ public Plugin setOrganization(String organization) {
+ this.organization = organization;
+ return this;
+ }
+
+ public String getOrganizationUrl() {
+ return organizationUrl;
+ }
+
+ public Plugin setOrganizationUrl(String url) {
+ this.organizationUrl = url;
+ return this;
+ }
+
+ public String getCategory() {
+ return category;
+ }
+
+ public Plugin setCategory(String category) {
+ this.category = category;
+ return this;
+ }
+
+ public String getTermsConditionsUrl() {
+ return termsConditionsUrl;
+ }
+
+ public Plugin setTermsConditionsUrl(String url) {
+ this.termsConditionsUrl = url;
+ return this;
+ }
+
+ public String getIssueTrackerUrl() {
+ return issueTrackerUrl;
+ }
+
+ public Plugin setIssueTrackerUrl(String url) {
+ this.issueTrackerUrl = url;
+ return this;
+ }
+
+ public Plugin merge(PluginManifest manifest) {
+ if (StringUtils.equals(key, manifest.getKey())) {
+ name = manifest.getName();
+ description = manifest.getDescription();
+ organization = manifest.getOrganization();
+ organizationUrl = manifest.getOrganizationUrl();
+ issueTrackerUrl = manifest.getIssueTrackerUrl();
+ license = manifest.getLicense();
+ homepageUrl = manifest.getHomepage();
+ termsConditionsUrl = manifest.getTermsConditionsUrl();
+ }
+ return this;
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java
new file mode 100644
index 00000000000..59c4265a70d
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java
@@ -0,0 +1,251 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import static org.sonar.updatecenter.common.FormatUtils.toDate;
+
+/**
+ * This class loads Sonar plugin metadata from JAR manifest
+ *
+ * @since 2.2
+ */
+public final class PluginManifest {
+
+ public static final String KEY = "Plugin-Key";
+ public static final String MAIN_CLASS = "Plugin-Class";
+ public static final String NAME = "Plugin-Name";
+ public static final String DESCRIPTION = "Plugin-Description";
+ public static final String ORGANIZATION = "Plugin-Organization";
+ public static final String ORGANIZATION_URL = "Plugin-OrganizationUrl";
+ public static final String LICENSE = "Plugin-License";
+ public static final String VERSION = "Plugin-Version";
+ public static final String SONAR_VERSION = "Sonar-Version";
+ public static final String DEPENDENCIES = "Plugin-Dependencies";
+ public static final String HOMEPAGE = "Plugin-Homepage";
+ public static final String TERMS_CONDITIONS_URL = "Plugin-TermsConditionsUrl";
+ public static final String BUILD_DATE = "Build-Date";
+ public static final String ISSUE_TRACKER_URL = "Plugin-IssueTrackerUrl";
+
+ private String key;
+ private String name;
+ private String mainClass;
+ private String description;
+ private String organization;
+ private String organizationUrl;
+ private String license;
+ private String version;
+ private String sonarVersion;
+ private String[] dependencies = new String[0];
+ private String homepage;
+ private String termsConditionsUrl;
+ private Date buildDate;
+ private String issueTrackerUrl;
+
+
+ /**
+ * Load the manifest from a JAR file.
+ */
+ public PluginManifest(File file) throws IOException {
+ JarFile jar = new JarFile(file);
+ try {
+ if (jar.getManifest() != null) {
+ loadManifest(jar.getManifest());
+ }
+
+ } finally {
+ jar.close();
+ }
+ }
+
+ /**
+ * @param manifest, can not be null
+ */
+ public PluginManifest(Manifest manifest) {
+ loadManifest(manifest);
+ }
+
+ public PluginManifest() {
+ }
+
+ private void loadManifest(Manifest manifest) {
+ Attributes attributes = manifest.getMainAttributes();
+ this.key = attributes.getValue(KEY);
+ this.mainClass = attributes.getValue(MAIN_CLASS);
+ this.name = attributes.getValue(NAME);
+ this.description = attributes.getValue(DESCRIPTION);
+ this.license = attributes.getValue(LICENSE);
+ this.organization = attributes.getValue(ORGANIZATION);
+ this.organizationUrl = attributes.getValue(ORGANIZATION_URL);
+ this.version = attributes.getValue(VERSION);
+ this.homepage = attributes.getValue(HOMEPAGE);
+ this.termsConditionsUrl = attributes.getValue(TERMS_CONDITIONS_URL);
+ this.sonarVersion = attributes.getValue(SONAR_VERSION);
+ this.issueTrackerUrl = attributes.getValue(ISSUE_TRACKER_URL);
+ this.buildDate = toDate(attributes.getValue(BUILD_DATE), true);
+
+ String deps = attributes.getValue(DEPENDENCIES);
+ this.dependencies = StringUtils.split(StringUtils.defaultString(deps), ' ');
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public PluginManifest setKey(String key) {
+ this.key = key;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public PluginManifest setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public PluginManifest setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public String getOrganization() {
+ return organization;
+ }
+
+ public PluginManifest setOrganization(String organization) {
+ this.organization = organization;
+ return this;
+ }
+
+ public String getOrganizationUrl() {
+ return organizationUrl;
+ }
+
+ public PluginManifest setOrganizationUrl(String url) {
+ this.organizationUrl = url;
+ return this;
+ }
+
+ public String getLicense() {
+ return license;
+ }
+
+ public PluginManifest setLicense(String license) {
+ this.license = license;
+ return this;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public PluginManifest setVersion(String version) {
+ this.version = version;
+ return this;
+ }
+
+ public String getSonarVersion() {
+ return sonarVersion;
+ }
+
+ public PluginManifest setSonarVersion(String sonarVersion) {
+ this.sonarVersion = sonarVersion;
+ return this;
+ }
+
+ public String getMainClass() {
+ return mainClass;
+ }
+
+ public PluginManifest setMainClass(String mainClass) {
+ this.mainClass = mainClass;
+ return this;
+ }
+
+ public String[] getDependencies() {
+ return dependencies;
+ }
+
+ public PluginManifest setDependencies(String[] dependencies) {
+ this.dependencies = dependencies;
+ return this;
+ }
+
+ public Date getBuildDate() {
+ return buildDate;
+ }
+
+ public PluginManifest setBuildDate(Date buildDate) {
+ this.buildDate = buildDate;
+ return this;
+ }
+
+ public String getHomepage() {
+ return homepage;
+ }
+
+ public PluginManifest setHomepage(String homepage) {
+ this.homepage = homepage;
+ return this;
+ }
+
+ public String getTermsConditionsUrl() {
+ return termsConditionsUrl;
+ }
+
+ public PluginManifest setTermsConditionsUrl(String termsConditionsUrl) {
+ this.termsConditionsUrl = termsConditionsUrl;
+ return this;
+ }
+
+ public String getIssueTrackerUrl() {
+ return issueTrackerUrl;
+ }
+
+ public PluginManifest setIssueTrackerUrl(String issueTrackerUrl) {
+ this.issueTrackerUrl = issueTrackerUrl;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return new ReflectionToStringBuilder(this).toString();
+ }
+
+ public boolean isValid() {
+ return StringUtils.isNotBlank(key) && StringUtils.isNotBlank(version);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Release.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Release.java
new file mode 100644
index 00000000000..a719d4c0655
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Release.java
@@ -0,0 +1,165 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+public final class Release implements Comparable<Release> {
+
+ private Artifact artifact;
+ private Version version;
+ private String description;
+ private String downloadUrl;
+ private String changelogUrl;
+
+ /** from oldest to newest sonar versions */
+ private SortedSet<Version> requiredSonarVersions = new TreeSet<Version>();
+ private Date date;
+
+ public Release(Artifact artifact, Version version) {
+ this.artifact = artifact;
+ this.version = version;
+ }
+
+ public Release(Artifact artifact, String version) {
+ this.artifact = artifact;
+ this.version = Version.create(version);
+ }
+
+ public Artifact getArtifact() {
+ return artifact;
+ }
+
+ public Version getVersion() {
+ return version;
+ }
+
+ public Release setVersion(Version version) {
+ this.version = version;
+ return this;
+ }
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public Release setDownloadUrl(String s) {
+ this.downloadUrl = s;
+ return this;
+ }
+
+ public String getFilename() {
+ return StringUtils.substringAfterLast(downloadUrl, "/");
+ }
+
+ public SortedSet<Version> getRequiredSonarVersions() {
+ return requiredSonarVersions;
+ }
+
+ public boolean supportSonarVersion(Version version) {
+ return requiredSonarVersions.contains(version);
+ }
+
+ public Release addRequiredSonarVersions(Version... versions) {
+ if (versions!=null) {
+ requiredSonarVersions.addAll(Arrays.asList(versions));
+ }
+ return this;
+ }
+
+ public Release addRequiredSonarVersions(String... versions) {
+ if (versions!=null) {
+ for (String v : versions) {
+ requiredSonarVersions.add(Version.create(v));
+ }
+ }
+ return this;
+ }
+
+ public Version getLastRequiredSonarVersion() {
+ if (requiredSonarVersions!=null && !requiredSonarVersions.isEmpty()) {
+ return requiredSonarVersions.last();
+ }
+ return null;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public Release setDate(Date date) {
+ this.date = date;
+ return this;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getChangelogUrl() {
+ return changelogUrl;
+ }
+
+ public void setChangelogUrl(String changelogUrl) {
+ this.changelogUrl = changelogUrl;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Release that = (Release) o;
+ return version.equals(that.version);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return version.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("version", version)
+ .append("downloadUrl", downloadUrl)
+ .append("changelogUrl", changelogUrl)
+ .append("description", description)
+ .toString();
+ }
+
+ public int compareTo(Release o) {
+ return getVersion().compareTo(o.getVersion());
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Sonar.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Sonar.java
new file mode 100644
index 00000000000..de1acf44ca9
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Sonar.java
@@ -0,0 +1,37 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+public final class Sonar extends Artifact {
+
+ public Sonar() {
+ super("sonar");
+ }
+
+ /**
+ * shortcut only for sonar, no need to have other fields than version
+ */
+ public Sonar setReleases(String[] versions) {
+ for (String version : versions) {
+ addRelease(new Release(this, Version.create(version)));
+ }
+ return this;
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenter.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenter.java
new file mode 100644
index 00000000000..32bb11cc19b
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenter.java
@@ -0,0 +1,84 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class UpdateCenter {
+
+ private Sonar sonar = new Sonar();
+ private Set<Plugin> plugins = new HashSet<Plugin>();
+ private Date date;
+
+ public UpdateCenter() {
+ this(new Date());
+ }
+
+ public UpdateCenter(Date date) {
+ this.date = date;
+ }
+
+ public Set<Plugin> getPlugins() {
+ return plugins;
+ }
+
+ public Plugin getPlugin(String key) {
+ for (Plugin plugin : plugins) {
+ if (StringUtils.equals(key, plugin.getKey())) {
+ return plugin;
+ }
+ }
+ return null;
+ }
+
+ public UpdateCenter setPlugins(Collection<Plugin> plugins) {
+ this.plugins.clear();
+ this.plugins.addAll(plugins);
+ return this;
+ }
+
+ public UpdateCenter addPlugin(Plugin plugin) {
+ this.plugins.add(plugin);
+ return this;
+ }
+
+ public Sonar getSonar() {
+ return sonar;
+ }
+
+ public UpdateCenter setSonar(Sonar sonar) {
+ this.sonar = sonar;
+ return this;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public UpdateCenter setDate(Date date) {
+ this.date = date;
+ return this;
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterDeserializer.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterDeserializer.java
new file mode 100644
index 00000000000..dfc7de61055
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterDeserializer.java
@@ -0,0 +1,111 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Properties;
+
+import static org.sonar.updatecenter.common.FormatUtils.toDate;
+
+public final class UpdateCenterDeserializer {
+
+ private UpdateCenterDeserializer() {
+ // only static methods
+ }
+
+ public static UpdateCenter fromProperties(File file) throws IOException {
+ FileInputStream in = FileUtils.openInputStream(file);
+ try {
+ Properties props = new Properties();
+ props.load(in);
+ UpdateCenter center = fromProperties(props);
+ center.setDate(new Date(file.lastModified()));
+ return center;
+
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ public static UpdateCenter fromProperties(Properties p) {
+ UpdateCenter center = new UpdateCenter();
+ center.setDate(FormatUtils.toDate(p.getProperty("date"), true));
+ String[] sonarVersions = getArray(p, "sonar.versions");
+ for (String sonarVersion : sonarVersions) {
+ Release release = new Release(center.getSonar(), sonarVersion);
+ release.setChangelogUrl(get(p, "sonar." + sonarVersion + ".changelogUrl"));
+ release.setDescription(get(p, "sonar." + sonarVersion + ".description"));
+ release.setDownloadUrl(get(p, "sonar." + sonarVersion + ".downloadUrl"));
+ release.setDate(FormatUtils.toDate(get(p, "sonar." + sonarVersion + ".date"), true));
+ center.getSonar().addRelease(release);
+ }
+
+ String[] pluginKeys = getArray(p, "plugins");
+ for (String pluginKey : pluginKeys) {
+ Plugin plugin = new Plugin(pluginKey);
+ center.addPlugin(plugin);
+ plugin.setName(get(p, pluginKey, "name"));
+ plugin.setDescription(get(p, pluginKey, "description"));
+ plugin.setCategory(get(p, pluginKey, "category"));
+ plugin.setHomepageUrl(get(p, pluginKey, "homepageUrl"));
+ plugin.setLicense(get(p, pluginKey, "license"));
+ plugin.setOrganization(get(p, pluginKey, "organization"));
+ plugin.setOrganizationUrl(get(p, pluginKey, "organizationUrl"));
+ plugin.setTermsConditionsUrl(get(p, pluginKey, "termsConditionsUrl"));
+ plugin.setIssueTrackerUrl(get(p, pluginKey, "issueTrackerUrl"));
+
+ String[] pluginReleases = StringUtils.split(StringUtils.defaultIfEmpty(get(p, pluginKey, "versions"), ""), ",");
+ for (String pluginVersion : pluginReleases) {
+ Release release = new Release(plugin, pluginVersion);
+ plugin.addRelease(release);
+ release.setDownloadUrl(get(p, pluginKey, pluginVersion + ".downloadUrl"));
+ release.setChangelogUrl(get(p, pluginKey, pluginVersion + ".changelogUrl"));
+ release.setDescription(get(p, pluginKey, pluginVersion + ".description"));
+ release.setDate(toDate(get(p, pluginKey, pluginVersion + ".date"), true));
+ String[] requiredSonarVersions = StringUtils.split(StringUtils.defaultIfEmpty(get(p, pluginKey, pluginVersion + ".requiredSonarVersions"), ""), ",");
+ for (String requiredSonarVersion : requiredSonarVersions) {
+ release.addRequiredSonarVersions(Version.create(requiredSonarVersion));
+ }
+ }
+ }
+
+ return center;
+ }
+
+ private static String get(Properties props, String key) {
+ return StringUtils.defaultIfEmpty(props.getProperty(key), null);
+ }
+
+ private static String[] getArray(Properties props, String key) {
+ return StringUtils.split(StringUtils.defaultIfEmpty(props.getProperty(key), ""), ",");
+ }
+
+ private static String get(Properties p, String pluginKey, String field) {
+ return get(p, pluginKey + "." + field);
+ }
+
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterSerializer.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterSerializer.java
new file mode 100644
index 00000000000..f8f4856140c
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/UpdateCenterSerializer.java
@@ -0,0 +1,112 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+
+public final class UpdateCenterSerializer {
+
+ private static void set(Properties props, String key, String value) {
+ if (StringUtils.isNotBlank(value)) {
+ props.setProperty(key, value);
+ }
+ }
+
+ private static void set(Properties props, String key, Collection values) {
+ if (values != null && !values.isEmpty()) {
+ props.setProperty(key, StringUtils.join(values, ","));
+ }
+ }
+
+ private static void set(Properties props, Plugin plugin, String key, String value) {
+ if (StringUtils.isNotBlank(value)) {
+ props.setProperty(plugin.getKey() + "." + key, value);
+ }
+ }
+
+ private static void set(Properties props, Plugin plugin, String key, Collection values) {
+ if (values != null && !values.isEmpty()) {
+ props.setProperty(plugin.getKey() + "." + key, StringUtils.join(values, ","));
+ }
+ }
+
+ public static Properties toProperties(UpdateCenter center) {
+ Properties p = new Properties();
+ set(p, "date", FormatUtils.toString(center.getDate(), true));
+ set(p, "sonar.versions", center.getSonar().getVersions());
+ for (Release sonarRelease : center.getSonar().getReleases()) {
+ set(p, "sonar." + sonarRelease.getVersion() + ".downloadUrl", sonarRelease.getDownloadUrl());
+ set(p, "sonar." + sonarRelease.getVersion() + ".changelogUrl", sonarRelease.getChangelogUrl());
+ set(p, "sonar." + sonarRelease.getVersion() + ".description", sonarRelease.getDescription());
+ set(p, "sonar." + sonarRelease.getVersion() + ".date", FormatUtils.toString(sonarRelease.getDate(), true));
+ }
+
+ List<String> pluginKeys = new ArrayList<String>();
+ for (Plugin plugin : center.getPlugins()) {
+ pluginKeys.add(plugin.getKey());
+ set(p, plugin, "name", plugin.getName());
+ set(p, plugin, "description", plugin.getDescription());
+ set(p, plugin, "category", plugin.getCategory());
+ set(p, plugin, "homepageUrl", plugin.getHomepageUrl());
+ set(p, plugin, "license", plugin.getLicense());
+ set(p, plugin, "organization", plugin.getOrganization());
+ set(p, plugin, "organizationUrl", plugin.getOrganizationUrl());
+ set(p, plugin, "termsConditionsUrl", plugin.getTermsConditionsUrl());
+ set(p, plugin, "issueTrackerUrl", plugin.getIssueTrackerUrl());
+
+ List<String> releaseKeys = new ArrayList<String>();
+ for (Release release : plugin.getReleases()) {
+ releaseKeys.add(release.getVersion().toString());
+ set(p, plugin, release.getVersion() + ".requiredSonarVersions", StringUtils.join(release.getRequiredSonarVersions(), ","));
+ set(p, plugin, release.getVersion() + ".downloadUrl", release.getDownloadUrl());
+ set(p, plugin, release.getVersion() + ".changelogUrl", release.getChangelogUrl());
+ set(p, plugin, release.getVersion() + ".description", release.getDescription());
+ set(p, plugin, release.getVersion() + ".date", FormatUtils.toString(release.getDate(), true));
+ }
+ set(p, plugin, "versions", releaseKeys);
+ }
+ set(p, "plugins", pluginKeys);
+ return p;
+ }
+
+ public static void toProperties(UpdateCenter sonar, File toFile) {
+ FileOutputStream output = null;
+ try {
+ output = FileUtils.openOutputStream(toFile);
+ toProperties(sonar).store(output, "Generated file");
+
+ } catch (IOException e) {
+ throw new RuntimeException("Fail to store Sonar properties to: " + toFile.getAbsolutePath(), e);
+
+ } finally {
+ IOUtils.closeQuietly(output);
+ }
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Version.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Version.java
new file mode 100644
index 00000000000..74a45335ce4
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/Version.java
@@ -0,0 +1,138 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.lang.StringUtils;
+
+public class Version implements Comparable<Version> {
+
+ private String normalizedMajor = normalizePart("0");
+ private String normalizedMinor = normalizePart("0");
+ private String normalizedPatch = normalizePart("0");
+ private String normalizedPatch2 = normalizePart("0");
+ private String major = "0";
+ private String minor = "0";
+ private String patch = "0";
+ private String patch2 = "0";
+ private String name;
+
+ private Version(String version) {
+ this.name = StringUtils.trimToEmpty(version);
+ String[] split = StringUtils.split(name, '.');
+ if (split.length >= 1) {
+ major = split[0];
+ normalizedMajor = normalizePart(major);
+ }
+ if (split.length >= 2) {
+ minor = split[1];
+ normalizedMinor = normalizePart(minor);
+ }
+ if (split.length >= 3) {
+ patch = split[2];
+ normalizedPatch = normalizePart(patch);
+ }
+ if (split.length >= 4) {
+ patch2 = split[3];
+ normalizedPatch2 = normalizePart(patch2);
+ }
+ }
+
+ private static String normalizePart(String part) {
+ return StringUtils.leftPad(part, 4, '0');
+ }
+
+ public String getMajor() {
+ return major;
+ }
+
+ public String getMinor() {
+ return minor;
+ }
+
+ public String getPatch() {
+ return patch;
+ }
+
+ public String getPatch2() {
+ return patch2;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Version version = (Version) o;
+ if (!normalizedMajor.equals(version.normalizedMajor)) {
+ return false;
+ }
+ if (!normalizedMinor.equals(version.normalizedMinor)) {
+ return false;
+ }
+ if (!normalizedPatch.equals(version.normalizedPatch)) {
+ return false;
+ }
+ if (!normalizedPatch2.equals(version.normalizedPatch2)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = normalizedMajor.hashCode();
+ result = 31 * result + normalizedMinor.hashCode();
+ result = 31 * result + normalizedPatch.hashCode();
+ result = 31 * result + normalizedPatch2.hashCode();
+ return result;
+ }
+
+ public int compareTo(Version other) {
+ // TODO : manage RC, alpha, ...
+ int c = normalizedMajor.compareTo(other.normalizedMajor);
+ if (c == 0) {
+ c = normalizedMinor.compareTo(other.normalizedMinor);
+ if (c == 0) {
+ c = normalizedPatch.compareTo(other.normalizedPatch);
+ if (c == 0) {
+ c = normalizedPatch2.compareTo(other.normalizedPatch2);
+ }
+ }
+ }
+ return c;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ public static Version create(String version) {
+ return new Version(version);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ArtifactTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ArtifactTest.java
new file mode 100644
index 00000000000..7f31a2c500c
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ArtifactTest.java
@@ -0,0 +1,76 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class ArtifactTest {
+
+ @Test
+ public void compare() {
+ Artifact a = new FakeArtifact("a");
+ Artifact b = new FakeArtifact("b");
+ Artifact c = new Plugin("c");
+
+ List<Artifact> list = Arrays.asList(b, a, c);
+ Collections.sort(list);
+ assertThat(list.get(0), is(a));
+ assertThat(list.get(1), is(b));
+ assertThat(list.get(2), is(c));
+ }
+
+ @Test
+ public void sortReleases() {
+ FakeArtifact artifact = new FakeArtifact("fake");
+ artifact.addRelease(Version.create("2.0"));
+ artifact.addRelease(Version.create("1.1"));
+ artifact.addRelease(Version.create("1.5"));
+
+ Iterator<Release> it = artifact.getReleases().iterator();
+ assertThat(it.next().getVersion().getName(), is("1.1"));
+ assertThat(it.next().getVersion().getName(), is("1.5"));
+ assertThat(it.next().getVersion().getName(), is("2.0"));
+ }
+
+ @Test
+ public void equals() {
+ FakeArtifact foo = new FakeArtifact("foo");
+ assertTrue(foo.equals(new FakeArtifact("foo")));
+ assertTrue(foo.equals(foo));
+ assertFalse(foo.equals(new FakeArtifact("bar")));
+ }
+}
+
+class FakeArtifact extends Artifact {
+
+ protected FakeArtifact(String key) {
+ super(key);
+ }
+} \ No newline at end of file
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/FormatUtilsTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/FormatUtilsTest.java
new file mode 100644
index 00000000000..ea477a061d7
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/FormatUtilsTest.java
@@ -0,0 +1,41 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.junit.Test;
+
+import java.text.ParseException;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+public class FormatUtilsTest {
+
+ @Test
+ public void testToDate() throws ParseException {
+ assertThat(FormatUtils.toDate("2010-05-18", false).getDate(), is(18));
+ }
+
+ @Test
+ public void ignoreNullDate() {
+ assertNull(FormatUtils.toDate(null, true));
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginManifestTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginManifestTest.java
new file mode 100644
index 00000000000..ac00a6ecf26
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginManifestTest.java
@@ -0,0 +1,59 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.number.OrderingComparisons.greaterThan;
+import static org.junit.Assert.assertThat;
+
+public class PluginManifestTest {
+
+ @Test
+ public void testCreateManifest() throws URISyntaxException, IOException {
+ URL jar = getClass().getResource("/org/sonar/updatecenter/common/PluginManifestTest/checkstyle-plugin.jar");
+ PluginManifest manifest = new PluginManifest(new File(jar.toURI()));
+
+ assertThat(manifest.getKey(), is("checkstyle"));
+ assertThat(manifest.getName(), is("Checkstyle"));
+ assertThat(manifest.getMainClass(), is("org.sonar.plugins.checkstyle.CheckstylePlugin"));
+ assertThat(manifest.getVersion().length(), greaterThan(1));
+ assertThat(manifest.getDependencies().length, is(4));
+ assertThat(manifest.getDependencies()[0], is("META-INF/lib/antlr-2.7.6.jar"));
+ }
+
+ @Test
+ public void doNotFailWhenNoOldPluginManifest() throws URISyntaxException, IOException {
+ URL jar = getClass().getResource("/org/sonar/updatecenter/common/PluginManifestTest/old-plugin.jar");
+ PluginManifest manifest = new PluginManifest(new File(jar.toURI()));
+
+ assertThat(manifest.getKey(), nullValue());
+ assertThat(manifest.getName(), nullValue());
+ assertThat(manifest.getMainClass(), is("org.sonar.plugins.checkstyle.CheckstylePlugin"));
+ assertThat(manifest.getDependencies().length, is(0));
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ReleaseTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ReleaseTest.java
new file mode 100644
index 00000000000..e5a6d9228e6
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/ReleaseTest.java
@@ -0,0 +1,38 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.junit.Test;
+
+import static junit.framework.Assert.assertNull;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+public class ReleaseTest {
+
+ @Test
+ public void getFilename() {
+ Release release = new Release(new Plugin("fake"), Version.create("1.2"));
+ assertNull(release.getFilename());
+
+ release.setDownloadUrl("http://dist.sonarsource.org/foo-1.2.jar");
+ assertThat(release.getFilename(), is("foo-1.2.jar"));
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterDeserializerTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterDeserializerTest.java
new file mode 100644
index 00000000000..3ad836d75a6
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterDeserializerTest.java
@@ -0,0 +1,56 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
+
+public class UpdateCenterDeserializerTest {
+
+ @Test
+ public void fromProperties() throws IOException {
+ InputStream input = getClass().getResourceAsStream("/org/sonar/updatecenter/common/UpdateCenterDeserializerTest/updates.properties");
+ try {
+ Properties props = new Properties();
+ props.load(input);
+ UpdateCenter center = UpdateCenterDeserializer.fromProperties(props);
+
+ assertThat(center.getSonar().getVersions(), hasItems(Version.create("2.2"), Version.create("2.3")));
+ assertThat(center.getSonar().getRelease(Version.create("2.2")).getDownloadUrl(), is("http://dist.sonar.codehaus.org/sonar-2.2.zip"));
+
+ Plugin clirr = center.getPlugin("clirr");
+ assertThat(clirr.getName(), is("Clirr"));
+ assertThat(clirr.getDescription(), is("Clirr Plugin"));
+ assertThat(clirr.getVersions(),hasItems(Version.create("1.0"), Version.create("1.1")));
+ assertThat(clirr.getRelease(Version.create("1.0")).getDownloadUrl(), is("http://dist.sonar-plugins.codehaus.org/clirr-1.0.jar"));
+
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterSerializerTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterSerializerTest.java
new file mode 100644
index 00000000000..8924e638582
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterSerializerTest.java
@@ -0,0 +1,61 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Properties;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class UpdateCenterSerializerTest {
+
+ @Test
+ public void testToProperties() throws IOException, URISyntaxException {
+ UpdateCenter center = new UpdateCenter();
+
+ center.getSonar().addRelease(Version.create("2.0"));
+ center.getSonar().addRelease(Version.create("2.1"));
+ center.addPlugin(new Plugin("foo").setName("Foo").setOrganizationUrl("http://www.sonarsource.org"));
+ Plugin barPlugin = new Plugin("bar");
+ center.addPlugin(barPlugin);
+ barPlugin.addRelease(
+ new Release(barPlugin, Version.create("1.2"))
+ .addRequiredSonarVersions(Version.create("2.0"))
+ .addRequiredSonarVersions(Version.create("2.1")));
+
+ Properties properties = UpdateCenterSerializer.toProperties(center);
+ properties.store(System.out, null);
+
+ assertProperty(properties, "sonar.versions", "2.0,2.1");
+ assertProperty(properties, "plugins", "foo,bar");
+ assertProperty(properties, "foo.name", "Foo");
+ assertProperty(properties, "foo.organizationUrl", "http://www.sonarsource.org");
+ assertProperty(properties, "bar.versions", "1.2");
+ assertProperty(properties, "bar.1.2.requiredSonarVersions", "2.0,2.1");
+ }
+
+ private void assertProperty(Properties props, String key, String value) {
+ assertThat(props.getProperty(key), is(value));
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterTest.java
new file mode 100644
index 00000000000..a624c884cdc
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/UpdateCenterTest.java
@@ -0,0 +1,44 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class UpdateCenterTest {
+
+ @Test
+ public void getAndSetPlugins() {
+ Plugin foo = new Plugin("foo");
+ Plugin bar = new Plugin("bar");
+
+ UpdateCenter center = new UpdateCenter();
+ center.addPlugin(foo);
+ center.addPlugin(bar);
+
+ assertEquals(foo, center.getPlugin("foo"));
+ assertNull(center.getPlugin("unknown"));
+ assertThat(center.getPlugins().size(), is(2));
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/VersionTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/VersionTest.java
new file mode 100644
index 00000000000..8059f223fdc
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/VersionTest.java
@@ -0,0 +1,102 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.common;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertTrue;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.number.OrderingComparisons.greaterThan;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+
+public class VersionTest {
+
+ @Test
+ public void testCompare() {
+ Version version12 = Version.create("1.2");
+ Version version121 = Version.create("1.2.1");
+
+ assertThat(version12.toString(), is("1.2"));
+ assertThat(version12.compareTo(version12), is(0));
+ assertThat(version121.compareTo(version121), is(0));
+
+ assertTrue(version121.compareTo(version12)>0);
+ assertTrue(version12.compareTo(version121)<0);
+ }
+
+ @Test
+ @Ignore("TODO : support alpha, beta, snapshot versions")
+ public void testCompareReleaseAndSnapshot() {
+ Version version12 = Version.create("1.2");
+ Version version12SNAPSHOT = Version.create("1.2-SNAPSHOT");
+
+ assertThat(version12.compareTo(version12SNAPSHOT), greaterThan(0));
+ }
+
+ @Test
+ public void testTrim() {
+ Version version12 = Version.create(" 1.2 ");
+ assertThat(version12.getName(), is("1.2"));
+ assertTrue(version12.equals(Version.create("1.2")));
+ }
+
+ @Test
+ public void testDefaultNumberIsZero() {
+ Version version12 = Version.create("1.2");
+ Version version120 = Version.create("1.2.0");
+ assertTrue(version12.equals(version120));
+ assertTrue(version120.equals(version12));
+ }
+
+
+ @Test
+ public void testCompareOnTwoDigits() {
+ Version version1dot10 = Version.create("1.10");
+ Version version1dot1 = Version.create("1.1");
+ Version version1dot9 = Version.create("1.9");
+
+ assertTrue(version1dot10.compareTo(version1dot1)>0);
+ assertTrue(version1dot10.compareTo(version1dot9)>0);
+ }
+
+ @Test
+ public void testFields() {
+ Version version = Version.create("1.10.2");
+ assertThat(version.getName(), is("1.10.2"));
+ assertThat(version.toString(), is("1.10.2"));
+ assertThat(version.getMajor(), is("1"));
+ assertThat(version.getMinor(), is("10"));
+ assertThat(version.getPatch(), is("2"));
+ assertThat(version.getPatch2(), is("0"));
+ }
+
+ @Test
+ public void testPatchFields() {
+ Version version = Version.create("1.2.3.4");
+ assertThat(version.getPatch(), is("3"));
+ assertThat(version.getPatch2(), is("4"));
+
+ assertTrue(version.equals(version));
+ assertTrue(version.equals(Version.create("1.2.3.4")));
+ assertFalse(version.equals(Version.create("1.2.3.5")));
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/checkstyle-plugin.jar b/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/checkstyle-plugin.jar
new file mode 100644
index 00000000000..ef5994d4f70
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/checkstyle-plugin.jar
Binary files differ
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/old-plugin.jar b/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/old-plugin.jar
new file mode 100644
index 00000000000..571c3a953d5
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/PluginManifestTest/old-plugin.jar
Binary files differ
diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/UpdateCenterDeserializerTest/updates.properties b/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/UpdateCenterDeserializerTest/updates.properties
new file mode 100644
index 00000000000..29360aeb23c
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/resources/org/sonar/updatecenter/common/UpdateCenterDeserializerTest/updates.properties
@@ -0,0 +1,17 @@
+sonar.versions=2.2,2.3
+sonar.2.2.downloadUrl=http://dist.sonar.codehaus.org/sonar-2.2.zip
+sonar.2.3.downloadUrl=http://dist.sonar.codehaus.org/sonar-2.3.zip
+sonar.2.3.description=sonar 2.3
+
+plugins=clirr,motionchart
+
+clirr.name=Clirr
+clirr.description=Clirr Plugin
+clirr.license=LGPL
+clirr.versions=1.0,1.1
+clirr.1.0.downloadUrl=http://dist.sonar-plugins.codehaus.org/clirr-1.0.jar
+clirr.1.1.downloadUrl=http://dist.sonar-plugins.codehaus.org/clirr-1.1.jar
+clirr.1.1.description=clirr 1.1
+
+motionchart.name=Motion Chart
+motionchart.description=Motion Chart Plugin \ No newline at end of file
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/pom.xml b/subprojects/sonar-update-center/sonar-update-center-server/pom.xml
new file mode 100644
index 00000000000..ad5f9faa4aa
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-update-center</artifactId>
+ <version>0.3-SNAPSHOT</version>
+ </parent>
+ <artifactId>sonar-update-center-server</artifactId>
+ <name>Sonar :: Update Center :: Server</name>
+
+ <properties>
+ <maven.version>3.0-beta-1</maven.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-update-center-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>xpp3</groupId>
+ <artifactId>xpp3</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.5.6</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>0.9.15</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-compat</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-http</artifactId>
+ <version>1.0-beta-5</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.5</version>
+ </dependency>
+
+ <dependency>
+ <groupId>args4j</groupId>
+ <artifactId>args4j</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+
+
+ <!-- experimental -->
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.0.1</version>
+ </dependency>
+
+
+ <!-- unit tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <version>1.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.sonar.updatecenter.deprecated.UpdateCenter</mainClass>
+ <arguments>
+ <argument>-d</argument>
+ <argument>${project.basedir}/target/site</argument>
+ </arguments>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>wagon-maven-plugin</artifactId>
+ <configuration>
+ <serverId>sonar-plugins</serverId>
+ <fromDir>${project.basedir}/target/site</fromDir>
+ <includes>**</includes>
+ <url>dav:https://dav.codehaus.org/dist/sonar-plugins/update-center</url>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/History.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/History.java
new file mode 100644
index 00000000000..f9b4de9e11d
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/History.java
@@ -0,0 +1,56 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * Information about release history, discovered from Maven repository.
+ *
+ * @author Evgeny Mandrikov
+ */
+public class History<M extends Versioned> {
+
+ private TreeMap<ArtifactVersion, M> artifacts = new TreeMap<ArtifactVersion, M>();
+
+ public History() {
+ }
+
+ public Set<ArtifactVersion> getAllVersions() {
+ return artifacts.keySet();
+ }
+
+ /**
+ * @return latest version of plugin
+ */
+ public M latest() {
+ if (artifacts.size() == 0) {
+ return null;
+ }
+ return artifacts.get(artifacts.lastKey());
+ }
+
+ public void addArtifact(ArtifactVersion version, M artifact) {
+ artifacts.put(version, artifact);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Plugin.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Plugin.java
new file mode 100644
index 00000000000..7dbf87a5374
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Plugin.java
@@ -0,0 +1,206 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+import org.apache.maven.model.Developer;
+import org.json.simple.JSONObject;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+/**
+ * Information about Sonar Plugin.
+ *
+ * @author Evgeny Mandrikov
+ */
+public class Plugin implements Versioned {
+ private String key;
+ private String name;
+ private String description;
+ private String version;
+ private String downloadUrl;
+ private String requiredSonarVersion;
+ private String homepage;
+ private long timestamp;
+
+ private String pluginClass;
+ private String issueTracker;
+ private String sources;
+ private String license;
+
+ private List<Developer> developers;
+
+ public Plugin(String pluginKey) {
+ this.key = pluginKey;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ /**
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * @return version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getReleaseDate() {
+ return (new SimpleDateFormat("d MMM yyyy")).format(new Date(timestamp));
+ }
+
+ private void setDate(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ /**
+ * @return URL for downloading
+ */
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ /**
+ * @return minimal Sonar version to run this plugin
+ */
+ public String getRequiredSonarVersion() {
+ // TODO Sonar-Version from MANIFEST.MF
+ return requiredSonarVersion;
+ }
+
+ public void setRequiredSonarVersion(String sonarVersion) {
+ this.requiredSonarVersion = sonarVersion;
+ }
+
+ /**
+ * @return homepage
+ */
+ public String getHomepage() {
+ // TODO Plugin-Homepage from MANIFEST.MF
+ return homepage;
+ }
+
+ public void setHomepage(String homepage) {
+ this.homepage = homepage;
+ }
+
+ public String getIssueTracker() {
+ return issueTracker;
+ }
+
+ public void setIssueTracker(String url) {
+ this.issueTracker = url;
+ }
+
+ public String getSources() {
+ return sources;
+ }
+
+ public void setSources(String sources) {
+ this.sources = sources;
+ }
+
+ public String getLicense() {
+ return license;
+ }
+
+ public void setLicense(String license) {
+ this.license = license;
+ }
+
+ public List<Developer> getDevelopers() {
+ return developers;
+ }
+
+ public void setDevelopers(List<Developer> developers) {
+ this.developers = developers;
+ }
+
+ public JSONObject toJsonObject() {
+ JSONObject obj = new JSONObject();
+ obj.put("id", getKey());
+ obj.put("name", getName());
+ obj.put("version", getVersion());
+ obj.put("sonarVersion", getRequiredSonarVersion());
+ if (getDownloadUrl() != null) {
+ obj.put("downloadUrl", getDownloadUrl());
+ }
+ if (getHomepage() != null) {
+ obj.put("homepage", getHomepage());
+ }
+ return obj;
+ }
+
+ public static Plugin extractMetadata(File file) throws IOException {
+ JarFile jar = new JarFile(file);
+ ZipEntry entry = jar.getEntry("META-INF/MANIFEST.MF");
+ long timestamp = entry.getTime();
+ Manifest manifest = jar.getManifest();
+ jar.close();
+
+ Attributes attributes = manifest.getMainAttributes();
+ String pluginKey = attributes.getValue("Plugin-Key");
+ Plugin plugin = new Plugin(pluginKey);
+ plugin.setName(attributes.getValue("Plugin-Name"));
+ plugin.setVersion(attributes.getValue("Plugin-Version"));
+ plugin.setRequiredSonarVersion(attributes.getValue("Sonar-Version"));
+ plugin.setHomepage(attributes.getValue("Plugin-Homepage"));
+ plugin.setDate(timestamp);
+ return plugin;
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Sonar.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Sonar.java
new file mode 100644
index 00000000000..cb652459af1
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Sonar.java
@@ -0,0 +1,58 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+import org.json.simple.JSONObject;
+
+/**
+ * Information about Sonar.
+ *
+ * @author Evgeny Mandrikov
+ */
+public class Sonar implements Versioned {
+
+ private final String version;
+
+ public Sonar(String version) {
+ this.version = version;
+ }
+
+ /**
+ * @return Sonar version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * @return URL for downloading
+ */
+ public String getDownloadUrl() {
+ return "http://dist.sonar.codehaus.org/sonar-" + getVersion() + ".zip";
+ }
+
+ public JSONObject toJsonObject() {
+ JSONObject obj = new JSONObject();
+ obj.put("version", getVersion());
+ obj.put("downloadUrl", getDownloadUrl());
+ return obj;
+ }
+
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateCenter.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateCenter.java
new file mode 100644
index 00000000000..7e95d397679
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateCenter.java
@@ -0,0 +1,318 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
+import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
+import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Developer;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectBuilder;
+import org.codehaus.plexus.ContainerConfiguration;
+import org.codehaus.plexus.DefaultContainerConfiguration;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.classworlds.ClassWorld;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Evgeny Mandrikov
+ */
+public class UpdateCenter {
+ // FIXME value set only for debug purposes
+ @Option(name = "-d")
+ public File outputDirectory = new File("/tmp/site");
+
+ private static final String ARTIFACT_JAR_TYPE = "jar";
+ private static final String ARTIFACT_POM_TYPE = "pom";
+
+ private List<ArtifactRepository> remoteRepositories;
+ private ArtifactRepository localRepository;
+
+ private ArtifactFactory artifactFactory;
+ private ArtifactResolver artifactResolver;
+ private ArtifactMetadataSource metadataSource;
+ private MavenProjectBuilder mavenProjectBuilder;
+
+ private void run() throws Exception {
+ // Init plexus
+ ClassWorld classWorld = new ClassWorld("plexus.core", UpdateCenter.class.getClassLoader());
+ ContainerConfiguration configuration = new DefaultContainerConfiguration().setClassWorld(classWorld);
+ PlexusContainer plexus = new DefaultPlexusContainer(configuration);
+ // Init components
+ artifactFactory = plexus.lookup(ArtifactFactory.class);
+ artifactResolver = plexus.lookup(ArtifactResolver.class);
+ metadataSource = plexus.lookup(ArtifactMetadataSource.class);
+ mavenProjectBuilder = plexus.lookup(MavenProjectBuilder.class);
+ ArtifactRepositoryFactory artifactRepositoryFactory = plexus.lookup(ArtifactRepositoryFactory.class);
+ // Init repositories
+ ArtifactRepositoryPolicy policy = new ArtifactRepositoryPolicy(
+ true,
+ ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY,
+ ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN
+ );
+ remoteRepositories = Collections.singletonList( // TODO add SonarSource repository with commercial plugins
+ artifactRepositoryFactory.createArtifactRepository(
+ "codehaus",
+ "http://repository.codehaus.org/",
+ new DefaultRepositoryLayout(),
+ policy,
+ policy
+ )
+ );
+ File localRepo = new File(new File(System.getProperty("user.home")), ".m2/repository");
+ localRepository = artifactRepositoryFactory.createArtifactRepository(
+ "local",
+ localRepo.toURI().toURL().toExternalForm(),
+ new DefaultRepositoryLayout(),
+ policy,
+ policy
+ );
+ // Do work
+ JSONObject obj = new JSONObject();
+
+ obj.put("version", "1"); // We can bump this version, when we make incompatible changes
+ obj.put("plugins", resolvePlugins());
+ obj.put("sonar", resolveSonar());
+
+ if (outputDirectory != null) {
+ FileUtils.writeStringToFile(new File(outputDirectory, "update-center.json"), obj.toJSONString());
+ }
+ }
+
+ private JSONArray resolvePlugins() throws Exception {
+ List<String> plugins = FileUtils.readLines(FileUtils.toFile(getClass().getResource("/plugins.txt")));
+
+ String pluginInfoWidgetTemplate = FileUtils.readFileToString(
+ FileUtils.toFile(getClass().getResource("/plugin-info-widget-template.html"))
+ );
+ if (outputDirectory != null) {
+ FileUtils.copyURLToFile(getClass().getResource("/style.css"), new File(outputDirectory, "plugins/style.css"));
+ }
+
+ JSONArray json = new JSONArray();
+ for (String plugin : plugins) {
+ if (plugin.startsWith("#")) {
+ // Skip comments
+ continue;
+ }
+ History<Plugin> history = resolvePluginHistory(plugin);
+ if (history.latest() == null) {
+ System.out.println("WTF? " + plugin);
+ continue;
+ }
+ json.add(history.latest().toJsonObject());
+
+ Plugin latest = history.latest();
+
+ if (outputDirectory != null) {
+ String pluginInfoWidget = StringUtils.replaceEach(
+ pluginInfoWidgetTemplate,
+ new String[]{"%name%", "%version%", "%date%", "%downloadUrl%", "%sonarVersion%", "%issueTracker%", "%sources%", "%license%", "%developers%"},
+ new String[]{
+ latest.getName(),
+ latest.getVersion(),
+ latest.getReleaseDate(),
+ latest.getDownloadUrl(),
+ latest.getRequiredSonarVersion(),
+ formatLink(latest.getIssueTracker()),
+ formatLink(latest.getSources()),
+ latest.getLicense() == null ? "Unknown" : latest.getLicense(),
+ formatDevelopers(latest.getDevelopers())
+ }
+ );
+ FileUtils.writeStringToFile(new File(outputDirectory, "plugins/" + latest.getKey() + ".html"), pluginInfoWidget);
+ }
+
+ // TODO use logger
+ System.out.println(latest.getName() + " : " + history.getAllVersions() + ", latest " + latest.getVersion());
+ }
+
+ return json;
+ }
+
+ private String formatDevelopers(List<Developer> developers) {
+ if (developers == null) {
+ return "Unknown";
+ }
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < developers.size(); i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(developers.get(i).getName());
+ }
+ return sb.toString();
+ }
+
+ private String formatLink(String url) {
+ return StringUtils.isBlank(url) ? "Unknown" : "<a href=\"" + url + "\" target=\"_top\">" + url + "</a>";
+ }
+
+ private JSONObject resolveSonar() throws Exception {
+ Artifact artifact = artifactFactory.createArtifact(
+ "org.codehaus.sonar",
+ "sonar-plugin-api",
+ Artifact.LATEST_VERSION,
+ Artifact.SCOPE_COMPILE,
+ ARTIFACT_JAR_TYPE
+ );
+
+ List<ArtifactVersion> versions = filterSnapshots(
+ metadataSource.retrieveAvailableVersions(artifact, localRepository, remoteRepositories)
+ );
+ History<Sonar> history = new History<Sonar>();
+ for (ArtifactVersion version : versions) {
+ history.addArtifact(version, new Sonar(version.toString()));
+ }
+
+ return history.latest().toJsonObject();
+ }
+
+ private String getDownloadUrl(String groupId, String artifactId, String version) {
+ // FIXME dirty hack
+ return "http://repository.codehaus.org/"
+ + StringUtils.replace(groupId, ".", "/") + "/"
+ + artifactId + "/"
+ + version + "/"
+ + artifactId + "-" + version + "." + ARTIFACT_JAR_TYPE;
+ }
+
+ private History<Plugin> resolvePluginHistory(String id) throws Exception {
+ String groupId = StringUtils.substringBefore(id, ":");
+ String artifactId = StringUtils.substringAfter(id, ":");
+
+ Artifact artifact = artifactFactory.createArtifact(
+ groupId, artifactId, Artifact.LATEST_VERSION, Artifact.SCOPE_COMPILE, ARTIFACT_JAR_TYPE
+ );
+
+ List<ArtifactVersion> versions = filterSnapshots(
+ metadataSource.retrieveAvailableVersions(artifact, localRepository, remoteRepositories)
+ );
+
+ History<Plugin> history = new History<Plugin>();
+ for (ArtifactVersion version : versions) {
+ Plugin plugin = org.sonar.updatecenter.deprecated.Plugin.extractMetadata(resolve(artifact.getGroupId(), artifact.getArtifactId(), version.toString()));
+ history.addArtifact(version, plugin);
+
+ MavenProject project = mavenProjectBuilder.buildFromRepository(
+ artifactFactory.createArtifact(groupId, artifactId, version.toString(), Artifact.SCOPE_COMPILE, ARTIFACT_POM_TYPE),
+ remoteRepositories,
+ localRepository
+ );
+
+ if (plugin.getVersion() == null) {
+ // Legacy plugin - set default values
+ plugin.setKey(project.getArtifactId());
+ plugin.setName(project.getName());
+ plugin.setVersion(project.getVersion());
+
+ String sonarVersion = "1.10"; // TODO Is it minimal version for all extension points ?
+ for (Dependency dependency : project.getDependencies()) {
+ if ("sonar-plugin-api".equals(dependency.getArtifactId())) { // TODO dirty hack
+ sonarVersion = dependency.getVersion();
+ }
+ }
+
+ plugin.setRequiredSonarVersion(sonarVersion);
+ plugin.setHomepage(project.getUrl());
+ }
+ plugin.setDownloadUrl(getDownloadUrl(groupId, artifactId, plugin.getVersion()));
+ // There is no equivalent for following properties in MANIFEST.MF
+ if (project.getIssueManagement() != null) {
+ plugin.setIssueTracker(project.getIssueManagement().getUrl());
+ } else {
+ System.out.println("Unknown Issue Management for " + plugin.getKey() + ":" + plugin.getVersion());
+ }
+ if (project.getScm() != null) {
+ String scmUrl = project.getScm().getUrl();
+ if (StringUtils.startsWith(scmUrl, "scm:")) {
+ scmUrl = StringUtils.substringAfter(StringUtils.substringAfter(scmUrl, ":"), ":");
+ }
+ plugin.setSources(scmUrl);
+ } else {
+ System.out.println("Unknown SCM for " + plugin.getKey() + ":" + plugin.getVersion());
+ }
+ if (project.getLicenses() != null && project.getLicenses().size() > 0) {
+ plugin.setLicense(project.getLicenses().get(0).getName());
+ } else {
+ System.out.println("Unknown License for " + plugin.getKey() + ":" + plugin.getVersion());
+ }
+ if (project.getDevelopers().size() > 0) {
+ plugin.setDevelopers(project.getDevelopers());
+ } else {
+ System.out.println("Unknown Developers for " + plugin.getKey() + ":" + plugin.getVersion());
+ }
+ }
+ return history;
+ }
+
+ private List<ArtifactVersion> filterSnapshots(List<ArtifactVersion> versions) {
+ List<ArtifactVersion> result = new ArrayList<ArtifactVersion>();
+ for (ArtifactVersion version : versions) {
+ // Ignore snapshots
+ if (!"SNAPSHOT".equalsIgnoreCase(version.getQualifier())) {
+ result.add(version);
+ }
+ }
+ return result;
+ }
+
+ private File resolve(String groupId, String artifactId, String version) throws Exception {
+ return resolve(groupId, artifactId, version, ARTIFACT_JAR_TYPE);
+ }
+
+ private File resolve(String groupId, String artifactId, String version, String type) throws Exception {
+ Artifact artifact = artifactFactory.createArtifact(groupId, artifactId, version, Artifact.SCOPE_COMPILE, type);
+ ArtifactResolutionRequest request = new ArtifactResolutionRequest()
+ .setArtifact(artifact)
+ .setResolveTransitively(false)
+ .setLocalRepository(localRepository)
+ .setRemoteRepositories(remoteRepositories);
+ artifactResolver.resolve(request);
+ return artifact.getFile();
+ }
+
+ public static void main(String[] args) throws Exception {
+ UpdateCenter updateCenter = new UpdateCenter();
+ CmdLineParser p = new CmdLineParser(updateCenter);
+ p.parseArgument(args);
+
+ updateCenter.run();
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateInfo.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateInfo.java
new file mode 100644
index 00000000000..bf65ee8a861
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/UpdateInfo.java
@@ -0,0 +1,42 @@
+package org.sonar.updatecenter.deprecated;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Information about updates.
+ *
+ * @author Evgeny Mandrikov
+ */
+@XStreamAlias("updateInfo")
+public class UpdateInfo {
+
+ public Sonar sonar;
+
+ @XStreamImplicit(itemFieldName = "plugin")
+ public List<Plugin> plugins;
+
+ public UpdateInfo(Sonar sonar, List<Plugin> plugins) {
+ this.sonar = sonar;
+ this.plugins = plugins;
+ }
+
+ public static void main(String[] args) {
+ XStream xstream = new XStream();
+ xstream.autodetectAnnotations(true);
+
+ Plugin plugin = new Plugin("sonar-test-plugin");
+ plugin.setVersion("0.1");
+ plugin.setName("Sonar Test Plugin");
+ plugin.setDescription("Test");
+ plugin.setHomepage("http://homepage");
+ plugin.setDownloadUrl("http://download");
+ plugin.setRequiredSonarVersion("2.0");
+
+ System.out.println(xstream.toXML(new UpdateInfo(new Sonar("2.0"), Arrays.asList(plugin))));
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Versioned.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Versioned.java
new file mode 100644
index 00000000000..fc50234c990
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/deprecated/Versioned.java
@@ -0,0 +1,27 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+/**
+ * @author Evgeny Mandrikov
+ */
+public interface Versioned {
+ String getVersion();
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Configuration.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Configuration.java
new file mode 100644
index 00000000000..165b7883562
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Configuration.java
@@ -0,0 +1,94 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.server;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+public class Configuration {
+
+ public static final String WORKING_DIR = "workingDir";
+ public static final String OUTPUT_FILE = "outputFile";
+ public static final String SOURCE_PATH = "path";
+ public static final String SOURCE_LOGIN = "login";
+ public static final String SOURCE_PASSWORD = "password";
+
+ private static Logger LOG = LoggerFactory.getLogger(Configuration.class);
+ private Properties props;
+ private File workingDir = null;
+
+ public Configuration(Properties props) {
+ this.props = props;
+ }
+
+ public void log() {
+ LOG.info("-------------------------------");
+ LOG.info(WORKING_DIR + ": " + getWorkingDir().getPath());
+ LOG.info(OUTPUT_FILE + ": " + getOutputFile().getPath());
+ LOG.info(SOURCE_PATH + ": " + getSourcePath());
+ LOG.info(SOURCE_LOGIN + ": " + getSourceLogin());
+ LOG.info(SOURCE_PASSWORD + ": " + getSourcePassword());
+ LOG.info("-------------------------------");
+ }
+
+ public File getWorkingDir() {
+ if (workingDir == null) {
+ String path = props.getProperty(WORKING_DIR);
+ if (StringUtils.isBlank(path)) {
+ workingDir = new File(System.getProperty("user.home"), ".sonar-update-center");
+ } else {
+ workingDir = new File(path);
+ }
+ try {
+ FileUtils.forceMkdir(workingDir);
+
+ } catch (IOException e) {
+ throw new RuntimeException("Fail to create the working directory: " + workingDir.getAbsolutePath(), e);
+ }
+ }
+ return workingDir;
+ }
+
+ public File getOutputFile() {
+ String path = props.getProperty(OUTPUT_FILE);
+ if (StringUtils.isNotBlank(path)) {
+ return new File(path);
+ }
+ return new File(getWorkingDir(), "generated-sonar-updates.properties");
+ }
+
+ public String getSourcePath() {
+ return props.getProperty(SOURCE_PATH);
+ }
+
+ public String getSourceLogin() {
+ return props.getProperty(SOURCE_LOGIN);
+ }
+
+ public String getSourcePassword() {
+ return props.getProperty(SOURCE_PASSWORD);
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/HttpDownloader.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/HttpDownloader.java
new file mode 100644
index 00000000000..44aad96b860
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/HttpDownloader.java
@@ -0,0 +1,102 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.server;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public class HttpDownloader {
+ private static Logger LOG = LoggerFactory.getLogger(HttpDownloader.class);
+
+ private File outputDir;
+
+ public HttpDownloader(File outputDir) {
+ this.outputDir = outputDir;
+ }
+
+ public File download(String url, boolean force) throws IOException, URISyntaxException {
+ return download(url, force, null, null);
+ }
+ public File download(String url, boolean force, String login, String password) throws IOException, URISyntaxException {
+ FileUtils.forceMkdir(outputDir);
+
+ String filename = StringUtils.substringAfterLast(url, "/");
+ File output = new File(outputDir, filename);
+ if (force || !output.exists() || output.length() <= 0) {
+ downloadFile(new URI(url), output, login, password);
+ } else {
+ LOG.info("Already downloaded: " + url);
+ }
+ return output;
+ }
+
+ File downloadFile(URI fileURI, File toFile, String login, String password) {
+ LOG.error("Download " + fileURI + " in " + toFile);
+ DefaultHttpClient client = new DefaultHttpClient();
+ try {
+ if (StringUtils.isNotBlank(login)) {
+ client.getCredentialsProvider().setCredentials(
+ new AuthScope(fileURI.getHost(), fileURI.getPort()),
+ new UsernamePasswordCredentials(login, password));
+ }
+ HttpGet httpget = new HttpGet(fileURI);
+ byte[] data = client.execute(httpget, new ByteResponseHandler());
+ if (data != null) {
+ FileUtils.writeByteArrayToFile(toFile, data);
+ }
+
+ } catch (Exception e) {
+ LOG.error("Fail to download " + fileURI + " to " + toFile, e);
+ FileUtils.deleteQuietly(toFile);
+
+ } finally {
+ client.getConnectionManager().shutdown();
+ }
+ return toFile;
+ }
+
+ static class ByteResponseHandler implements ResponseHandler<byte[]> {
+ public byte[] handleResponse(HttpResponse response) throws IOException {
+ HttpEntity entity = response.getEntity();
+ if (response.getStatusLine().getStatusCode()!=200) {
+ throw new RuntimeException("Unvalid HTTP response: " + response.getStatusLine());
+ }
+ if (entity != null) {
+ return EntityUtils.toByteArray(entity);
+ }
+ return null;
+ }
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/MetadataFile.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/MetadataFile.java
new file mode 100644
index 00000000000..a0207021726
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/MetadataFile.java
@@ -0,0 +1,72 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.server;
+
+import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.UpdateCenterDeserializer;
+
+import java.io.File;
+import java.io.IOException;
+
+public final class MetadataFile {
+
+ private Configuration conf;
+ private HttpDownloader downloader;
+
+ public MetadataFile(Configuration conf, HttpDownloader downloader) {
+ this.conf = conf;
+ this.downloader = downloader;
+ }
+
+ public File getFile() {
+ try {
+ File file;
+ if (isRemote()) {
+ file = downloader.download(conf.getSourcePath(), true, conf.getSourceLogin(), conf.getSourcePassword());
+ } else {
+ file = new File(conf.getSourcePath());
+ }
+ if (!file.exists()) {
+ throw new RuntimeException("The metadata file does not exist: " + file.getPath());
+ }
+ return file;
+
+ } catch (RuntimeException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new RuntimeException("Can not open the metadata file: " + conf.getSourcePath(), e);
+ }
+ }
+
+ public UpdateCenter getUpdateCenter() {
+ File file = getFile();
+ try {
+ return UpdateCenterDeserializer.fromProperties(file);
+
+ } catch (IOException e) {
+ throw new RuntimeException("Can not read properties from: " + file.getPath(), e);
+ }
+ }
+
+ private boolean isRemote() {
+ return conf.getSourcePath().startsWith("http");
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Server.java b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Server.java
new file mode 100644
index 00000000000..4288ba2e8a1
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/java/org/sonar/updatecenter/server/Server.java
@@ -0,0 +1,83 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.server;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.updatecenter.common.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+public final class Server {
+ private static Logger LOG = LoggerFactory.getLogger(Server.class);
+
+ public void start() throws IOException, URISyntaxException {
+ Configuration conf = new Configuration(System.getProperties());
+ conf.log();
+ HttpDownloader downloader = new HttpDownloader(conf.getWorkingDir());
+ UpdateCenter center = buildFromPartialMetadata(conf, downloader);
+ downloadReleases(downloader, center);
+ generateMetadata(conf, center);
+ }
+
+ private UpdateCenter buildFromPartialMetadata(Configuration conf, HttpDownloader downloader) {
+ return new MetadataFile(conf, downloader).getUpdateCenter();
+ }
+
+ private void downloadReleases(HttpDownloader downloader, UpdateCenter center) throws IOException, URISyntaxException {
+ for (Plugin plugin : center.getPlugins()) {
+ LOG.info("Load plugin: " + plugin.getKey());
+
+ File masterJar = null;
+ for (Release release : plugin.getReleases()) {
+ if (StringUtils.isNotBlank(release.getDownloadUrl())) {
+ File jar = downloader.download(release.getDownloadUrl(), false);
+ if (jar!= null && jar.exists()) {
+ masterJar = jar;
+ } else {
+ release.setDownloadUrl(null);
+ LOG.warn("Ignored because of wrong downloadUrl: plugin " + plugin.getKey() + ", version " + release.getVersion());
+ }
+
+ } else {
+ LOG.warn("Ignored because of missing downloadUrl: plugin " + plugin.getKey() + ", version " + release.getVersion());
+ }
+ }
+
+ // the last release is the master version for loading metadata included in manifest
+ if (masterJar != null) {
+ plugin.merge(new PluginManifest(masterJar));
+ }
+ }
+ }
+
+ private void generateMetadata(Configuration conf, UpdateCenter center) {
+ LOG.info("Generate output: " + conf.getOutputFile());
+ UpdateCenterSerializer.toProperties(center, conf.getOutputFile());
+ }
+
+ public static void main(String[] args) throws IOException, URISyntaxException {
+ new Server().start();
+ }
+
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/log4j.properties b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/log4j.properties
new file mode 100644
index 00000000000..be19b35722a
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootCategory=INFO, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+
+log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugin-info-widget-template.html b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugin-info-widget-template.html
new file mode 100644
index 00000000000..2abbbb8f41a
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugin-info-widget-template.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+ <title>%name%</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta name="generator" content="Sonar Update Center" />
+ <style type="text/css">
+ @import url("style.css");
+ </style>
+</head>
+<body>
+<a href="%downloadUrl%" class="button">Download</a>
+<table cellpadding="0" cellspacing="0">
+ <tr>
+ <td><strong>Name</strong></td>
+ <td>%name%</td>
+ </tr>
+ <tr>
+ <td><strong>Latest version</strong></td>
+ <td><strong>%version%</strong> ( %date% )</td>
+ </tr>
+ <tr>
+ <td><strong>Requires Sonar version</strong></td>
+ <td>
+ <strong>%sonarVersion%</strong> or higher
+ ( check <a href="http://docs.codehaus.org/display/SONAR/Plugin+version+matrix" target="_top">version compatibility</a> )
+ </td>
+ </tr>
+ <tr>
+ <td><strong>License</strong></td>
+ <td>%license%</td>
+ </tr>
+ <tr>
+ <td><strong>Developers</strong></td>
+ <td>%developers%</td>
+ </tr>
+ <tr>
+ <td><strong>Issue tracker</strong></td>
+ <td>%issueTracker%</td>
+ </tr>
+ <tr>
+ <td><strong>Sources</strong></td>
+ <td>%sources%</td>
+ </tr>
+</table>
+</body>
+</html>
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugins.txt b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugins.txt
new file mode 100644
index 00000000000..222e5a4b0cb
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/plugins.txt
@@ -0,0 +1,38 @@
+#
+# Open-source plugins
+#
+org.codehaus.sonar-plugins:sonar-artifact-size-plugin
+org.codehaus.sonar-plugins:sonar-build-breaker-plugin
+org.codehaus.sonar-plugins:sonar-build-stability-plugin
+org.codehaus.sonar-plugins:sonar-clirr-plugin
+org.codehaus.sonar-plugins:sonar-crowd-plugin
+org.codehaus.sonar-plugins:sonar-emma-plugin
+org.codehaus.sonar-plugins:sonar-flex-plugin
+org.codehaus.sonar-plugins:sonar-greenpepper-plugin
+org.codehaus.sonar-plugins:sonar-jacoco-plugin
+org.codehaus.sonar-plugins:sonar-jira-plugin
+org.codehaus.sonar-plugins:sonar-ldap-plugin
+org.codehaus.sonar-plugins:sonar-motion-chart-plugin
+org.codehaus.sonar-plugins:sonar-piwik-plugin
+org.codehaus.sonar-plugins:sonar-plugin-taglist
+org.codehaus.sonar-plugins:sonar-quality-index-plugin
+org.codehaus.sonar-plugins:sonar-radiator-plugin
+org.codehaus.sonar-plugins:sonar-rulesmeter-plugin
+org.codehaus.sonar-plugins:sonar-security-rules-plugin
+org.codehaus.sonar-plugins:sonar-sigmm-plugin
+org.codehaus.sonar-plugins:sonar-sonarj-plugin
+org.codehaus.sonar-plugins:sonar-taglist-plugin
+org.codehaus.sonar-plugins:sonar-technicaldebt-plugin
+org.codehaus.sonar-plugins:sonar-timeline-plugin
+org.codehaus.sonar-plugins:sonar-total-quality-plugin
+org.codehaus.sonar-plugins:sonar-trac-plugin
+org.codehaus.sonar-plugins:sonar-twitter-plugin
+org.codehaus.sonar-plugins.scm-activity:sonar-scm-activity-plugin
+org.codehaus.sonar-plugins:sonar-groovy-plugin
+org.codehaus.sonar-plugins:sonar-web-plugin
+#
+# Incorrect artifactId
+#
+#org.codehaus.sonar-plugins:pdf-report
+#org.codehaus.sonar-plugins:technical-debt
+#org.codehaus.sonar-plugins:emma
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/style.css b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/style.css
new file mode 100644
index 00000000000..a3215e49890
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/main/resources/style.css
@@ -0,0 +1,29 @@
+body {
+ font-family: Verdana,arial,sans-serif;
+ font-size: 9pt;
+}
+a {
+ color: #036;
+}
+table {
+ border-collapse: collapse;
+ width: 100%;
+}
+table td {
+ border: 1px #CCC solid;
+ padding: 3px;
+ font-size: 9pt;
+}
+th {
+ text-align: left;
+}
+.button {
+ background: #3C78B5;
+ text-align: center;
+ border-radius: 3px;
+ display: block;
+ padding: 5px;
+ cursor: pointer;
+ margin: 5px;
+ color: white;
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/HistoryTest.java b/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/HistoryTest.java
new file mode 100644
index 00000000000..f0563ee42f1
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/HistoryTest.java
@@ -0,0 +1,53 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Evgeny Mandrikov
+ */
+public class HistoryTest {
+ @Test
+ public void testLatest() {
+ History<Plugin> history = new History<Plugin>();
+
+ history.addArtifact(new DefaultArtifactVersion("0.1"), newPlugin("0.1"));
+ assertEquals(1, history.getAllVersions().size());
+ assertEquals("0.1", history.latest().getVersion());
+
+ history.addArtifact(new DefaultArtifactVersion("1.0"), newPlugin("1.0"));
+ assertEquals(2, history.getAllVersions().size());
+ assertEquals("1.0", history.latest().getVersion());
+
+ history.addArtifact(new DefaultArtifactVersion("0.2"), newPlugin("0.2"));
+ assertEquals(3, history.getAllVersions().size());
+ assertEquals("1.0", history.latest().getVersion());
+ }
+
+ private Plugin newPlugin(String version) {
+ Plugin plugin = new Plugin(version);
+ plugin.setVersion(version);
+ return plugin;
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/PluginTest.java b/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/PluginTest.java
new file mode 100644
index 00000000000..95914a870e3
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/PluginTest.java
@@ -0,0 +1,60 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Evgeny Mandrikov
+ */
+public class PluginTest {
+ @Test
+ public void testToJsonObject() {
+ /*
+ Plugin plugin = new Plugin("org.sonar.plugins.test.Test");
+ plugin.setVersion("0.1");
+ plugin.setName("Sonar Test Plugin");
+ plugin.setRequiredSonarVersion("2.0");
+ assertEquals(
+ "{\"sonarVersion\":\"2.0\"" +
+ ",\"id\":\"org.sonar.plugins.test.Test\"" +
+ ",\"name\":\"Sonar Test Plugin\"" +
+ ",\"version\":\"0.1\"" +
+ "}",
+ plugin.toJsonObject().toJSONString()
+ );
+
+ plugin.setDownloadUrl("http://download");
+ plugin.setHomepage("http://homepage");
+ assertEquals(
+ "{\"sonarVersion\":\"2.0\"" +
+ ",\"id\":\"org.sonar.plugins.test.Test\"" +
+ ",\"name\":\"Sonar Test Plugin\"" +
+ ",\"downloadUrl\":\"http:\\/\\/download\"" +
+ ",\"homepage\":\"http:\\/\\/homepage\"" +
+ ",\"version\":\"0.1\"" +
+ "}",
+ plugin.toJsonObject().toJSONString()
+ );
+ */
+ }
+}
diff --git a/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/SonarTest.java b/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/SonarTest.java
new file mode 100644
index 00000000000..efcae7fe7f8
--- /dev/null
+++ b/subprojects/sonar-update-center/sonar-update-center-server/src/test/java/org/sonar/updatecenter/deprecated/SonarTest.java
@@ -0,0 +1,41 @@
+/*
+ * Sonar, open source software quality management 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
+ */
+package org.sonar.updatecenter.deprecated;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Evgeny Mandrikov
+ */
+public class SonarTest {
+ @Test
+ public void testToJsonObject() throws Exception {
+ /*
+ assertEquals(
+ "{\"downloadUrl\":\"http:\\/\\/dist.sonar.codehaus.org\\/sonar-2.0.zip\"" +
+ ",\"version\":\"2.0\"" +
+ "}",
+ new Sonar("2.0").toJsonObject().toJSONString()
+ );
+ */
+ }
+}