blob: af00c2cca02eb1b45cfc3a5debd95ee086996a27 [file] [log] [blame]
/*
* Copyright 20012 The Apache Software Foundation.
*
* 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.
*/
package org.apache.aries.versioning.mojo;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Map;
import org.apache.aries.util.manifest.BundleManifest;
import org.apache.aries.versioning.check.BundleCompatibility;
import org.apache.aries.versioning.check.BundleInfo;
import org.apache.aries.versioning.check.VersionChange;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
import org.osgi.framework.Version;
/**
* Check semantic version changes between an explicitly named old artifact and
* the project output artifact. Optionally write packageinfo files for wrong
* package versions.
*/
@Mojo(name = "version-check", defaultPhase = LifecyclePhase.VERIFY)
public class VersionCheckerMojo extends AbstractMojo {
/**
* name of old artifact in
* groupId:artifactId[:extension[:classifier]]:version notation
*/
@Parameter(property="aries.oldArtifact")
private String oldArtifact;
@Parameter(property="aries.skip.version.check", defaultValue = "false")
private boolean skip;
/**
* Location of the file (defaults to main project artifact).
*/
@Parameter
private File newFile;
/**
* whether to write packageinfo files into source tree
*/
@Parameter(property="writePackageInfos", defaultValue="false")
private boolean writePackageinfos = false;
/**
* source tree location
*/
@Parameter(defaultValue="${project.basedir}/src/main/java")
private File source;
@Parameter
private List<String> excludes;
@Component
private RepositorySystem repository;
@Component
protected MavenProject project;
@Component
private MavenSession session;
public void execute() throws MojoExecutionException {
if (skip) {
return;
}
if ("pom".equals(project.getPackaging())) {
return;
}
if (newFile == null) {
newFile = project.getArtifact().getFile();
}
if (oldArtifact != null) {
try {
BundleInfo newBundle = getBundleInfo(newFile);
if (newBundle == null || newBundle.getBundleManifest() == null) {
//not a bundle type, just return
getLog().info(newFile + " is not an OSGi bundle, skipping.");
return;
}
if (null == newBundle.getBundleManifest().getManifestVersion()
&& null == newBundle.getBundleManifest().getSymbolicName()
&& Version.emptyVersion.equals(newBundle.getBundleManifest().getVersion())) {
//not a bundle type, just return
getLog().info(newFile + " is not an OSGi bundle, skipping.");
return;
}
BundleInfo oldBundle = getBundleInfo(resolve(oldArtifact));
String bundleSymbolicName = newBundle.getBundleManifest().getSymbolicName();
URLClassLoader oldClassLoader = new URLClassLoader(new URL[] {oldBundle.getBundle().toURI()
.toURL()});
URLClassLoader newClassLoader = new URLClassLoader(new URL[] {newBundle.getBundle().toURI()
.toURL()});
BundleCompatibility bundleCompatibility = new BundleCompatibility(bundleSymbolicName,
newBundle, oldBundle,
oldClassLoader,
newClassLoader,
excludes);
bundleCompatibility.invoke();
String bundleElement = bundleCompatibility.getBundleElement();
String pkgElement = bundleCompatibility.getPkgElements().toString();
boolean failed = false;
if ((bundleElement != null) && (bundleElement.trim().length() > 0)) {
getLog().error(bundleElement + "\r\n");
failed = true;
}
if ((pkgElement != null) && (pkgElement.trim().length() > 0)) {
getLog().error(pkgElement);
failed = true;
}
if (writePackageinfos) {
writePackageInfos(bundleCompatibility);
}
if (failed) {
throw new RuntimeException("Semantic Versioning incorrect");
} else {
getLog().info("All package or bundle versions are semanticly versioned correctly.");
}
} catch (MalformedURLException e) {
throw new MojoExecutionException("Problem analyzing sources");
} catch (IOException e) {
throw new MojoExecutionException("Problem analyzing sources");
}
}
}
private void writePackageInfos(BundleCompatibility bundleCompatibility) {
Map<String, VersionChange> packages = bundleCompatibility.getPackageChanges();
for (Map.Entry<String, VersionChange> packageChange : packages.entrySet()) {
VersionChange versionChange = packageChange.getValue();
if (!versionChange.isCorrect()) {
String packageName = packageChange.getKey();
String[] bits = packageName.split("\\.");
File packageInfo = source;
for (String bit : bits) {
packageInfo = new File(packageInfo, bit);
}
packageInfo.mkdirs();
packageInfo = new File(packageInfo, "packageinfo");
try {
FileWriter w = new FileWriter(packageInfo);
try {
w.append("# generated by Apache Aries semantic versioning tool\n");
w.append("version " + versionChange.getRecommendedNewVersion().toString() + "\n");
w.flush();
} finally {
w.close();
}
} catch (IOException e) {
getLog().error("Could not write packageinfo for package " + packageName, e);
}
}
}
}
private File resolve(String artifactDescriptor) {
String[] s = artifactDescriptor.split(":");
String type = (s.length >= 4 ? s[3] : "jar");
Artifact artifact = repository.createArtifact(s[0], s[1], s[2], type);
ArtifactResolutionRequest request = new ArtifactResolutionRequest();
request.setArtifact(artifact);
request.setResolveRoot(true).setResolveTransitively(false);
request.setServers( session.getRequest().getServers() );
request.setMirrors( session.getRequest().getMirrors() );
request.setProxies( session.getRequest().getProxies() );
request.setLocalRepository(session.getLocalRepository());
request.setRemoteRepositories(session.getRequest().getRemoteRepositories());
repository.resolve(request);
return artifact.getFile();
}
private BundleInfo getBundleInfo(File f) {
BundleManifest bundleManifest = BundleManifest.fromBundle(f);
return new BundleInfo(bundleManifest, f);
}
}