2 * Sonar, open source software quality management tool.
3 * Copyright (C) 2009 SonarSource SA
4 * mailto:contact AT sonarsource DOT com
6 * Sonar is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * Sonar is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Sonar; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
20 package org.sonar.updatecenter.deprecated;
22 import org.apache.commons.io.FileUtils;
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.maven.artifact.Artifact;
25 import org.apache.maven.artifact.factory.ArtifactFactory;
26 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
27 import org.apache.maven.artifact.repository.ArtifactRepository;
28 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
29 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
30 import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
31 import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
32 import org.apache.maven.artifact.resolver.ArtifactResolver;
33 import org.apache.maven.artifact.versioning.ArtifactVersion;
34 import org.apache.maven.model.Dependency;
35 import org.apache.maven.model.Developer;
36 import org.apache.maven.project.MavenProject;
37 import org.apache.maven.project.MavenProjectBuilder;
38 import org.codehaus.plexus.ContainerConfiguration;
39 import org.codehaus.plexus.DefaultContainerConfiguration;
40 import org.codehaus.plexus.DefaultPlexusContainer;
41 import org.codehaus.plexus.PlexusContainer;
42 import org.codehaus.plexus.classworlds.ClassWorld;
43 import org.json.simple.JSONArray;
44 import org.json.simple.JSONObject;
45 import org.kohsuke.args4j.CmdLineParser;
46 import org.kohsuke.args4j.Option;
49 import java.util.ArrayList;
50 import java.util.Collections;
51 import java.util.List;
54 * @author Evgeny Mandrikov
56 public class UpdateCenter {
57 // FIXME value set only for debug purposes
59 public File outputDirectory = new File("/tmp/site");
61 private static final String ARTIFACT_JAR_TYPE = "jar";
62 private static final String ARTIFACT_POM_TYPE = "pom";
64 private List<ArtifactRepository> remoteRepositories;
65 private ArtifactRepository localRepository;
67 private ArtifactFactory artifactFactory;
68 private ArtifactResolver artifactResolver;
69 private ArtifactMetadataSource metadataSource;
70 private MavenProjectBuilder mavenProjectBuilder;
72 private void run() throws Exception {
74 ClassWorld classWorld = new ClassWorld("plexus.core", UpdateCenter.class.getClassLoader());
75 ContainerConfiguration configuration = new DefaultContainerConfiguration().setClassWorld(classWorld);
76 PlexusContainer plexus = new DefaultPlexusContainer(configuration);
78 artifactFactory = plexus.lookup(ArtifactFactory.class);
79 artifactResolver = plexus.lookup(ArtifactResolver.class);
80 metadataSource = plexus.lookup(ArtifactMetadataSource.class);
81 mavenProjectBuilder = plexus.lookup(MavenProjectBuilder.class);
82 ArtifactRepositoryFactory artifactRepositoryFactory = plexus.lookup(ArtifactRepositoryFactory.class);
84 ArtifactRepositoryPolicy policy = new ArtifactRepositoryPolicy(
86 ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY,
87 ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN
89 remoteRepositories = Collections.singletonList( // TODO add SonarSource repository with commercial plugins
90 artifactRepositoryFactory.createArtifactRepository(
92 "http://repository.codehaus.org/",
93 new DefaultRepositoryLayout(),
98 File localRepo = new File(new File(System.getProperty("user.home")), ".m2/repository");
99 localRepository = artifactRepositoryFactory.createArtifactRepository(
101 localRepo.toURI().toURL().toExternalForm(),
102 new DefaultRepositoryLayout(),
107 JSONObject obj = new JSONObject();
109 obj.put("version", "1"); // We can bump this version, when we make incompatible changes
110 obj.put("plugins", resolvePlugins());
111 obj.put("sonar", resolveSonar());
113 if (outputDirectory != null) {
114 FileUtils.writeStringToFile(new File(outputDirectory, "update-center.json"), obj.toJSONString());
118 private JSONArray resolvePlugins() throws Exception {
119 List<String> plugins = FileUtils.readLines(FileUtils.toFile(getClass().getResource("/plugins.txt")));
121 String pluginInfoWidgetTemplate = FileUtils.readFileToString(
122 FileUtils.toFile(getClass().getResource("/plugin-info-widget-template.html"))
124 if (outputDirectory != null) {
125 FileUtils.copyURLToFile(getClass().getResource("/style.css"), new File(outputDirectory, "plugins/style.css"));
128 JSONArray json = new JSONArray();
129 for (String plugin : plugins) {
130 if (plugin.startsWith("#")) {
134 History<Plugin> history = resolvePluginHistory(plugin);
135 if (history.latest() == null) {
136 System.out.println("WTF? " + plugin);
139 json.add(history.latest().toJsonObject());
141 Plugin latest = history.latest();
143 if (outputDirectory != null) {
144 String pluginInfoWidget = StringUtils.replaceEach(
145 pluginInfoWidgetTemplate,
146 new String[]{"%name%", "%version%", "%date%", "%downloadUrl%", "%sonarVersion%", "%issueTracker%", "%sources%", "%license%", "%developers%"},
150 latest.getReleaseDate(),
151 latest.getDownloadUrl(),
152 latest.getRequiredSonarVersion(),
153 formatLink(latest.getIssueTracker()),
154 formatLink(latest.getSources()),
155 latest.getLicense() == null ? "Unknown" : latest.getLicense(),
156 formatDevelopers(latest.getDevelopers())
159 FileUtils.writeStringToFile(new File(outputDirectory, "plugins/" + latest.getKey() + ".html"), pluginInfoWidget);
163 System.out.println(latest.getName() + " : " + history.getAllVersions() + ", latest " + latest.getVersion());
169 private String formatDevelopers(List<Developer> developers) {
170 if (developers == null) {
173 StringBuilder sb = new StringBuilder();
174 for (int i = 0; i < developers.size(); i++) {
178 sb.append(developers.get(i).getName());
180 return sb.toString();
183 private String formatLink(String url) {
184 return StringUtils.isBlank(url) ? "Unknown" : "<a href=\"" + url + "\" target=\"_top\">" + url + "</a>";
187 private JSONObject resolveSonar() throws Exception {
188 Artifact artifact = artifactFactory.createArtifact(
189 "org.codehaus.sonar",
191 Artifact.LATEST_VERSION,
192 Artifact.SCOPE_COMPILE,
196 List<ArtifactVersion> versions = filterSnapshots(
197 metadataSource.retrieveAvailableVersions(artifact, localRepository, remoteRepositories)
199 History<Sonar> history = new History<Sonar>();
200 for (ArtifactVersion version : versions) {
201 history.addArtifact(version, new Sonar(version.toString()));
204 return history.latest().toJsonObject();
207 private String getDownloadUrl(String groupId, String artifactId, String version) {
209 return "http://repository.codehaus.org/"
210 + StringUtils.replace(groupId, ".", "/") + "/"
213 + artifactId + "-" + version + "." + ARTIFACT_JAR_TYPE;
216 private History<Plugin> resolvePluginHistory(String id) throws Exception {
217 String groupId = StringUtils.substringBefore(id, ":");
218 String artifactId = StringUtils.substringAfter(id, ":");
220 Artifact artifact = artifactFactory.createArtifact(
221 groupId, artifactId, Artifact.LATEST_VERSION, Artifact.SCOPE_COMPILE, ARTIFACT_JAR_TYPE
224 List<ArtifactVersion> versions = filterSnapshots(
225 metadataSource.retrieveAvailableVersions(artifact, localRepository, remoteRepositories)
228 History<Plugin> history = new History<Plugin>();
229 for (ArtifactVersion version : versions) {
230 Plugin plugin = org.sonar.updatecenter.deprecated.Plugin.extractMetadata(resolve(artifact.getGroupId(), artifact.getArtifactId(), version.toString()));
231 history.addArtifact(version, plugin);
233 MavenProject project = mavenProjectBuilder.buildFromRepository(
234 artifactFactory.createArtifact(groupId, artifactId, version.toString(), Artifact.SCOPE_COMPILE, ARTIFACT_POM_TYPE),
239 if (plugin.getVersion() == null) {
240 // Legacy plugin - set default values
241 plugin.setKey(project.getArtifactId());
242 plugin.setName(project.getName());
243 plugin.setVersion(project.getVersion());
245 String sonarVersion = "1.10"; // TODO Is it minimal version for all extension points ?
246 for (Dependency dependency : project.getDependencies()) {
247 if ("sonar-plugin-api".equals(dependency.getArtifactId())) { // TODO dirty hack
248 sonarVersion = dependency.getVersion();
252 plugin.setRequiredSonarVersion(sonarVersion);
253 plugin.setHomepage(project.getUrl());
255 plugin.setDownloadUrl(getDownloadUrl(groupId, artifactId, plugin.getVersion()));
256 // There is no equivalent for following properties in MANIFEST.MF
257 if (project.getIssueManagement() != null) {
258 plugin.setIssueTracker(project.getIssueManagement().getUrl());
260 System.out.println("Unknown Issue Management for " + plugin.getKey() + ":" + plugin.getVersion());
262 if (project.getScm() != null) {
263 String scmUrl = project.getScm().getUrl();
264 if (StringUtils.startsWith(scmUrl, "scm:")) {
265 scmUrl = StringUtils.substringAfter(StringUtils.substringAfter(scmUrl, ":"), ":");
267 plugin.setSources(scmUrl);
269 System.out.println("Unknown SCM for " + plugin.getKey() + ":" + plugin.getVersion());
271 if (project.getLicenses() != null && project.getLicenses().size() > 0) {
272 plugin.setLicense(project.getLicenses().get(0).getName());
274 System.out.println("Unknown License for " + plugin.getKey() + ":" + plugin.getVersion());
276 if (project.getDevelopers().size() > 0) {
277 plugin.setDevelopers(project.getDevelopers());
279 System.out.println("Unknown Developers for " + plugin.getKey() + ":" + plugin.getVersion());
285 private List<ArtifactVersion> filterSnapshots(List<ArtifactVersion> versions) {
286 List<ArtifactVersion> result = new ArrayList<ArtifactVersion>();
287 for (ArtifactVersion version : versions) {
289 if (!"SNAPSHOT".equalsIgnoreCase(version.getQualifier())) {
296 private File resolve(String groupId, String artifactId, String version) throws Exception {
297 return resolve(groupId, artifactId, version, ARTIFACT_JAR_TYPE);
300 private File resolve(String groupId, String artifactId, String version, String type) throws Exception {
301 Artifact artifact = artifactFactory.createArtifact(groupId, artifactId, version, Artifact.SCOPE_COMPILE, type);
302 ArtifactResolutionRequest request = new ArtifactResolutionRequest()
303 .setArtifact(artifact)
304 .setResolveTransitively(false)
305 .setLocalRepository(localRepository)
306 .setRemoteRepositories(remoteRepositories);
307 artifactResolver.resolve(request);
308 return artifact.getFile();
311 public static void main(String[] args) throws Exception {
312 UpdateCenter updateCenter = new UpdateCenter();
313 CmdLineParser p = new CmdLineParser(updateCenter);
314 p.parseArgument(args);