Author: pgier Date: Wed Jul 8 22:33:24 2009 New Revision: 792339 URL: http://svn.apache.org/viewvc?rev=792339&view=rev Log: [MANTTASKS-156] First attempt at caching the list of dependencies in an ant build file.
Added: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/ maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntBuildWriter.java (with props) maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntTaskModified.java (with props) maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntUtil.java (with props) Modified: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/DependenciesTask.java Modified: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/DependenciesTask.java URL: http://svn.apache.org/viewvc/maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/DependenciesTask.java?rev=792339&r1=792338&r2=792339&view=diff ============================================================================== --- maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/DependenciesTask.java (original) +++ maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/DependenciesTask.java Wed Jul 8 22:33:24 2009 @@ -20,6 +20,9 @@ */ import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.ant.util.AntBuildWriter; +import org.apache.maven.artifact.ant.util.AntTaskModified; +import org.apache.maven.artifact.ant.util.AntUtil; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.repository.ArtifactRepository; @@ -45,7 +48,9 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; +import java.util.Enumeration; import java.util.HashSet; +import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -62,6 +67,9 @@ public class DependenciesTask extends AbstractArtifactWithRepositoryTask { + + public static final String DEFAULT_ANT_BUILD_FILE = "target/build-dependencies.xml"; + private List dependencies = new ArrayList(); private String pathId; @@ -83,6 +91,10 @@ private boolean verbose; private boolean addArtifactFileSetRefs; + + private String cacheBuildFile; + + private boolean cacheDependencyRefs; protected void doExecute() { @@ -93,6 +105,20 @@ throw new BuildException( "You cannot specify both useScope and scopes in the dependencies task." ); } + // Try to load dependency refs from Ant + if ( isCacheDependencyRefs() ) + { + if ( getCacheBuildFile() == null ) + { + setCacheBuildFile( DEFAULT_ANT_BUILD_FILE ); + } + if ( checkCachedDependencies() ) + { + log( "Dependency refs loaded from file: " + getCacheBuildFile(), Project.MSG_VERBOSE ); + return; + } + } + ArtifactRepository localRepo = createLocalArtifactRepository(); log( "Using local repository: " + localRepo.getBasedir(), Project.MSG_VERBOSE ); @@ -236,8 +262,103 @@ String versionsValue = StringUtils.join( versions.iterator(), File.pathSeparator ); getProject().setNewProperty( versionsId, versionsValue ); } + + // Write the dependency references out to a file. + if ( getCacheBuildFile() != null || this.isCacheDependencyRefs() ) + { + if ( getCacheBuildFile() == null || getCacheBuildFile().equals( "default" ) ) + { + setCacheBuildFile( DEFAULT_ANT_BUILD_FILE ); + } + log( "Building ant file: " + getCacheBuildFile()); + AntBuildWriter antBuildWriter = new AntBuildWriter(); + File antBuildFile = new File( getProject().getBaseDir(), getCacheBuildFile() ); + try + { + antBuildWriter.openAntBuild( antBuildFile, "maven-dependencies", "init-dependencies" ); + antBuildWriter.openTarget( "init-dependencies" ); + + Iterator i = result.getArtifacts().iterator(); + while ( i.hasNext() ) + { + Artifact artifact = (Artifact) i.next(); + String conflictId = artifact.getDependencyConflictId(); + antBuildWriter.writeProperty( conflictId, artifact.getFile().getAbsolutePath() ); + if ( this.isAddArtifactFileSetRefs() ) + { + FileSet singleArtifactFileSet = (FileSet)getProject().getReference( conflictId ); + antBuildWriter.writeFileSet( singleArtifactFileSet, conflictId ); + } + } + + if ( pathId != null ) + { + Path thePath = (Path)getProject().getReference( pathId ); + antBuildWriter.writePath( thePath, pathId ); + } + + if ( filesetId != null ) + { + antBuildWriter.writeFileSet( dependencyFileSet, filesetId ); + } + if ( sourcesFilesetId != null ) + { + antBuildWriter.writeFileSet( sourcesFileSet, sourcesFilesetId ); + } + if ( javadocFilesetId != null ) + { + antBuildWriter.writeFileSet( sourcesFileSet, javadocFilesetId ); + } + + antBuildWriter.closeTarget(); + antBuildWriter.closeAntBuild(); + } + catch ( IOException e ) + { + throw new BuildException ( "Unable to write ant build: " + e); + } + } + } + + private boolean checkCachedDependencies() + { + File cacheBuildFile = new File( getProject().getBaseDir(), getCacheBuildFile() ); + if ( ! cacheBuildFile.exists() ) + { + return false; + } + File antBuildFile = new File( getProject().getProperty( "ant.file" ) ); + if ( antBuildFile.lastModified() > cacheBuildFile.lastModified() ) + { + return false; + } + + return loadDependenciesFromAntBuildFile(); } + /** + * Load the dependency references from the generated ant build file. + * + * @return True if the dependency refs were successfully loaded. + */ + private boolean loadDependenciesFromAntBuildFile() + { + Project currentAntProject = getProject(); + + // Run the ant build with the dependency refs + AntTaskModified dependenciesAntBuild = new AntTaskModified(); + dependenciesAntBuild.setAntfile( getCacheBuildFile() ); + dependenciesAntBuild.setProject( currentAntProject ); + dependenciesAntBuild.execute(); + + // Copy the properties and refs to the current project + Project cachedDepsProject = dependenciesAntBuild.getSavedNewProject(); + AntUtil.copyProperties( cachedDepsProject, currentAntProject ); + AntUtil.copyReferences( cachedDepsProject, currentAntProject ); + + return true; + } + private FileSet createFileSet() { FileSet fileSet = new FileSet(); @@ -435,4 +556,24 @@ { this.addArtifactFileSetRefs = addArtifactFileSetRefs; } + + public String getCacheBuildFile() + { + return cacheBuildFile; + } + + public void setCacheBuildFile( String cacheBuildFile ) + { + this.cacheBuildFile = cacheBuildFile; + } + + public boolean isCacheDependencyRefs() + { + return cacheDependencyRefs; + } + + public void setCacheDependencyRefs( boolean cacheDependencyRefs ) + { + this.cacheDependencyRefs = cacheDependencyRefs; + } } Added: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntBuildWriter.java URL: http://svn.apache.org/viewvc/maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntBuildWriter.java?rev=792339&view=auto ============================================================================== --- maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntBuildWriter.java (added) +++ maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntBuildWriter.java Wed Jul 8 22:33:24 2009 @@ -0,0 +1,177 @@ +package org.apache.maven.artifact.ant.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.types.FileList; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Path; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; +import org.codehaus.plexus.util.xml.XmlWriterUtil; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * Utility class for writing an Ant build file. + */ +public class AntBuildWriter +{ + public static final String DEFAULT_FILE_ENCODING = "UTF-8"; + + /** + * The default line indenter + */ + protected static final int DEFAULT_INDENTATION_SIZE = XmlWriterUtil.DEFAULT_INDENTATION_SIZE; + + private XMLWriter writer; + + private OutputStreamWriter outputStreamWriter; + + /** + * Open an Ant build file for writing. Opens the file and prints the opening project tag. + * + * @param buildFile + * @param name + * @param defaultTarget + * @throws IOException + */ + public void openAntBuild( File dependenciesBuildFile, String name, String defaultTarget ) + throws IOException + { + String encoding = DEFAULT_FILE_ENCODING; + + if ( ! dependenciesBuildFile.getParentFile().exists() ) + { + dependenciesBuildFile.getParentFile().mkdirs(); + } + outputStreamWriter = new OutputStreamWriter( new FileOutputStream( dependenciesBuildFile ), encoding ); + + writer = + new PrettyPrintXMLWriter( outputStreamWriter, StringUtils.repeat( " ", DEFAULT_INDENTATION_SIZE ), + encoding, null ); + writer.startElement( "project" ); + writer.addAttribute( "name", name ); + writer.addAttribute( "default", defaultTarget ); + + XmlWriterUtil.writeLineBreak( writer ); + } + + /** + * Close the ant build writer + * + * @throws IOException + */ + public void closeAntBuild() + throws IOException + { + writer.endElement(); + + XmlWriterUtil.writeLineBreak( writer ); + + IOUtil.close( outputStreamWriter ); + + } + + public void openTarget( String targetName ) + throws IOException + { + writer.startElement( "target" ); + writer.addAttribute( "name", targetName ); + } + + public void closeTarget() + throws IOException + { + writer.endElement(); + } + + public void writeFileSet( FileSet fileSet, String id ) + { + writer.startElement( "fileset" ); + + if ( id != null ) + { + writer.addAttribute( "id", id ); + } + + File dir = fileSet.getDir( fileSet.getProject() ); + writer.addAttribute( "dir", dir.getAbsolutePath() ); + + DirectoryScanner scanner = fileSet.getDirectoryScanner( fileSet.getProject() ); + scanner.scan(); + String[] files = scanner.getIncludedFiles(); + + for ( int i = 0; i < files.length; ++i ) + { + writer.startElement( "include" ); + writer.addAttribute( "name", files[i] ); + writer.endElement(); + } + + writer.endElement(); + } + + public void writeProperty( String name, String value ) + { + writer.startElement( "property" ); + + writer.addAttribute( "name", name ); + writer.addAttribute( "value", value ); + + writer.endElement(); + } + + public void writeFileList( FileList fileList, String id ) + { + writer.startElement( "filelist" ); + writer.addAttribute( "id", id ); + File dir = fileList.getDir( fileList.getProject() ); + writer.addAttribute( "dir", dir.getAbsolutePath() ); + + String[] files = fileList.getFiles( fileList.getProject() ); + for ( int i = 0; i < files.length; ++i ) + { + writer.startElement( "file" ); + writer.addAttribute( "name", files[i] ); + writer.endElement(); + } + writer.endElement(); + } + + public void writePath( Path path, String pathId ) + { + writer.startElement( "path" ); + writer.addAttribute( "id", pathId ); + String[] paths = path.list(); + for ( int i = 0; i < paths.length; ++i ) + { + writer.startElement( "pathelement" ); + writer.addAttribute( "path", paths[i] ); + writer.endElement(); + } + writer.endElement(); + } +} Propchange: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntBuildWriter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntBuildWriter.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Added: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntTaskModified.java URL: http://svn.apache.org/viewvc/maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntTaskModified.java?rev=792339&view=auto ============================================================================== --- maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntTaskModified.java (added) +++ maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntTaskModified.java Wed Jul 8 22:33:24 2009 @@ -0,0 +1,81 @@ +package org.apache.maven.artifact.ant.util; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.lang.reflect.Field; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Ant; + +/** + * A modified version of the Ant task that allows access to the + * new sub project. + * + * @author pgier + * + */ +public class AntTaskModified extends Ant +{ + + /** + * The Ant tasks sets newProject to null at the end of execute(), so + * we need to save this object to a different place. + */ + private Project savedNewProject; + + public void init() + { + super.init(); + savedNewProject = saveNewProject(); + } + + /** + * This is a hack to get access to the private variable "newProject" in the Ant task. This should not be used. + * Note: This may not work with later versions of Ant + * + * @return + */ + private Project saveNewProject( ) + { + try + { + Field newProjectField = Ant.class.getDeclaredField( "newProject" ); + newProjectField.setAccessible( true ); + Project newProjectObj = (Project) newProjectField.get( this ); + return newProjectObj; + } + catch ( Exception e ) + { + throw new BuildException( "Unable to load cache: " + e ); + } + } + + /** + * Get the new Ant project created by this task. + * + * @return + */ + public Project getSavedNewProject() + { + return savedNewProject; + } + +} Propchange: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntTaskModified.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntTaskModified.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Added: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntUtil.java URL: http://svn.apache.org/viewvc/maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntUtil.java?rev=792339&view=auto ============================================================================== --- maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntUtil.java (added) +++ maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntUtil.java Wed Jul 8 22:33:24 2009 @@ -0,0 +1,106 @@ +package org.apache.maven.artifact.ant.util; + +import java.util.Enumeration; +import java.util.Hashtable; + +import org.apache.tools.ant.Project; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * Utility stuff for dealing with Ant. + */ +public class AntUtil +{ + + /** + * Copies all properties from the given project to the new project - omitting those that have already been set in the + * new project as well as properties named basedir or ant.file. + * + * @param fromProject copy from + * @param toProject copy to + */ + public static void copyProperties( Project fromProject, Project toProject ) + { + copyProperties( fromProject.getProperties(), toProject ); + } + + /** + * Copies all properties from the given table to the new project - omitting those that have already been set in the + * new project as well as properties named basedir or ant.file. + * + * @param props properties <code>Hashtable</code> to copy to the new project. + * @param project the project where the properties are added + */ + public static void copyProperties( Hashtable props, Project project ) + { + Enumeration e = props.keys(); + while ( e.hasMoreElements() ) + { + String key = e.nextElement().toString(); + if ( "basedir".equals( key ) || "ant.file".equals( key ) ) + { + // basedir and ant.file get special treatment in execute() + continue; + } + + String value = props.get( key ).toString(); + // don't re-set user properties, avoid the warning message + if ( project.getProperty( key ) == null ) + { + // no user property + project.setNewProperty( key, value ); + } + } + } + + /** + * Copy references from one project to another. + * + * @param fromProject + * @param toProject + */ + public static void copyReferences( Project fromProject, Project toProject ) + { + copyReferences( fromProject.getReferences(), toProject ); + } + + /** + * Copy references from a hashtable to a project. Will not + * overwrite existing references. + * + * @param refs + * @param project + */ + public static void copyReferences( Hashtable refs, Project project ) + { + Enumeration e = refs.keys(); + while ( e.hasMoreElements() ) + { + String key = e.nextElement().toString(); + // don't overwrite existing references + if ( project.getReference( key ) == null ) + { + project.addReference( key, refs.get( key ) ); + } + } + } + +} Propchange: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant/util/AntUtil.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision