1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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.HashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.concurrent.Callable;
34 import java.util.concurrent.ExecutionException;
35 import java.util.concurrent.ExecutorService;
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.api.type.TypeFactory;
43 import org.objectweb.fractal.cecilia.adl.TypeNameProvider;
44 import org.objectweb.fractal.cecilia.adl.file.FutureFileCollectionProvider;
45 import org.objectweb.fractal.cecilia.adl.file.FutureFileProvider;
46 import org.objectweb.fractal.cecilia.adl.file.SourceFileWriter;
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 = FutureFileProvider.class, record = "role:archiveFile, id:%", parameters = "id"))
54 public abstract class AbstractArchiveTask implements FutureFileProvider {
55
56
57
58
59
60
61 public static final String FILE_NAME_SUFFIX = ".a";
62
63
64 protected final String outputName;
65
66 protected List<String> flags;
67
68 protected final File outputDir;
69
70
71 protected Future<File> archiveFile;
72
73
74 protected static Logger depLogger = FractalADLLogManager
75 .getLogger("dep");
76
77 protected static Logger ioLogger = FractalADLLogManager
78 .getLogger("io");
79
80
81
82
83
84
85 @ClientInterface(name = "type-name-provider", contingency = TypeFactory.OPTIONAL, record = "role:typeNameProvider, id:%", parameters = "id")
86 public TypeNameProvider typeNameProviderItf;
87
88
89 @ClientInterface(name = "source-file-provider", signature = FutureFileProvider.class, record = "role:compiledFile, id:%", parameters = "id")
90 public final Map<String, FutureFileProvider> fileProviderItfs = new HashMap<String, FutureFileProvider>();
91
92
93 @ClientInterface(name = "source-file-collection-provider", signature = FutureFileCollectionProvider.class, record = "role:compiledFileCollection, id:%", parameters = "id")
94 public final Map<String, FutureFileCollectionProvider> fileCollectionProviderItfs = new HashMap<String, FutureFileCollectionProvider>();
95
96
97
98
99
100
101
102
103
104
105 public AbstractArchiveTask(final String outputName, final File outputDir,
106 final List<String> flags) {
107 this.outputName = outputName;
108 this.outputDir = outputDir;
109 this.flags = flags;
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 protected abstract File archivate(File outputFile, Collection<File> inputFiles)
128 throws ADLException, InterruptedException;
129
130
131
132
133
134 protected File getOutputFile() {
135 final String name;
136 if (outputName != null)
137 name = outputName;
138 else if (typeNameProviderItf != null)
139 name = typeNameProviderItf.getCTypeName() + FILE_NAME_SUFFIX;
140 else
141 throw new IllegalStateException(
142 "the output file name must either be specifyed in the contructor parameters or the typeNameProviderItf interface must be bound");
143
144 return new File(outputDir, name);
145 }
146
147
148
149
150
151 public synchronized Future<File> getFile(final ExecutorService executorService) {
152 if (archiveFile == null) {
153 final Collection<Future<File>> futureFiles = new HashSet<Future<File>>();
154
155
156 for (final FutureFileProvider fileProvider : fileProviderItfs.values()) {
157 futureFiles.add(fileProvider.getFile(executorService));
158 }
159
160
161 for (final FutureFileCollectionProvider collectionProvider : fileCollectionProviderItfs
162 .values()) {
163 futureFiles.addAll(collectionProvider.getFiles(executorService));
164 }
165
166 archiveFile = executorService.submit(new Callable<File>() {
167
168 public File call() throws Exception {
169 final Collection<File> inputFiles = new ArrayList<File>(futureFiles
170 .size());
171 File outputFile = getOutputFile();
172 final long outputTimestamp = outputFile.lastModified();
173 boolean relink = false;
174 if (outputTimestamp == 0) relink = true;
175
176 for (final Future<File> futureFile : futureFiles) {
177 File inputFile;
178 try {
179 inputFile = futureFile.get();
180 } catch (final ExecutionException e) {
181 if (e.getCause() instanceof ADLException)
182 throw (ADLException) e.getCause();
183 else
184 throw e;
185 }
186 inputFiles.add(inputFile);
187 if (!relink && inputFile.lastModified() > outputTimestamp) {
188 if (depLogger.isLoggable(Level.FINE))
189 depLogger.fine("Input file '" + inputFile
190 + " is more recent than file '" + outputFile
191 + "', recompile.");
192 relink = true;
193 }
194 }
195 if (!relink && depLogger.isLoggable(Level.FINE))
196 depLogger.fine("Output file '" + outputFile
197 + "' is up to date, do not recompile.");
198
199 if (relink) {
200 SourceFileWriter.createOutputDir(outputFile.getParentFile());
201 outputFile = archivate(outputFile, inputFiles);
202 }
203 return outputFile;
204 }
205 });
206 }
207 return archiveFile;
208 }
209 }