Index: /home/morten/workspace/HEAD/eclipse/project.properties =================================================================== --- /home/morten/workspace/HEAD/eclipse/project.properties (revision 169622) +++ /home/morten/workspace/HEAD/eclipse/project.properties (working copy) @@ -17,3 +17,5 @@ # ------------------------------------------------------------------- # P R O J E C T P R O P E R T I E S # ------------------------------------------------------------------- +# Needs http://cvs.apache.org/repository/ for snapshots of new scm jars +maven.repo.remote = http://www.ibiblio.org/maven, http://cvs.apache.org/repository/ Index: /home/morten/workspace/HEAD/eclipse/project.xml =================================================================== --- /home/morten/workspace/HEAD/eclipse/project.xml (revision 169622) +++ /home/morten/workspace/HEAD/eclipse/project.xml (working copy) @@ -102,4 +102,46 @@ -3 + + + ant + ant + 1.5.3-1 + + + commons-jelly + commons-jelly-tags-interaction + 1.0 + + + plexus + plexus-container-default + 1.0-alpha-1 + + + plexus + plexus-utils + 1.0-alpha-1 + + + classworlds + classworlds + 1.1-alpha-1 + + + maven + maven-scm-api + 1.0-alpha-1-SNAPSHOT + + + maven + maven-scm-provider-cvs + 1.0-alpha-1-SNAPSHOT + + + maven + maven-scm-provider-svn + 1.0-alpha-1-SNAPSHOT + + Index: /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/ProjectSetHandler.java =================================================================== --- /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/ProjectSetHandler.java (revision 0) +++ /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/ProjectSetHandler.java (revision 0) @@ -0,0 +1,117 @@ +package org.apache.maven.eclipse.projectset; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * XML handler used when parsing projectset file. + * + *
+ * + * @author Morten Kristiansen + */ +public class ProjectSetHandler extends DefaultHandler { + + private List myResult = new ArrayList(); + private String username = null; + private String cvsprovider = null; + private String svnprovider = null; + private String provider = null; + + /** + * Creates new instance of this class. + * + * @param username Username used for adding username to CVS urls. + * @param cvsprovider From projectset file to determine CVS data. + * @param svnprovider From projectset file to determine SVN data. + */ + public ProjectSetHandler( String username, String cvsprovider, String svnprovider ) { + this.username = username; + this.cvsprovider = cvsprovider; + this.svnprovider = svnprovider; + } + + /** + * @param namespaceURI - + * @param sName - + * @param qName - + * @param attrs - + * + * @throws SAXException - + */ + public void startElement( String namespaceURI, String sName, String qName, Attributes attrs ) + throws SAXException { + + if( "provider".equals( qName ) ) { + + provider = attrs.getValue( "id" ); + + } else if( "project".equals( qName ) ) { + + StringTokenizer tokens = new StringTokenizer( attrs.getValue( "reference" ), "," ); + if( cvsprovider.equals( provider ) ) { + + doCVS( tokens ); + + } else if( svnprovider.equals( provider ) ) { + + doSVN( tokens ); + + } else { + + throw new SAXException( "Found unsupported scm provider " + provider ); + + } + } + } + + private void doCVS( StringTokenizer tokens ) { + + SCMData data = new SCMData(); + tokens.nextToken(); // Skip first token (version nr) + data.url = "scm:cvs:" + getCVSUrlWithUsername( tokens.nextToken() ); + tokens.nextToken(); // Skip third token (path to module?) + data.module = tokens.nextToken(); + data.url = data.url + ":" + data.module; + + // If fifth token, it's a tag + if( tokens.hasMoreTokens() ) { + data.tag = tokens.nextToken(); + } + + myResult.add( data ); + + } + + private void doSVN( StringTokenizer tokens ) { + + SCMData data = new SCMData(); + tokens.nextToken(); // Skip first token (version nr) + data.url = "scm:svn:" + tokens.nextToken(); + data.module = tokens.nextToken(); + myResult.add( data ); + + } + + private String getCVSUrlWithUsername( String url ) { + StringTokenizer tokens = new StringTokenizer( url, ":" ); + StringBuffer result = new StringBuffer(); + result.append( tokens.nextToken() + ":" + username + "@" + tokens.nextToken() + ":" + tokens.nextToken() ); + return result.toString(); + } + + /** + * Returns parsed elements. + * + * @return List of ProjectSetData objects. + */ + public List getResult() { + return myResult; + } + +} \ No newline at end of file Index: /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/ProjectSetTask.java =================================================================== --- /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/ProjectSetTask.java (revision 0) +++ /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/ProjectSetTask.java (revision 0) @@ -0,0 +1,127 @@ +package org.apache.maven.eclipse.projectset; + +import java.io.File; +import java.util.Iterator; +import java.util.List; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +/** + * Ant task performing parsing of projectset file and checkout. + * + *
+ * + * @author Morten Kristiansen + */ +public class ProjectSetTask extends Task { + + private String projectset = null; + private String dest = null; + private String username = null; + private String password = null; + private String cvsprovider = null; + private String svnprovider = null; + private String tagBase = null; + + /** + * Tasks' execute method. + * + * @throws BuildException If execute fails. + */ + public void execute() throws BuildException { + + log( "Parsing projectset file: " + projectset, Project.MSG_INFO ); + + List myModules = null; + + try { + + ProjectSetHandler handler = new ProjectSetHandler( username, cvsprovider, svnprovider ); + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser saxParser = factory.newSAXParser(); + saxParser.parse( new File( projectset ), handler ); + myModules = handler.getResult(); + + } catch( Throwable t ) { + throw new BuildException( "Could not parse projectset file: " + t.getMessage() ); + } + + log( "Checking out to " + dest, Project.MSG_INFO ); + CheckoutBean scm = new CheckoutBean( dest, username, password, tagBase ); + for( Iterator iter = myModules.iterator(); iter.hasNext(); ) { + + SCMData data = (SCMData) iter.next(); + log( "Checking out " + data.url + " as " + data.module, Project.MSG_INFO ); + try { + scm.checkout( data ); + } catch( Exception e ) { + throw new BuildException( "Failed to checkout: " + e.getMessage() ); + } + + } + + log( myModules.size() + " modules handled", Project.MSG_VERBOSE ); + } + + public String getCvsprovider() { + return cvsprovider; + } + + public void setCvsprovider( String cvsprovider ) { + this.cvsprovider = cvsprovider; + } + + public String getDest() { + return dest; + } + + public void setDest( String dest ) { + this.dest = dest; + } + + public String getPassword() { + return password; + } + + public void setPassword( String password ) { + this.password = password; + } + + public String getProjectset() { + return projectset; + } + + public void setProjectset( String projectset ) { + this.projectset = projectset; + } + + public String getSvnprovider() { + return svnprovider; + } + + public void setSvnprovider( String svnprovider ) { + this.svnprovider = svnprovider; + } + + public String getTagBase() { + return tagBase; + } + + public void setTagBase( String tagBase ) { + this.tagBase = tagBase; + } + + public String getUsername() { + return username; + } + + public void setUsername( String username ) { + this.username = username; + } + +} \ No newline at end of file Index: /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/CheckoutBean.java =================================================================== --- /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/CheckoutBean.java (revision 0) +++ /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/CheckoutBean.java (revision 0) @@ -0,0 +1,130 @@ +package org.apache.maven.eclipse.projectset; + +import java.io.File; + +import org.apache.maven.scm.ScmFileSet; +import org.apache.maven.scm.ScmResult; +import org.apache.maven.scm.command.checkout.CheckOutScmResult; +import org.apache.maven.scm.manager.NoSuchScmProviderException; +import org.apache.maven.scm.manager.ScmManager; +import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository; +import org.apache.maven.scm.repository.ScmRepository; +import org.apache.maven.scm.repository.ScmRepositoryException; +import org.codehaus.plexus.embed.Embedder; +import org.codehaus.plexus.util.FileUtils; + +/** + * Wrapper for the checkout through org.apache.maven.scm.manager.ScmManager. + * + *
+ * + * @author Morten Kristiansen + */ +public class CheckoutBean { + + private String dest = null; + private String username = null; + private String password = null; + private String tagBase = null; + + /** + * Creates new instance of this class. + * + * @param dest The checkout root destination. + * @param username SCM username. + * @param password Only needed for SVN checkouts. For CVS, .cvspass file is used. + * @param tagBase Only needed for SVN checkouts if checking out branches/tags. + */ + public CheckoutBean( String dest, String username, String password, String tagBase ) { + this.dest = dest; + this.username = username; + this.password = password; + this.tagBase = tagBase; + } + + /** + * Checkout SCM data. + * + * @param data Data containing url, module and tag(optional). + * + * @throws Exception If errors occur. + */ + public void checkout( SCMData data ) throws Exception { + + ScmManager scmManager = lookupScmManager(); + + ScmRepository repository = getScmRepository( scmManager, data.url ); + + File checkoutDirectory = new File( dest, data.module ); + if( checkoutDirectory.exists() ) { + // TODO: sanity check that it is not . or .. or lower + FileUtils.deleteDirectory( checkoutDirectory ); + } + checkoutDirectory.mkdirs(); + + CheckOutScmResult result = scmManager.checkOut( repository, + new ScmFileSet( checkoutDirectory ), data.tag ); + + checkResult( result ); + + if( repository.getProvider().equals( "svn" ) ) { + File doubleSub = new File( checkoutDirectory, data.module ); + FileUtils.copyDirectoryStructure( doubleSub, checkoutDirectory ); + FileUtils.deleteDirectory( doubleSub ); + } + } + + private ScmManager lookupScmManager() throws Exception { + Embedder embedder = getEmbedder(); + ScmManager scmManager = (ScmManager) embedder.lookup( ScmManager.ROLE ); + return scmManager; + } + + private Embedder getEmbedder() throws Exception { + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); + + // TODO: allow this to be passed in as a parameter so Maven 1.1 can have one embedder only + Embedder embedder = new Embedder(); + embedder.start(); + + Thread.currentThread().setContextClassLoader( oldClassLoader ); + + return embedder; + } + + private ScmRepository getScmRepository( ScmManager scmManager, String url ) throws ScmRepositoryException, + NoSuchScmProviderException { + ScmRepository repository = scmManager.makeScmRepository( url ); + + if( repository.getProvider().equals( "svn" ) ) { + SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) repository + .getProviderRepository(); + + if( username != null && username.length() > 0 ) { + svnRepo.setUser( username ); + } + if( password != null && password.length() > 0 ) { + svnRepo.setPassword( password ); + } + if( tagBase != null && tagBase.length() > 0 ) { + svnRepo.setTagBase( tagBase ); + } + } + return repository; + } + + + + private void checkResult( ScmResult result ) throws Exception { + if( !result.isSuccess() ) { + // TODO: improve error handling + System.err.println( "Provider message:" ); + System.err.println( result.getProviderMessage() ); + System.err.println( "Command output:" ); + System.err.println( result.getCommandOutput() ); + throw new Exception( "Error!" ); + } + } + +} Index: /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/SCMData.java =================================================================== --- /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/SCMData.java (revision 0) +++ /home/morten/workspace/HEAD/eclipse/src/main/org/apache/maven/eclipse/projectset/SCMData.java (revision 0) @@ -0,0 +1,16 @@ +package org.apache.maven.eclipse.projectset; + +/** + * DTO holding scm data from one instance in projectset file. + * + *
+ * + * @author Morten Kristiansen + */ +public class SCMData { + + String url = null; + String module = null; + String tag = null; + +} \ No newline at end of file Index: /home/morten/workspace/HEAD/eclipse/plugin.properties =================================================================== --- /home/morten/workspace/HEAD/eclipse/plugin.properties (revision 169622) +++ /home/morten/workspace/HEAD/eclipse/plugin.properties (working copy) @@ -27,3 +27,11 @@ maven.gen.src=${maven.build.dir}/generated-sources maven.eclipse.src.extension = zip maven.eclipse.resources.addtoclasspath=false + +maven.eclipse.projectset.file=${basedir}/projectset.psf +maven.eclipse.projectset.dest=${basedir}/checkout +maven.eclipse.projectset.username=anoncvs +maven.eclipse.projectset.password= +maven.eclipse.projectset.cvsprovider=org.eclipse.team.cvs.core.cvsnature +maven.eclipse.projectset.svnprovider=org.tigris.subversion.subclipse.core.svnnature +maven.eclipse.projectset.tagBase= Index: /home/morten/workspace/HEAD/eclipse/plugin.jelly =================================================================== --- /home/morten/workspace/HEAD/eclipse/plugin.jelly (revision 169622) +++ /home/morten/workspace/HEAD/eclipse/plugin.jelly (working copy) @@ -24,7 +24,8 @@ xmlns:test="test" xmlns:util="jelly:util" xmlns:define="jelly:define" - xmlns:maven="jelly:maven"> + xmlns:maven="jelly:maven" + xmlns:assert="assert"> @@ -268,5 +269,46 @@ Cleaned up eclipse generated files - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +