View Javadoc

1   /***
2    * Cecilia ADL Compiler
3    * Copyright (C) 2006-2007 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.IdentityHashMap;
29  import java.util.List;
30  import java.util.Map;
31  
32  import org.objectweb.fractal.adl.ContextLocal;
33  import org.objectweb.fractal.api.Component;
34  import org.objectweb.fractal.task.core.AbstractTaskFactoryUser;
35  import org.objectweb.fractal.task.core.TaskException;
36  
37  public abstract class AbstractCompilationTaskFactory
38      extends
39        AbstractTaskFactoryUser implements CompilationTaskFactory {
40  
41    private final ContextLocal<Map<Object, Component>> compileTaskCache = new ContextLocal<Map<Object, Component>>();
42    private final ContextLocal<Map<Object, Component>> linkTaskCache    = new ContextLocal<Map<Object, Component>>();
43    private final ContextLocal<Map<Object, Component>> archiveTaskCache = new ContextLocal<Map<Object, Component>>();
44  
45    // -------------------------------------------------------------------------
46    // Implementation of the CompilationTaskFactory interface
47    // -------------------------------------------------------------------------
48  
49    public Component newCompileTask(final Object id, List<String> flags,
50        final Map<Object, Object> context) throws TaskException {
51      final Map<Object, Component> cache = getCompileCache(context);
52      Component task = cache.get(id);
53      if (task == null) {
54        // append context flags.
55        if (flags == null) flags = new ArrayList<String>();
56        flags = tryAppendFlag(flags, "c-flags", context);
57  
58        // get compiler command from context
59        final String compilerCommand = getContextStringArg("compiler-command", context);
60  
61        // get output directory from context
62        final File outputDir = (File) context.get("objBuildDirectory");
63  
64        // create compilation task
65        task = createCompileTask(id, compilerCommand, flags, outputDir, context);
66  
67        // put task in cache
68        cache.put(id, task);
69      }
70      return task;
71    }
72  
73    public Component newLinkTask(final Object id, String linkedFileName,
74        List<String> flags, final Map<Object, Object> context) throws TaskException {
75      final Map<Object, Component> cache = getLinkTaskCache(context);
76      Component task = cache.get(id);
77      if (task == null) {
78        // append context flags.
79        if (flags == null) flags = new ArrayList<String>();
80        flags = tryAppendFlag(flags, "ld-flags", context);
81  
82        // get linker command from context
83        final String linkerCommand = getContextStringArg("linker-command", context);
84  
85        // get output directory from context
86        final File outputDir = (File) context.get("objBuildDirectory");
87  
88        // get the executable name is not specified as parameter
89        if (linkedFileName == null) {
90          linkedFileName = getContextStringArg("executable-name", context);
91        }
92  
93        // get the number of jobs from context
94        Integer nThreads = (Integer) context.get("jobs");
95        if (nThreads == null) nThreads = 1;
96  
97        // create compilation task
98        task = createLinkTask(id, linkerCommand, linkedFileName, flags,
99            outputDir, nThreads, context);
100 
101       // put task in cache
102       cache.put(id, task);
103     }
104     return task;
105   }
106 
107   public Component newArchiveTask(final Object id,
108       final String archiveFileName, List<String> flags,
109       final Map<Object, Object> context) throws TaskException {
110     final Map<Object, Component> cache = getArchiveTaskCache(context);
111     Component task = cache.get(id);
112     if (task == null) {
113       // append context flags.
114       if (flags == null) flags = new ArrayList<String>();
115       flags = tryAppendFlag(flags, "ar-flags", context);
116 
117       // get linker command from context
118       final String archiveCommand = getContextStringArg("archiver-command", context);
119 
120       // get output directory from context
121       final File outputDir = (File) context.get("objBuildDirectory");
122 
123       // create compilation task
124       task = createArchiveTask(id, archiveCommand, archiveFileName, flags,
125           outputDir, context);
126 
127       // put task in cache
128       cache.put(id, task);
129     }
130     return task;
131   }
132 
133   // ---------------------------------------------------------------------------
134   // Abstract methods
135   // ---------------------------------------------------------------------------
136 
137   protected abstract Component createCompileTask(final Object id,
138       String compileCommand, List<String> flags, File outputDir,
139       final Map<Object, Object> context) throws TaskException;
140 
141   protected abstract Component createLinkTask(final Object id,
142       String linkCommand, String linkedFileName, List<String> flags, File outputDir,
143       int nbJobs, final Map<Object, Object> context) throws TaskException;
144 
145   protected abstract Component createArchiveTask(final Object id,
146       String archiveCommand, String archiveFileName, List<String> flags,
147       File outputDir, final Map<Object, Object> context) throws TaskException;
148 
149   // ---------------------------------------------------------------------------
150   // Utility methods
151   // ---------------------------------------------------------------------------
152 
153   private Map<Object, Component> getCompileCache(final Object context) {
154     Map<Object, Component> cache = compileTaskCache.get(context);
155     if (cache == null) {
156       cache = new IdentityHashMap<Object, Component>();
157       compileTaskCache.set(context, cache);
158     }
159     return cache;
160   }
161 
162   private Map<Object, Component> getLinkTaskCache(final Object context) {
163     Map<Object, Component> cache = linkTaskCache.get(context);
164     if (cache == null) {
165       cache = new IdentityHashMap<Object, Component>();
166       compileTaskCache.set(context, cache);
167     }
168     return cache;
169   }
170 
171   private Map<Object, Component> getArchiveTaskCache(final Object context) {
172     Map<Object, Component> cache = archiveTaskCache.get(context);
173     if (cache == null) {
174       cache = new IdentityHashMap<Object, Component>();
175       compileTaskCache.set(context, cache);
176     }
177     return cache;
178   }
179 
180   protected List<String> getContextArg(final String name,
181       final Map<Object, Object> context) {
182     final List<String> s = tryGetContextArg(name, context);
183     if (s == null)
184       throw new IllegalArgumentException("Can't find contextual parameter \'"
185           + name + "\'.");
186     return s;
187   }
188 
189   protected String getContextStringArg(final String name,
190       final Map<Object, Object> context) {
191     final String s = tryGetContextStringArg(name, context);
192     if (s == null)
193       throw new IllegalArgumentException("Can't find contextual parameter \'"
194           + name + "\'.");
195     return s;
196   }
197 
198   protected List<String> tryGetContextArg(final String name,
199       final Map<Object, Object> context) {
200     final Object arg = context.get(name);
201     if ((arg != null) && !(arg instanceof List)) {
202       throw new IllegalArgumentException("Contextual parameter \'" + name
203           + "\' is not a List<String>.");
204     }
205     return (List<String>) arg;
206   }
207 
208   protected String tryGetContextStringArg(final String name,
209       final Map<Object, Object> context) {
210     final Object arg = context.get(name);
211     if ((arg != null) && !(arg instanceof String)) {
212       throw new IllegalArgumentException("Contextual parameter \'" + name
213           + "\' is not a String.");
214     }
215     return (String) arg;
216   }
217 
218   protected List<String> tryAppendFlag(final List<String> flags, final String contextArg,
219       final Map<Object, Object> context) {
220     final List<String> arg = tryGetContextArg(contextArg, context);
221     if (arg != null) {
222       //flags.addAll(arg);
223       for (String s : arg) {
224         flags.add(s);
225       }
226     }
227     return flags;
228   }
229 }