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;
25  
26  import java.io.File;
27  import java.io.PrintStream;
28  import java.net.URL;
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.Collection;
32  import java.util.Collections;
33  import java.util.HashMap;
34  import java.util.Iterator;
35  import java.util.LinkedHashMap;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.logging.Level;
39  import java.util.logging.Logger;
40  
41  import org.objectweb.fractal.adl.ADLException;
42  import org.objectweb.fractal.adl.Factory;
43  import org.objectweb.fractal.adl.FactoryFactory;
44  import org.objectweb.fractal.adl.JavaFactory;
45  import org.objectweb.fractal.adl.StaticJavaGenerator;
46  import org.objectweb.fractal.adl.util.FractalADLLogManager;
47  import org.objectweb.fractal.api.Component;
48  import org.objectweb.fractal.api.NoSuchInterfaceException;
49  import org.objectweb.fractal.api.control.IllegalLifeCycleException;
50  import org.objectweb.fractal.cecilia.adl.directives.DirectiveHelper;
51  import org.objectweb.fractal.cecilia.adl.plugin.AbstractPluginManager;
52  import org.objectweb.fractal.cecilia.targetDescriptor.TargetDescriptorException;
53  import org.objectweb.fractal.cecilia.targetDescriptor.TargetDescriptorLoader;
54  import org.objectweb.fractal.cecilia.targetDescriptor.TargetDescriptorLoaderJavaFactory;
55  import org.objectweb.fractal.cecilia.targetDescriptor.ast.ADLMapping;
56  import org.objectweb.fractal.cecilia.targetDescriptor.ast.CFlag;
57  import org.objectweb.fractal.cecilia.targetDescriptor.ast.LdFlag;
58  import org.objectweb.fractal.cecilia.targetDescriptor.ast.Target;
59  import org.objectweb.fractal.util.Fractal;
60  
61  /**
62   * A class to compile a component. Usage: Launcher <definition> where
63   * <definition> is the name of the component to be compiled.
64   */
65  public class Launcher extends AbstractLauncher {
66  
67    protected static final String   PROGRAM_NAME_PROPERTY_NAME     = "cecilia.launcher.name";
68  
69    /**
70     * The default value of the {@link #PLUGIN_FACTORY_BACKEND_PROPERTY_NAME}
71     * property.
72     */
73    public static final String      DEFAULT_PLUGIN_FACTORY_BACKEND = "Java";
74  
75    /** The name of the default ADL of the compiler. */
76    public static final String      CECILIA_BASIC_COMPILER_ADL     = "org.objectweb.fractal.cecilia.adl.CeciliaBasicFactory";
77  
78    public static final String      C_FLAGS                        = "c-flags";
79    public static final String      COMPILER_COMMAND               = "compiler-command";
80    public static final String      LD_FLAGS                       = "ld-flags";
81    public static final String      LINKER_COMMAND                 = "linker-command";
82    public static final String      LINKER_SCRIPT                  = "linker-script";
83    public static final String      ARCHIVER_COMMAND               = "archiver-command";
84    public static final String      EXEC_NAME                      = "executable-name";
85  
86    protected final CmdArgument     compilerADLOpt                 = new CmdArgument(
87                                                                       null,
88                                                                       "compiler-adl",
89                                                                       "Specify the name of the ADL of the compiler itself",
90                                                                       "<adl name>",
91                                                                       CECILIA_BASIC_COMPILER_ADL,
92                                                                       false);
93  
94    protected final CmdArgument     targetDescOpt                  = new CmdArgument(
95                                                                       "t",
96                                                                       "target-descriptor",
97                                                                       "Specify the target descriptor",
98                                                                       "<name>");
99  
100   protected final CmdArgument     compilerCmdOpt                 = new CmdArgument(
101                                                                      null,
102                                                                      "compiler-command",
103                                                                      "the command of the C compiler",
104                                                                      "<path>",
105                                                                      "gcc",
106                                                                      false);
107 
108   protected final CmdAppendOption cFlagsOpt                      = new CmdAppendOption(
109                                                                      "c",
110                                                                      "c-flags",
111                                                                      "the c-flags compiler directives",
112                                                                      "<flags>");
113 
114   protected final CmdPathOption   includePathOpt                 = new CmdPathOption(
115                                                                      "I",
116                                                                      "inc-path",
117                                                                      "the list of path to be added in compiler include paths",
118                                                                      "<path list>");
119 
120   protected final CmdArgument     linkerCmdOpt                   = new CmdArgument(
121                                                                      null,
122                                                                      "linker-command",
123                                                                      "the command of the linker",
124                                                                      "<path>",
125                                                                      "gcc",
126                                                                      false);
127 
128   protected final CmdAppendOption ldFlagsOpt                     = new CmdAppendOption(
129                                                                      "l",
130                                                                      "ld-flags",
131                                                                      "the ld-flags compiler directives",
132                                                                      "<flags>");
133 
134   protected final CmdPathOption   ldPathOpt                      = new CmdPathOption(
135                                                                      "L",
136                                                                      "ld-path",
137                                                                      "the list of path to be added to linker library search path",
138                                                                      "<path list>");
139 
140   protected final CmdArgument     archiverCmdOpt                 = new CmdArgument(
141                                                                      null,
142                                                                      "archiver-command",
143                                                                      "the command of the archiver tool",
144                                                                      "<path>",
145                                                                      "ar",
146                                                                      false);
147 
148   protected final CmdArgument     linkerScriptOpt                = new CmdArgument(
149                                                                      "T",
150                                                                      "linker-script",
151                                                                      "linker script to use (given path is resolved in source path)",
152                                                                      "<path>");
153 
154   protected final CmdArgument     executableNameCmdOpt           = new CmdArgument(
155                                                                      null,
156                                                                      "executable-name",
157                                                                      "the name of the target executable file (can be used with only one ADL to be compiled.)",
158                                                                      "<name>");
159 
160   protected final CmdArgument     concurrentJobCmdOpt            = new CmdArgument(
161                                                                      "j",
162                                                                      "jobs",
163                                                                      "The number of concurrent compilation jobs",
164                                                                      "<number>",
165                                                                      "1", false);
166 
167   protected final CmdFlag         printStackTraceOpt             = new CmdFlag(
168                                                                      "e", null,
169                                                                      "Print error stack traces");
170 
171   protected final CmdFlag         checkADLModeOpt                = new CmdFlag(
172                                                                      null,
173                                                                      "check-adl",
174                                                                      "Only check input ADL(s), do not compile");
175 
176   protected Map<String, String>   adlToExecName;
177   protected Map<Object, Object>   compilerContext                = new HashMap<Object, Object>();
178   protected Factory               compiler;
179 
180   protected Target                targetDescriptor;
181 
182   protected boolean               printStackTrace                = false;
183 
184   protected boolean               checkADLMode                   = false;
185 
186   protected static Logger         logger                         = FractalADLLogManager
187                                                                      .getLogger("launcher");
188 
189   protected File                  buildDir;
190 
191   protected File                  adlBuildDir;
192   protected File                  idlBuildDir;
193   protected File                  objBuildDir;
194 
195   /**
196    * Creates a new Compiler launcher context.
197    * 
198    * @param outDir the output directory
199    * @param sources the source path.
200    * @throws InvalidCommandLineException
201    * @throws CompilerInstantiationException
202    */
203   public Launcher(final String outDir, final String sources)
204       throws InvalidCommandLineException, CompilerInstantiationException {
205     init("-o=" + outDir, "-src-path=" + sources);
206   }
207 
208   /**
209    * Creates a new Compiler launcher context.
210    * 
211    * @param options the options
212    * @throws InvalidCommandLineException
213    * @throws CompilerInstantiationException
214    */
215   public Launcher(final Map<String, String> options)
216       throws InvalidCommandLineException, CompilerInstantiationException {
217     init(toArgs(options));
218   }
219 
220   protected static String[] toArgs(final Map<String, String> options) {
221     final String[] params = new String[options.size()];
222     int i = 0;
223     for (final Map.Entry<String, String> option : options.entrySet()) {
224       if (option.getValue() == null) {
225         params[i] = option.getKey();
226       } else {
227         params[i] = option.getKey() + '=' + option.getValue();
228       }
229       i++;
230     }
231     return params;
232   }
233 
234   /**
235    * Creates a new Compiler launcher context and run compilation.
236    * 
237    * @param args the command line arguments.
238    * @throws Exception
239    */
240   public Launcher(final String... args) throws Exception {
241     try {
242       init(args);
243       compile();
244     } catch (final InvalidCommandLineException e) {
245       handleException(e);
246     } catch (final CompilerInstantiationException e) {
247       handleException(e);
248     } catch (final ADLException e) {
249       handleException(e);
250     }
251   }
252 
253   protected void init(final String... args) throws InvalidCommandLineException,
254       CompilerInstantiationException {
255     if (logger.isLoggable(Level.CONFIG)) {
256       for (final String arg : args) {
257         logger.config("[arg] " + arg);
258       }
259     }
260 
261     addOptions();
262 
263     // parse arguments to a CommandLine.
264     final CommandLine cmdLine = CommandLine.parseArgs(options, false, args);
265 
266     // If help is asked, print it and exit.
267     if (helpOpt.isPresent(cmdLine)) {
268       printHelp(System.out);
269       System.exit(0);
270     }
271 
272     // get list of ADL
273     final List<String> adlList = cmdLine.getArguments();
274     adlToExecName = parserADLList(adlList, cmdLine);
275 
276     // instantiate compiler
277     compiler = createCompiler(compilerContext, cmdLine);
278 
279     // add source class loader in context
280     final ClassLoader sourceClassLoader = getSourceClassLoader(cmdLine);
281     compilerContext.put("classloader", sourceClassLoader);
282 
283     // load target descriptor (if any)
284     final String targetDesc = targetDescOpt.getValue(cmdLine);
285     if (targetDesc != null) {
286       final TargetDescriptorLoader loader = createTargetDescriptorLoader(compilerContext);
287       try {
288         targetDescriptor = loader.load(targetDesc, compilerContext);
289       } catch (final TargetDescriptorException e) {
290         logger.log(Level.FINE, "Error while loading target descriptor", e);
291         throw new InvalidCommandLineException(
292             "Unable to load target descriptor: " + e.getMessage(), 1);
293       }
294     }
295     if (targetDescriptor != null && targetDescriptor.getLinkerScript() != null) {
296       final URL linkerScriptURL = sourceClassLoader
297           .getResource(targetDescriptor.getLinkerScript().getPath());
298       if (linkerScriptURL == null) {
299         throw new InvalidCommandLineException("Invalid linker script: '"
300             + targetDescriptor.getLinkerScript().getPath()
301             + "'. Cannot find file in the source path", 1);
302       }
303       targetDescriptor.getLinkerScript().setPath(linkerScriptURL.getPath());
304     }
305 
306     printStackTrace = printStackTraceOpt.isPresent(cmdLine);
307     checkADLMode = checkADLModeOpt.isPresent(cmdLine);
308 
309     // add build directories to context
310     String optValue = outDirOpt.getValue(cmdLine);
311     if (nullOrEmpty(optValue)) {
312       throw new InvalidCommandLineException("Invalid output directory ''", 1);
313     }
314     buildDir = new File(optValue);
315     checkDir(buildDir);
316     if (!buildDir.exists()) {
317       throw new InvalidCommandLineException("Invalid output directory '"
318           + optValue + "' does not exist.", 1);
319     }
320     adlBuildDir = new File(buildDir, "adl");
321     idlBuildDir = new File(buildDir, "idl");
322     objBuildDir = new File(buildDir, "obj");
323     checkDir(adlBuildDir);
324     checkDir(idlBuildDir);
325     checkDir(objBuildDir);
326 
327     // build c-flags
328     final List<String> cFlagsList = new ArrayList<String>();
329     final List<String> incPaths = new ArrayList<String>();
330     if (srcPathOpt.getPathValue(cmdLine) != null) {
331       incPaths.addAll(srcPathOpt.getPathValue(cmdLine));
332     }
333     if (includePathOpt.getValue(cmdLine) != null) {
334       incPaths.addAll(includePathOpt.getPathValue(cmdLine));
335     }
336     incPaths.add(adlBuildDir.getAbsolutePath());
337     incPaths.add(idlBuildDir.getAbsolutePath());
338 
339     for (final String inc : incPaths) {
340       final File incDir = new File(inc);
341       cFlagsList.add("-I");
342       cFlagsList.add(incDir.getAbsolutePath());
343     }
344 
345     optValue = cFlagsOpt.getValue(cmdLine);
346     if (!nullOrEmpty(optValue)) {
347       cFlagsList.addAll(DirectiveHelper.splitOptionString(optValue));
348     }
349     compilerContext.put(C_FLAGS, cFlagsList);
350 
351     // build ld-flags
352     final List<String> ldPaths = ldPathOpt.getPathValue(cmdLine);
353     final List<String> ldFlagsList = new ArrayList<String>();
354     if (ldPaths != null) {
355       for (final String ld : ldPaths) {
356         final File ldDir = new File(ld);
357         ldFlagsList.add("-L");
358         ldFlagsList.add(ldDir.getAbsolutePath());
359       }
360     }
361     optValue = ldFlagsOpt.getValue(cmdLine);
362     if (!nullOrEmpty(optValue)) {
363       ldFlagsList.addAll(DirectiveHelper.splitOptionString(optValue));
364     }
365     compilerContext.put(LD_FLAGS, ldFlagsList);
366 
367     // add compiler arguments to context
368 
369     if (compilerCmdOpt.isPresent(cmdLine)) {
370       optValue = compilerCmdOpt.getValue(cmdLine);
371       if (optValue.length() == 0)
372         throw new InvalidCommandLineException("Invalid compiler ''", 1);
373       compilerContext.put(COMPILER_COMMAND, optValue);
374     }
375 
376     if (linkerCmdOpt.isPresent(cmdLine)) {
377       optValue = linkerCmdOpt.getValue(cmdLine);
378       if (optValue.length() == 0)
379         throw new InvalidCommandLineException("Invalid linker ''", 1);
380       compilerContext.put(LINKER_COMMAND, optValue);
381     }
382 
383     if (archiverCmdOpt.isPresent(cmdLine)) {
384       optValue = archiverCmdOpt.getValue(cmdLine);
385       if (optValue.length() == 0)
386         throw new InvalidCommandLineException("Invalid archiver ''", 1);
387       compilerContext.put(ARCHIVER_COMMAND, optValue);
388     }
389 
390     Integer jobs = null;
391     try {
392       jobs = Integer.decode(concurrentJobCmdOpt.getValue(cmdLine));
393     } catch (final NumberFormatException e) {
394       throw new InvalidCommandLineException("Invalid jobs value '"
395           + concurrentJobCmdOpt.getValue(cmdLine) + "' is not a valid number",
396           1);
397     }
398     compilerContext.put("jobs", jobs);
399 
400     // add linker script to the context
401     final String linkerScript = linkerScriptOpt.getValue(cmdLine);
402     if (linkerScript != null) {
403       final URL linkerScriptURL = sourceClassLoader.getResource(linkerScript);
404       if (linkerScriptURL == null) {
405         throw new InvalidCommandLineException("Invalid linker script: '"
406             + linkerScript + "'. Cannot find file in the source path", 1);
407       }
408 
409       compilerContext.put(LINKER_SCRIPT, linkerScriptURL.getPath());
410     }
411   }
412 
413   protected void addOptions() {
414     options.addOptions(compilerADLOpt, targetDescOpt, compilerCmdOpt,
415         cFlagsOpt, includePathOpt, linkerCmdOpt, ldFlagsOpt, ldPathOpt,
416         archiverCmdOpt, linkerScriptOpt, executableNameCmdOpt,
417         concurrentJobCmdOpt, printStackTraceOpt, checkADLModeOpt);
418   }
419 
420   protected void initBuildDirs(final Map<Object, Object> context) {
421     adlBuildDir.mkdirs();
422     context.put("adlBuildDirectory", adlBuildDir);
423 
424     idlBuildDir.mkdirs();
425     context.put("idlBuildDirectory", idlBuildDir);
426 
427     objBuildDir.mkdirs();
428     context.put("objBuildDirectory", objBuildDir);
429   }
430 
431   protected Map<String, String> parserADLList(final List<String> adlList,
432       final CommandLine cmdLine) throws InvalidCommandLineException {
433     final Map<String, String> adlToExecName = new LinkedHashMap<String, String>();
434 
435     final String defaultExecName = executableNameCmdOpt.getValue(cmdLine);
436     boolean defaultExeNameUsed = false;
437     // parse adlNames
438     for (final String adlName : adlList) {
439       final int i = adlName.indexOf(':');
440       if (i == -1) {
441         if (defaultExeNameUsed) {
442           if (defaultExecName == null)
443             throw new InvalidCommandLineException(
444                 "Executable name must be specified for adl \"" + adlName
445                     + "\" using -" + executableNameCmdOpt.getLongName()
446                     + "=NAME or the ADL:NAME syntax.", 1);
447           else
448             throw new InvalidCommandLineException(
449                 "Executable name must be specified for adl \"" + adlName
450                     + "\" using the ADL:NAME syntax.", 1);
451         }
452         adlToExecName.put(adlName, defaultExecName);
453         defaultExeNameUsed = true;
454       } else {
455         final String adl = adlName.substring(0, i);
456         final String exec = adlName.substring(i + 1);
457         adlToExecName.put(adl, exec);
458       }
459     }
460 
461     return adlToExecName;
462   }
463 
464   protected String processContext(final Target targetDesc,
465       final String inputADL, final Map<Object, Object> context) {
466     processCFlags(targetDesc, context);
467     processLdFlags(targetDesc, context);
468     processCompiler(targetDesc, context);
469     processLinker(targetDesc, context);
470     processLinkerScript(targetDesc, context);
471     processArchiver(targetDesc, context);
472     return processADLMapping(targetDesc, inputADL, context);
473   }
474 
475   protected void processCFlags(final Target target,
476       final Map<Object, Object> context) {
477     if (target != null && target.getCFlags().length > 0) {
478       final CFlag[] flags = target.getCFlags();
479 
480       List<String> targetFlags = new ArrayList<String>();
481       for (int i = 0; i < flags.length; i++) {
482         targetFlags.addAll(DirectiveHelper.splitOptionString(
483             flags[i].getValue()));
484       }
485 
486       if (logger.isLoggable(Level.FINE))
487         logger.log(Level.FINE, "Adding target c-flags: " + targetFlags);
488 
489       List<String> contextFlags = (List<String>) context.get(C_FLAGS);
490       if (contextFlags == null) {
491         contextFlags = new ArrayList<String>();
492       }
493       contextFlags.addAll(targetFlags);
494       context.put(C_FLAGS, contextFlags);
495     }
496   }
497 
498   protected void processLdFlags(final Target target,
499       final Map<Object, Object> context) {
500     if (target != null && target.getLdFlags().length > 0) {
501       final LdFlag[] flags = target.getLdFlags();
502 
503       List<String> targetFlags = new ArrayList<String>();
504       for (int i = 0; i < flags.length; i++) {
505         targetFlags.addAll(DirectiveHelper.splitOptionString(
506             flags[i].getValue()));
507       }
508 
509       if (logger.isLoggable(Level.FINE))
510         logger.log(Level.FINE, "Adding target ld-flags: " + targetFlags);
511 
512       List<String> contextFlags = (List<String>) context.get(LD_FLAGS);
513       if (contextFlags == null) {
514         contextFlags = new ArrayList<String>();
515       }
516       contextFlags.addAll(targetFlags);
517       context.put(LD_FLAGS, contextFlags);
518     }
519   }
520 
521   protected void processCompiler(final Target target,
522       final Map<Object, Object> context) {
523     final String opt = (String) context.get(COMPILER_COMMAND);
524     if (opt == null) {
525       if (target != null && target.getCompiler() != null) {
526         if (logger.isLoggable(Level.FINE)) {
527           logger.log(Level.FINE, "Using target compiler : "
528               + target.getCompiler().getPath());
529         }
530         context.put(COMPILER_COMMAND, target.getCompiler().getPath());
531       } else {
532         context.put(COMPILER_COMMAND, compilerCmdOpt.getDefaultValue());
533       }
534     }
535   }
536 
537   protected void processLinker(final Target target,
538       final Map<Object, Object> context) {
539     final String opt = (String) context.get(LINKER_COMMAND);
540     if (opt == null) {
541       if (target != null && target.getLinker() != null) {
542         if (logger.isLoggable(Level.FINE)) {
543           logger.log(Level.FINE, "Using target linker : "
544               + target.getLinker().getPath());
545         }
546         context.put(LINKER_COMMAND, target.getLinker().getPath());
547       } else {
548         context.put(LINKER_COMMAND, linkerCmdOpt.getDefaultValue());
549       }
550     }
551   }
552 
553   protected void processLinkerScript(final Target target,
554       final Map<Object, Object> context) {
555     if (target != null) {
556       final String opt = (String) context.get(LINKER_SCRIPT);
557       if (opt == null && target.getLinkerScript() != null) {
558         if (logger.isLoggable(Level.FINE)) {
559           logger.log(Level.FINE, "Using target linker script : "
560               + target.getLinkerScript().getPath());
561         }
562         context.put(LINKER_SCRIPT, target.getLinkerScript().getPath());
563       }
564     }
565   }
566 
567   protected void processArchiver(final Target target,
568       final Map<Object, Object> context) {
569     final String opt = (String) context.get(ARCHIVER_COMMAND);
570     if (opt == null) {
571       if (target != null && target.getArchiver() != null) {
572         if (logger.isLoggable(Level.FINE)) {
573           logger.log(Level.FINE, "Using target archiver : "
574               + target.getArchiver().getPath());
575         }
576         context.put(ARCHIVER_COMMAND, target.getArchiver().getPath());
577       } else {
578         context.put(ARCHIVER_COMMAND, archiverCmdOpt.getDefaultValue());
579       }
580     }
581   }
582 
583   protected String processADLMapping(final Target target,
584       final String inputADL, final Map<Object, Object> context) {
585     if (target != null) {
586       final ADLMapping mapping = target.getAdlMapping();
587       if (mapping == null) return inputADL;
588 
589       if (mapping.getOutputName() != null) {
590         final String outputName = ((String) context.get(EXEC_NAME)).replace(
591             "${inputADL}", inputADL);
592         if (logger.isLoggable(Level.FINE)) {
593           logger.log(Level.FINE, "Compiling ADL : " + outputName);
594         }
595         context.put(EXEC_NAME, outputName);
596       }
597 
598       return mapping.getMapping().replace("${inputADL}", inputADL);
599     } else {
600       return inputADL;
601     }
602   }
603 
604   /**
605    * Create the o.o.f.a.Factory class that will be used to read the application
606    * definition. Subclasses of the Launcher may extend this.
607    */
608   protected Factory createCompiler(final Map<Object, Object> compilerContext,
609       final CommandLine cmdLine) throws CompilerInstantiationException {
610     return createCompiler(compilerADLOpt.getValue(cmdLine), compilerContext);
611   }
612 
613   protected Factory createCompiler(final String compilerAdl,
614       final Map<Object, Object> compilerContext)
615       throws CompilerInstantiationException {
616     final Object pluginFactoryBackend = compilerContext
617         .get(AbstractPluginManager.PLUGIN_FACTORY_BACKEND);
618     if (pluginFactoryBackend == null
619         || DEFAULT_PLUGIN_FACTORY_BACKEND.equals(pluginFactoryBackend)) {
620       /* instantiate the bootstrap factory with the default backend */
621       try {
622         final Class<?> factoryFactoryClass = getClass().getClassLoader()
623             .loadClass(compilerAdl + StaticJavaGenerator.CLASSNAME_SUFFIX);
624         final JavaFactory factoryFactory = (JavaFactory) factoryFactoryClass
625             .newInstance();
626         final Map<?, ?> compilerComponent = (Map<?, ?>) factoryFactory
627             .newComponent();
628         logger
629             .fine("[Launcher] Cecilia compiler instantiated using statically generated factory.");
630         return (Factory) compilerComponent.get("factory");
631       } catch (final Exception e) {
632         // ignore and try to instantiate the compiler using a FractalADL
633         // factory.
634         if (logger.isLoggable(Level.FINE)) {
635           logger
636               .fine("[Launcher] Unable to instantiate cecilia compiler using statically generated factory ("
637                   + e.getClass().getName() + ":" + e.getMessage() + ").");
638         }
639       }
640 
641       try {
642         final Factory factory = FactoryFactory.getFactory();
643         /* try to instantiate the CeciliaADL BasicFactory */
644         final Map<?, ?> compilerComponent = (Map<?, ?>) factory.newComponent(
645             compilerAdl, compilerContext);
646         logger
647             .fine("[Launcher] Cecilia compiler instantiated using FractalADL factory.");
648         return (Factory) compilerComponent.get("factory");
649       } catch (final ADLException e) {
650         throw new CompilerInstantiationException(
651             "Unable to instantiate Cecilia compiler", e, 101);
652       }
653 
654     } else {
655       /* instantiate the bootstrap factory with the Fractal backend */
656       Component compilerComponent = null;
657       try {
658         final Factory factory = FactoryFactory
659             .getFactory(FactoryFactory.FRACTAL_BACKEND);
660 
661         /* try to instantiate the CeciliaADL BasicFactory */
662         compilerComponent = (Component) factory.newComponent(compilerAdl,
663             compilerContext);
664         /* start compiler */
665         Fractal.getLifeCycleController(compilerComponent).startFc();
666 
667         final Factory result = (Factory) compilerComponent
668             .getFcInterface("factory");
669         return result;
670       } catch (final ADLException e) {
671         throw new CompilerInstantiationException(
672             "Unable to instantiate Cecilia compiler", e, 101);
673       } catch (final NoSuchInterfaceException e) {
674         throw new CompilerInstantiationException(
675             "Unable to instantiate Cecilia compiler", e, 101);
676       } catch (final IllegalLifeCycleException e) {
677         throw new CompilerInstantiationException(
678             "Unable to instantiate Cecilia compiler", e, 101);
679       }
680     }
681   }
682 
683   protected TargetDescriptorLoader createTargetDescriptorLoader(
684       final Map<Object, Object> compilerContext)
685       throws CompilerInstantiationException {
686     try {
687       final JavaFactory factory = new TargetDescriptorLoaderJavaFactory();
688       final Map<?, ?> component = (Map<?, ?>) factory.newComponent();
689       return (TargetDescriptorLoader) component.get("loader");
690     } catch (final Exception e) {
691       throw new CompilerInstantiationException(
692           "Unable to instantiate target descriptor loader", e, 101);
693     }
694   }
695 
696   protected static boolean nullOrEmpty(final String s) {
697     return s == null || s.length() == 0;
698   }
699 
700   /**
701    * Compiles the given ADL.
702    * 
703    * @param adlName the name of the the name of the architecture (ADL) to
704    *          compile.
705    * @return the list of objects that are the results of the compilation.
706    * @throws ADLException if the compilation fails.
707    */
708   public List<Object> compile(final String adlName) throws ADLException {
709     final List<Object> result = new ArrayList<Object>();
710     compile(adlName, null, result);
711     return result;
712   }
713 
714   /**
715    * Compiles the given ADL.
716    * 
717    * @param adlName the name of the architecture (ADL) to compile.
718    * @param execName the name of the executable file to be created.
719    * @return the list of objects that are the results of the compilation.
720    * @throws ADLException if the compilation fails.
721    */
722   public List<Object> compile(final String adlName, final String execName)
723       throws ADLException {
724     final List<Object> result = new ArrayList<Object>();
725     compile(adlName, execName, result);
726     return result;
727   }
728 
729   /**
730    * Compiles the list of adl files that are received from the command-line.
731    * 
732    * @return the list of objects that are the results of the compilation of the
733    *         list of adl files received from the command-line.
734    * @throws ADLException if the compilation fails.
735    * @throws InvalidCommandLineException
736    */
737   public List<Object> compile() throws ADLException,
738       InvalidCommandLineException {
739     // Check if at least 1 adlName is specified
740     if (adlToExecName.size() == 0) {
741       throw new InvalidCommandLineException("no definition name is specified.",
742           1);
743     }
744 
745     final List<Object> result = new ArrayList<Object>();
746     for (final Map.Entry<String, String> e : adlToExecName.entrySet()) {
747       compile(e.getKey(), e.getValue(), result);
748     }
749     return result;
750   }
751 
752   private void compile(String adlName, final String execName,
753       final List<Object> result) throws ADLException {
754     final HashMap<Object, Object> contextMap = new HashMap<Object, Object>(
755         compilerContext);
756     if (execName != null)
757       contextMap.put(EXEC_NAME, execName);
758     else
759       contextMap.put(EXEC_NAME, adlName.replace('.', '_'));
760 
761     initBuildDirs(contextMap);
762 
763     adlName = processContext(targetDescriptor, adlName, contextMap);
764 
765     if (checkADLMode) {
766       contextMap.put("check-adl", Boolean.TRUE);
767     }
768 
769     final Object compilationResult = this.compiler.newComponent(adlName,
770         contextMap);
771 
772     if (compilationResult instanceof File) {
773       result.add(compilationResult);
774     } else if (compilationResult instanceof Collection) {
775       for (final Object elem : (Collection<?>) compilationResult) {
776         result.add(elem);
777       }
778     }
779   }
780 
781   @Override
782   protected void printUsage(final PrintStream ps) {
783     final String prgName = System.getProperty(PROGRAM_NAME_PROPERTY_NAME,
784         getClass().getName());
785     ps.println("Usage: " + prgName + " [OPTIONS] (<definition>[:<execname>])+");
786     ps.println("  where <definition> is the name of the component to"
787         + " be compiled, ");
788     ps
789         .println("  and <execname> is the name of the output file to be created.");
790   }
791 
792   protected void handleException(final InvalidCommandLineException e)
793       throws Exception {
794     logger.log(Level.FINER, "Caught an InvalidCommandLineException", e);
795     if (printStackTrace) {
796       e.printStackTrace();
797     } else {
798       System.err.println(e.getMessage());
799       printHelp(System.err);
800       System.exit(e.exitValue);
801     }
802   }
803 
804   protected void handleException(final CompilerInstantiationException e)
805       throws Exception {
806     logger.log(Level.FINER, "Caught a CompilerInstantiationException", e);
807     e.printStackTrace();
808     System.exit(e.exitValue);
809   }
810 
811   protected void handleException(final ADLException e) throws Exception {
812     logger.log(Level.FINER, "Caught an ADL Exception", e);
813     if (printStackTrace) {
814       e.printStackTrace();
815     } else {
816       final StringBuffer sb = new StringBuffer();
817       sb.append(e.getMessage()).append('\n');
818       Throwable cause = e.getCause();
819       while (cause != null) {
820         sb.append("caused by : ");
821         sb.append(cause.getMessage()).append('\n');
822         cause = cause.getCause();
823       }
824       System.err.println(sb);
825     }
826     System.exit(1);
827   }
828 
829   /**
830    * Entry point.
831    * 
832    * @param args
833    */
834   public static void main(final String... args) {
835     try {
836       new Launcher(args);
837     } catch (final Exception e) {
838       // never append
839       e.printStackTrace();
840     }
841   }
842 
843   /**
844    * Exception thrown when the CeciliaADL compiler can't be instantiated.
845    */
846   public static class CompilerInstantiationException extends Exception {
847 
848     final int exitValue;
849 
850     /**
851      * @param message detail message.
852      * @param cause cause.
853      * @param exitValue exit value.
854      */
855     public CompilerInstantiationException(final String message,
856         final Throwable cause, final int exitValue) {
857       super(message, cause);
858       this.exitValue = exitValue;
859     }
860 
861   }
862 }