diff options
Diffstat (limited to 'subprojects/sonar-update-center')
77 files changed, 5197 insertions, 0 deletions
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 Binary files differnew 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 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 Binary files differnew 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 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() + ); + */ + } +} |