View Javadoc

1   /*
2    * Copyright 2007 scala-tools.org
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing,
11   * software distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions
14   * and limitations under the License.
15   */
16  package org.scala_tools.maven;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.List;
23  
24  import org.codehaus.plexus.util.FileUtils;
25  
26  /**
27   * Abstract parent of all Scala Mojo
28   */
29  public abstract class ScalaCompilerSupport extends ScalaMojoSupport {
30      /**
31       * Pause duration between to scan to detect changed file to compile.
32       * Used only if compileInLoop or testCompileInLoop is true.
33       */
34      protected long loopSleep = 2500;
35  
36  
37      abstract protected File getOutputDir() throws Exception;
38  
39      abstract protected List<String> getClasspathElements() throws Exception;
40      /**
41       * Retreives the list of *all* root source directories.  We need to pass all .java and .scala files into the scala compiler
42       */
43      abstract protected List<String> getSourceDirectories() throws Exception;
44      
45      @Override
46      protected void doExecute() throws Exception {
47          File outputDir = normalize(getOutputDir());
48          if (!outputDir.exists()) {
49              outputDir.mkdirs();
50          }
51          for(String directory : getSourceDirectories()) {
52          	getLog().error(directory);
53          }
54          int nbFiles = compile(getSourceDirectories(), outputDir, getClasspathElements(), false);
55          switch (nbFiles) {
56              case -1:
57                  getLog().warn("No source files found.");
58                  break;
59              case 0:
60                  getLog().info("Nothing to compile - all classes are up to date");;
61                  break;
62              default:
63                  break;
64          }
65      }
66  
67      protected File normalize(File f) {
68          try {
69              f = f.getCanonicalFile();
70          } catch (IOException exc) {
71              f = f.getAbsoluteFile();
72          }
73          return f;
74      }
75      
76      
77      protected int compile(File sourceDir, File outputDir, List<String> classpathElements, boolean compileInLoop) throws Exception, InterruptedException {
78      	//getLog().warn("Using older form of compile");
79      	return compile(Arrays.asList(sourceDir.getAbsolutePath()), outputDir, classpathElements, compileInLoop);
80      }
81      
82     protected int compile(List<String> sourceRootDirs, File outputDir, List<String> classpathElements, boolean compileInLoop) throws Exception, InterruptedException {
83         List<String> scalaSourceFiles = findSource(sourceRootDirs, "scala");
84         if (scalaSourceFiles.size() == 0) {
85             return -1;
86         }
87  
88         // filter uptodate
89         File lastCompileAtFile = new File(outputDir + ".timestamp");
90         long lastCompileAt = lastCompileAtFile.lastModified();
91         ArrayList<File> files = new ArrayList<File>(scalaSourceFiles.size());
92         for (String x : scalaSourceFiles) {
93             File f = new File(x);
94             if (f.lastModified() >= lastCompileAt) {
95                 files.add(f);
96             }
97         }
98         if (files.size() == 0) {
99             return 0;
100        }
101        //Add java files to the source, so we make sure we can have nested dependencies
102        //BUT only when not compiling in "loop" fashion and when we're not using an older version of scala
103        
104        if(!compileInLoop && isJavaSupportedByCompiler()) {
105     	   List<String> javaSourceFiles = findSource(sourceRootDirs,"java");
106     	   for(String javaSourceFile : javaSourceFiles) {
107     		   files.add(new File(javaSourceFile));
108     	   }
109        }
110        
111        if (!compileInLoop) {
112            getLog().info(String.format("Compiling %d source files to %s", files.size(), outputDir.getAbsolutePath()));
113        }
114        long now = System.currentTimeMillis();
115        JavaCommand jcmd = getScalaCommand();
116        jcmd.addArgs("-classpath", JavaCommand.toMultiPath(classpathElements));
117        jcmd.addArgs("-d", outputDir.getAbsolutePath());
118        //jcmd.addArgs("-sourcepath", sourceDir.getAbsolutePath());
119        for (File f : files) {
120            jcmd.addArgs(f.getAbsolutePath());
121            if (compileInLoop) {
122                getLog().info(String.format("%tR compiling %s", now, f.getName()));
123            }
124        }
125        jcmd.run(displayCmd, !compileInLoop);
126        if (lastCompileAtFile.exists()) {
127            lastCompileAtFile.setLastModified(now);
128        } else {
129            FileUtils.fileWrite(lastCompileAtFile.getAbsolutePath(), ".");
130        }
131        return files.size();
132    }
133    
134    /**
135     * Finds all source files in a set of directories with a given extension. 
136     */
137    private List<String> findSource(List<String> sourceRootDirs, String extension) {
138 	   List<String> sourceFiles = new ArrayList<String>();
139 	   //TODO - Since we're making files anyway, perhaps we should just test for existence here...
140 	   for(String rootSourceDir : normalizeSourceRoots(sourceRootDirs)) {
141 		   File dir = normalize(new File(rootSourceDir));	
142 		   String[] tmpFiles = JavaCommand.findFiles(dir, "**/*." + extension);
143 		   for(String tmpLocalFile : tmpFiles) {			   
144 			   File tmpAbsFile = normalize(new File(dir, tmpLocalFile));
145 			   sourceFiles.add(tmpAbsFile.getAbsolutePath());
146 		   }
147 	   }
148 	   return sourceFiles;
149    }
150    
151     
152     
153     /**
154      * This limits the source directories to only those that exist for real.
155      */
156     private List<String> normalizeSourceRoots( List<String> compileSourceRootsList )
157     {
158         List<String> newCompileSourceRootsList = new ArrayList<String>();
159         if ( compileSourceRootsList != null )
160         {
161             // copy as I may be modifying it
162             for ( String srcDir : compileSourceRootsList )
163             {
164             	File srcDirFile = normalize(new File(srcDir));
165                 if ( !newCompileSourceRootsList.contains( srcDirFile.getAbsolutePath() ) && srcDirFile.exists() )
166                 {
167                     newCompileSourceRootsList.add( srcDirFile.getAbsolutePath() );
168                 }
169             }
170         }
171         return newCompileSourceRootsList;
172     }
173 }