You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by pg...@apache.org on 2009/07/09 00:33:24 UTC

svn commit: r792339 - in /maven/ant-tasks/trunk/src/main/java/org/apache/maven/artifact/ant: DependenciesTask.java util/ util/AntBuildWriter.java util/AntTaskModified.java util/AntUtil.java

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