View Javadoc

1   /***
2    * Cecilia ADL Compiler
3    * Copyright (C) 2006-2008 STMicroelectronics
4    *
5    * This library is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10   * This library is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   * Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public
16   * License along with this library; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   *
19   * Contact: fractal@objectweb.org
20   *
21   * Author:Matthieu Leclercq
22   */
23  
24  package org.objectweb.fractal.cecilia.adl.compiler;
25  
26  import java.io.File;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.HashMap;
30  import java.util.LinkedHashSet;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.concurrent.ExecutionException;
34  import java.util.concurrent.ExecutorService;
35  import java.util.concurrent.Executors;
36  import java.util.concurrent.Future;
37  import java.util.logging.Level;
38  import java.util.logging.Logger;
39  
40  import org.objectweb.fractal.adl.ADLException;
41  import org.objectweb.fractal.adl.util.FractalADLLogManager;
42  import org.objectweb.fractal.cecilia.adl.file.FileProvider;
43  import org.objectweb.fractal.cecilia.adl.file.FutureFileCollectionProvider;
44  import org.objectweb.fractal.cecilia.adl.file.FutureFileProvider;
45  import org.objectweb.fractal.cecilia.adl.file.SourceFileWriter;
46  import org.objectweb.fractal.task.core.Executable;
47  import org.objectweb.fractal.task.core.primitive.annotations.ClientInterface;
48  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterface;
49  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterfaces;
50  import org.objectweb.fractal.task.core.primitive.annotations.TaskParameters;
51  
52  @TaskParameters("id")
53  @ServerInterfaces(@ServerInterface(name = "file-provider", signature = FileProvider.class, record = "role:linkedFile, id:%", parameters = "id"))
54  public abstract class AbstractLinkTask implements Executable, FileProvider {
55  
56    /** The name of the linked file. */
57    protected final String                                 outputName;
58    /** The compilation flags. */
59    protected List<String>                                       flags;
60    /** The output directory. */
61    protected final File                                   outputDir;
62    /** The number of concurrent compilation jobs. */
63    protected final int                                    nThreads;
64  
65    // Produced file
66    protected File                                         linkedFile;
67  
68    // The dep logger
69    protected static Logger                                depLogger                  = FractalADLLogManager
70                                                                                          .getLogger("dep");
71    // The io logger
72    protected static Logger                                ioLogger                   = FractalADLLogManager
73                                                                                          .getLogger("io");
74  
75    // ---------------------------------------------------------------------------
76    // Task client interfaces
77    // ---------------------------------------------------------------------------
78  
79    /** The client collection interface used to retrieve the files to linked. */
80    @ClientInterface(name = "source-file-provider", signature = FutureFileProvider.class, record = "role:compiledFile, id:%", parameters = "id")
81    public final Map<String, FutureFileProvider>           fileProviderItfs           = new HashMap<String, FutureFileProvider>();
82  
83    /** The client collection interface used to retrieve the files to linked. */
84    @ClientInterface(name = "source-file-collection-provider", signature = FutureFileCollectionProvider.class, record = "role:compiledFileCollection, id:%", parameters = "id")
85    public final Map<String, FutureFileCollectionProvider> fileCollectionProviderItfs = new HashMap<String, FutureFileCollectionProvider>();
86  
87    // ---------------------------------------------------------------------------
88    // Task constructor
89    // ---------------------------------------------------------------------------
90  
91    /**
92     * @param outputName the name of the linked file
93     * @param outputDir the directory into which the compiled file will be placed.
94     * @param flags compilation flags.
95     * @param nThreads the number of concurrent compilation jobs
96     */
97    public AbstractLinkTask(final String outputName, final File outputDir,
98        final List<String> flags, final int nThreads) {
99      this.outputName = outputName;
100     this.outputDir = outputDir;
101     this.flags = flags;
102     this.nThreads = nThreads;
103   }
104 
105   // ---------------------------------------------------------------------------
106   // Abstract methods
107   // ---------------------------------------------------------------------------
108 
109   /**
110    * Link method.
111    * 
112    * @param outputFile the linked file that is provided by this task.
113    * @param inputFiles the input files to be linked.
114    * @throws the linked file. Most of the time this is the same the
115    *             <code>outputFile</code> parameter but it is not necessary the
116    *             case. In particular, on Windows platform, a ".exe" suffix can
117    *             be added on the file name.
118    * @throws ADLException if an error occurs.
119    * @throws InterruptedException
120    */
121   protected abstract File link(File outputFile, Collection<File> inputFiles)
122       throws ADLException, InterruptedException;
123 
124   // ---------------------------------------------------------------------------
125   // Utility methods
126   // ---------------------------------------------------------------------------
127 
128   protected File getOutputFile() {
129     final File outFile = new File(outputName);
130     if (outFile.isAbsolute())
131       return outFile;
132     else
133       return new File(outputDir, outputName);
134   }
135 
136   // -------------------------------------------------------------------------
137   // Implementation of the Executable interface
138   // -------------------------------------------------------------------------
139 
140   public void execute() throws Exception {
141     ExecutorService executorService = null;
142     try {
143       executorService = Executors.newFixedThreadPool(nThreads);
144 
145       // use LinkedHashSet to preserve file order.
146       final Collection<Future<File>> futureFiles = new LinkedHashSet<Future<File>>();
147 
148       // get every files provided by every FileProvider
149       for (final FutureFileProvider fileProvider : fileProviderItfs.values()) {
150         futureFiles.add(fileProvider.getFile(executorService));
151       }
152 
153       // get every files provided by every FileCollectionProvider
154       for (final FutureFileCollectionProvider collectionProvider : fileCollectionProviderItfs
155           .values()) {
156         futureFiles.addAll(collectionProvider.getFiles(executorService));
157       }
158 
159       final Collection<File> inputFiles = new ArrayList<File>(futureFiles.size());
160       linkedFile = getOutputFile();
161       final long outputTimestamp = linkedFile.lastModified();
162       boolean relink = false;
163       for (final Future<File> futureFile : futureFiles) {
164         File inputFile;
165         try {
166           inputFile = futureFile.get();
167         } catch (final ExecutionException e) {
168           if (e.getCause() instanceof ADLException)
169             throw (ADLException) e.getCause();
170           else
171             throw e;
172         }
173         inputFiles.add(inputFile);
174         if (inputFile.lastModified() > outputTimestamp) {
175           if (depLogger.isLoggable(Level.FINE))
176             depLogger.fine("Input file '" + inputFile
177                 + " is more recent than file '" + linkedFile + "', recompile.");
178           relink = true;
179         }
180       }
181 
182       if (relink) {
183         SourceFileWriter.createOutputDir(linkedFile.getParentFile());
184         linkedFile = link(linkedFile, inputFiles);
185       } else if (depLogger.isLoggable(Level.FINE)) {
186         depLogger.fine("Output file '" + linkedFile
187             + "' is up to date, do not recompile.");
188       }
189     }
190     finally {
191       // Destroy the threads pools even if an exception was thrown.
192       executorService.shutdown();
193     }
194   }
195 
196   // -------------------------------------------------------------------------
197   // Implementation of the FileProvider interface
198   // -------------------------------------------------------------------------
199 
200   public File getFile() {
201     return linkedFile;
202   }
203 }