View Javadoc

1   /***
2    * Cecilia ADL Compiler
3    * Copyright (C) 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.implementations;
25  
26  import static org.objectweb.fractal.cecilia.adl.SourceCodeHelper.appendSortedSourceCodes;
27  
28  import java.io.File;
29  import java.io.IOException;
30  import java.util.ArrayList;
31  import java.util.Collection;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  
36  import org.objectweb.fractal.adl.ADLException;
37  import org.objectweb.fractal.adl.Definition;
38  import org.objectweb.fractal.adl.DefinitionVisitor;
39  import org.objectweb.fractal.adl.Node;
40  import org.objectweb.fractal.adl.components.ComponentContainer;
41  import org.objectweb.fractal.adl.error.GenericErrors;
42  import org.objectweb.fractal.api.Component;
43  import org.objectweb.fractal.api.NoSuchInterfaceException;
44  import org.objectweb.fractal.api.control.IllegalBindingException;
45  import org.objectweb.fractal.api.control.IllegalLifeCycleException;
46  import org.objectweb.fractal.cecilia.adl.SourceCodeProvider;
47  import org.objectweb.fractal.cecilia.adl.compiler.CompilationTaskFactory;
48  import org.objectweb.fractal.cecilia.adl.file.CodeWriter;
49  import org.objectweb.fractal.cecilia.adl.file.SourceFile;
50  import org.objectweb.fractal.cecilia.adl.file.SourceFileProvider;
51  import org.objectweb.fractal.cecilia.adl.file.SourceFileWriter;
52  import org.objectweb.fractal.task.core.AbstractTaskFactoryUser;
53  import org.objectweb.fractal.task.core.Executable;
54  import org.objectweb.fractal.task.core.TaskException;
55  import org.objectweb.fractal.task.core.primitive.annotations.ClientInterface;
56  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterface;
57  import org.objectweb.fractal.task.core.primitive.annotations.ServerInterfaces;
58  
59  public class GlobalInitVisitor extends AbstractTaskFactoryUser
60      implements
61        DefinitionVisitor {
62  
63    public static final String    COMPOSTION                        = "org.objectweb.fractal.cecilia.adl.implementations.GlobalInitCompilation";
64  
65    // ---------------------------------------------------------------------------
66    // Client interface
67    // ---------------------------------------------------------------------------
68  
69    /** The name of the {@link #compilationTaskFactoryItf} client interface. */
70    public static final String    COMPILATION_TASK_FACTORY_ITF_NAME = "compilation-task-factory";
71  
72    /** The client interface used to create compilation tasks. */
73    public CompilationTaskFactory compilationTaskFactoryItf;
74  
75    // ---------------------------------------------------------------------------
76    // Implementation of the DefinitionVisitor interface
77    // ---------------------------------------------------------------------------
78  
79    /**
80     * Visits {@link ComponentContainer} nodes and creates a task that writes the
81     * source code containing the component data structure definitions.
82     */
83    public Component visit(final List<Node> path, final Definition container,
84        final Map<Object, Object> context) throws ADLException, TaskException {
85      final Collection<Component> tasks = new ArrayList<Component>();
86      tasks.add(createGlobalInitialisationDeclarationTask(container, context));
87      tasks.add(createGlobalInitialisationCompilationTask(container, context));
88      return taskFactoryItf.newCompositeTask(tasks, COMPOSTION, null, container);
89    }
90  
91    // ---------------------------------------------------------------------------
92    // Utility methods
93    // ---------------------------------------------------------------------------
94  
95    protected Component createGlobalInitialisationDeclarationTask(
96        final Definition container, final Map<Object, Object> context)
97        throws TaskException {
98      return taskFactoryItf
99          .newPrimitiveTask(new GlobalInitialisationDeclatationTask(
100             (File) context.get("adlBuildDirectory"), container.getName()));
101   }
102 
103   protected Component createGlobalInitialisationCompilationTask(
104       final Definition container, final Map<Object, Object> context)
105       throws TaskException {
106     return compilationTaskFactoryItf
107         .newCompileTask("globalInit", null, context);
108   }
109 
110   // ---------------------------------------------------------------------------
111   // Task classes
112   // ---------------------------------------------------------------------------
113 
114   @ServerInterfaces(@ServerInterface(name = "global-init-code", signature = SourceFileProvider.class, record = "role:globalInitFile"))
115   public static class GlobalInitialisationDeclatationTask
116       implements
117         Executable,
118         SourceFileProvider {
119 
120     /** The suffix of the generated file. */
121     public static final String                   FILE_NAME_SUFFIX     = ".init.c";
122 
123     protected final File                         adlBuildDirectory;
124 
125     protected final String                       definitionName;
126 
127     // Produced source file
128     protected SourceFile                         sourceFile;
129 
130     // -------------------------------------------------------------------------
131     // Task client interfaces
132     // -------------------------------------------------------------------------
133 
134     /**
135      * The client interface bound to task providing declarations necessary for
136      * the constructor/destructor code.
137      */
138     @ClientInterface(name = "constructor-declaration-provider", signature = SourceCodeProvider.class, record = "role:globalInit, type:declaration")
139     public final Map<String, SourceCodeProvider> declatationsItfs     = new HashMap<String, SourceCodeProvider>();
140 
141     /** The client interface bound to task providing constructor code. */
142     @ClientInterface(name = "constructor-call-provider", signature = SourceCodeProvider.class, record = "role:globalInit, type:call, kind:constructor")
143     public final Map<String, SourceCodeProvider> constructorCallsItfs = new HashMap<String, SourceCodeProvider>();
144 
145     /** The client interface bound to task providing destructor code. */
146     @ClientInterface(name = "destructor-call-provider", signature = SourceCodeProvider.class, record = "role:globalInit, type:call, kind:destructor")
147     public final Map<String, SourceCodeProvider> destructorCallsItfs  = new HashMap<String, SourceCodeProvider>();
148 
149     // -------------------------------------------------------------------------
150     // Task constructor
151     // -------------------------------------------------------------------------
152 
153     /**
154      * @param adlBuildDirectory The directory into which the generated file will
155      *          be placed.
156      * @param definitionName the name of the global definition.
157      */
158     public GlobalInitialisationDeclatationTask(final File adlBuildDirectory,
159         final String definitionName) {
160       this.adlBuildDirectory = adlBuildDirectory;
161       this.definitionName = definitionName;
162     }
163 
164     // -------------------------------------------------------------------------
165     // Utility methods
166     // -------------------------------------------------------------------------
167 
168     protected void prepareSourceCode(final CodeWriter cw) throws Exception {
169 
170       cw.appendln("// --------------------------------------------------------"
171           + "---------------------");
172       cw.appendln("// declaration of global constructor/destructor functions");
173       cw.appendln("// --------------------------------------------------------"
174           + "---------------------");
175       cw.endl();
176 
177       appendSortedSourceCodes(cw, declatationsItfs.values());
178 
179       cw.appendln("void __cecilia_global_constructor__(void) {");
180       appendSortedSourceCodes(cw, constructorCallsItfs.values());
181       cw.appendln("}");
182 
183       cw.appendln("void __cecilia_global_destructor__(void) {");
184       appendSortedSourceCodes(cw, destructorCallsItfs.values());
185       cw.appendln("}");
186     }
187 
188     protected String getFileName() {
189       return definitionName.replace('.', '_') + FILE_NAME_SUFFIX;
190     }
191 
192     protected String getSignature() {
193       return definitionName + "_init";
194     }
195 
196     // -------------------------------------------------------------------------
197     // Implementation of the Executable interface
198     // -------------------------------------------------------------------------
199 
200     public void execute() throws Exception {
201       final String fileName = getFileName();
202       final File outputFile = new File(adlBuildDirectory, fileName);
203 
204       final CodeWriter cw = new CodeWriter();
205       cw.appendln("// THIS FILE HAS BEEN GENERATED BY THE CECILIA ADL "
206           + "COMPILER.");
207       cw.appendln("// DO NOT EDIT").endl();
208       prepareSourceCode(cw);
209 
210       try {
211         SourceFileWriter.writeToFile(outputFile, cw.toString());
212       } catch (final IOException e) {
213         throw new ADLException(GenericErrors.INTERNAL_ERROR, e,
214             "An error occurs while writing to file '"
215                 + outputFile.getAbsolutePath() + "'");
216       }
217 
218       sourceFile = new SourceFile(getSignature(), outputFile);
219     }
220 
221     // -------------------------------------------------------------------------
222     // Implementation of the SourceFileProvider interface
223     // -------------------------------------------------------------------------
224 
225     public SourceFile getSourceFile() {
226       return sourceFile;
227     }
228   }
229 
230   // ---------------------------------------------------------------------------
231   // Implementation of the BindingController interface
232   // ---------------------------------------------------------------------------
233 
234   @Override
235   public String[] listFc() {
236     final String[] superItfs = super.listFc();
237     final String[] itfs = new String[superItfs.length + 1];
238     System.arraycopy(superItfs, 0, itfs, 0, superItfs.length);
239     itfs[superItfs.length] = COMPILATION_TASK_FACTORY_ITF_NAME;
240     return itfs;
241   }
242 
243   @Override
244   public void bindFc(final String clientItfName, final Object serverItf)
245       throws NoSuchInterfaceException, IllegalBindingException,
246       IllegalLifeCycleException {
247 
248     if (clientItfName == null) {
249       throw new IllegalArgumentException("Interface name can't be null");
250     }
251 
252     if (clientItfName.equals(COMPILATION_TASK_FACTORY_ITF_NAME))
253       compilationTaskFactoryItf = (CompilationTaskFactory) serverItf;
254     else
255       super.bindFc(clientItfName, serverItf);
256   }
257 
258   @Override
259   public Object lookupFc(final String clientItfName)
260       throws NoSuchInterfaceException {
261 
262     if (clientItfName == null) {
263       throw new IllegalArgumentException("Interface name can't be null");
264     }
265 
266     if (clientItfName.equals(COMPILATION_TASK_FACTORY_ITF_NAME))
267       return compilationTaskFactoryItf;
268     else
269       return super.lookupFc(clientItfName);
270   }
271 
272   @Override
273   public void unbindFc(final String clientItfName)
274       throws NoSuchInterfaceException, IllegalBindingException,
275       IllegalLifeCycleException {
276 
277     if (clientItfName == null) {
278       throw new IllegalArgumentException("Interface name can't be null");
279     }
280 
281     if (clientItfName.equals(COMPILATION_TASK_FACTORY_ITF_NAME))
282       compilationTaskFactoryItf = null;
283     else
284       super.unbindFc(clientItfName);
285   }
286 }