In the next section, we'll see all the steps in details to write a new Maven-SCM provider.
Your project need to use some jars from the Maven-SCM framework. Add them to your POM.
<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> <artifactId>maven-scm-providers</artifactId> <groupId>org.apache.maven.scm</groupId> <version>LATEST VERSION OF MAVEN-SCM PROVIDERS MASTER POM</version> </parent> <artifactId>maven-scm-provider-YOUR_PROVIDER_NAME</artifactId> <version>1.0-SNAPSHOT</version> <name>My Maven-SCM Provider</name> <build> <plugins> <plugin> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-component-metadata</artifactId> <version>1.7.1</version> <executions> <execution> <goals> <goal>generate-metadata</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
The plexus-component-metadata maven plugin will generate the Plexus meta-data file used by the Maven-SCM manager.
This class will contain all SCM information about your SCM connection (user, password, host, port, path...).
package org.apache.maven.scm.provider.myprovider.repository; import org.apache.maven.scm.provider.ScmProviderRepository; public class MyScmProviderRepository extends ScmProviderRepository { }
Before you add more information to this class, you can look at the ScmProviderRepository sub-classes, if they are already implemented.
This class is the central point of the provider. The Maven-SCM framework will know only this class in the provider, so this class must validate the scm url, populate the ScmProviderRepository and provide all commands supported by your provider. We start with a basic class, then we'll add commands to it when we implement them.
Before you start to write your SCM provider, you must define the SCM URLs you want to support.
package org.apache.maven.scm.provider.myprovider; import org.apache.maven.scm.provider.myprovider.repository.MyScmProviderRepository; import org.apache.maven.scm.provider.AbstractScmProvider; import org.apache.maven.scm.provider.ScmProviderRepository; import org.apache.maven.scm.repository.ScmRepositoryException; /** * @plexus.component role="org.apache.maven.scm.provider.ScmProvider" role-hint="provider_name" */ public class MyScmProvider extends AbstractScmProvider { public String getScmType() { return "provider_name"; } /** * This method parse the scm URL and return a SCM provider repository. * At this point, the scmSpecificUrl is the part after scm:provider_name: in your SCM URL. */ public ScmProviderRepository makeProviderScmRepository( String scmSpecificUrl, char delimiter ) throws ScmRepositoryException { MyScmProviderRepository providerRepository = new MyScmProviderRepository(); //Parse scmSpecificUrl and populate there your provider repository return providerRepository; } }
The plexus.component javadoc tag will be used by the plexus maven plugin, declared in the POM, to generate plexus meta-data. Generally, we use the string just after scm: in the scm URL as the provider_name.
When you write a new SCM command, you must extend base classes for the Maven-SCM framework. We have one base command for each command supported by Maven-SCM and each command have an execute method that return an SCM result.
package org.apache.maven.scm.provider.myprovider.command.checkout; import org.apache.maven.scm.command.checkout.AbstractCheckOutCommand; public class MyCheckoutCommand extends AbstractCheckOutCommand { protected abstract CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repository, ScmFileSet fileSet, String tag ) throws ScmException { CheckOutScmResult result = new CheckOutScmResult(); //Add the code there to run the command //If you need to run a native commandline like cvs/svn/cleartool..., look at other providers how to launch it and parse the output return result; } }
Now that your command is implemented, you need to add it in your SCM provider (MyScmProvider). Open the provider class and override the method that relates to your command.
public class MyScmProvider extends AbstractScmProvider { ... protected CheckOutScmResult checkout( ScmRepository repository, ScmFileSet fileSet, CommandParameters params ) throws ScmException { MyCheckoutCommand command = new MyCheckoutCommand(); command.setLogger( getLogger() ); return (CheckOutScmResult) command.execute( repository.getProviderRepository(), fileSet, params ); } }
To be sure your provider works as expected, you must implement some tests. You can implement two levels of tests: