001/*
002 * Copyright (c) 2008-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2013-05-15 18:43:58 +0000 (Wed, 15 May 2013) $' 
007 * '$Revision: 32048 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler;
031
032import java.io.File;
033import java.io.FileNotFoundException;
034import java.io.FileReader;
035import java.io.IOException;
036import java.util.Vector;
037
038import org.kepler.loader.util.ParseWorkflow;
039import org.kepler.util.sql.HSQL;
040
041import ptolemy.actor.CompositeActor;
042import ptolemy.actor.ExecutionListener;
043import ptolemy.actor.Manager;
044import ptolemy.kernel.util.IllegalActionException;
045import ptolemy.kernel.util.KernelException;
046import ptolemy.kernel.util.NamedObj;
047import ptolemy.kernel.util.Workspace;
048import ptolemy.moml.MoMLParser;
049import ptolemy.moml.filter.BackwardCompatibility;
050import ptolemy.util.MessageHandler;
051
052/**
053 * This class is the main entry point for making API calls to the underlying
054 * ptolemy execution engine and moml parser.
055 */
056public class ExecutionEngine implements ExecutionListener
057{
058  private static ExecutionEngine instance = null;
059  private Vector<ExecutionListener> exeListeners;
060  
061  /**
062   * singleton accessor
063   */
064  public static ExecutionEngine getInstance()
065  {
066    if(instance == null)
067    {
068        instance = new ExecutionEngine();
069    }
070    return instance;
071  }
072  
073  /**
074   * private constructor
075   */
076  private ExecutionEngine()
077  {
078    MoMLParser.setMoMLFilters(BackwardCompatibility.allFilters());
079    MessageHandler.setMessageHandler(new MessageHandler());
080    exeListeners = new Vector<ExecutionListener>();
081  }
082  
083  /**
084   * run a single model in the current thread
085   * @param model the model to run
086   * @return Manager the manager to control the execution
087   */
088  public Manager runModel(CompositeActor model) 
089    throws IllegalActionException, KernelException
090  {
091    System.out.println("Running model in current thread: " + model.getName());
092    Manager manager = setupModel(model);
093    runModel(manager, false);
094    return manager;
095  }
096  
097  /**
098   * run a model in a new thread.  Use the manager to control the thread.
099   * @param model the model to run
100   * @return Manager the manager that controls the new thread
101   */
102  public Manager runModelInThread(CompositeActor model)
103    throws IllegalActionException, KernelException
104  {
105    System.out.println("Running model in new thread: " + model.getName());
106    Manager manager = setupModel(model);
107    runModel(manager, true);
108    return manager;
109  }
110  
111  /**
112   * add an execution listener
113   * @param exeListener the listener to add
114   */
115  public void addExecutionListener(ExecutionListener exeListener)
116  {
117    exeListeners.addElement(exeListener);
118  }
119  
120  /**
121   * remove an execution listener
122   * @param exeListener the listener to remove
123   */
124  public void removeExecutionListener(ExecutionListener exeListener)
125  {
126    exeListeners.remove(exeListener);
127  }
128  
129  /**
130   * return a vector of all of the registered ExecutionListeners
131   */
132  public Vector<ExecutionListener> getExecutionListeners()
133  {
134    return exeListeners;
135  }
136  
137  /**
138   * static method to parse a moml document and return a NamedObj
139   * @param moml the moml to parse
140   */
141  public static NamedObj parseMoML(String moml)
142    throws Exception
143  {
144    return parseMoML(moml, null);
145  }
146  
147  /**
148   * static method to parse a moml document and return a NamedObj
149   * @param moml the moml to parse
150   * @param workspace the workspace to parse the moml in to.
151   */
152  public static NamedObj parseMoML(String moml, Workspace workspace)
153    throws Exception
154  {
155    MoMLParser parser;
156    if(workspace == null)
157    {
158      parser = new MoMLParser();
159    }
160    else
161    {
162      parser = new MoMLParser(workspace);
163    }
164    NamedObj obj = parser.parse(moml);
165    return obj;
166  }
167  
168  /**
169   * read a file and return its contents as a string
170   * @param filename the name or path of the file to read
171   */
172  public static String readFile(String filename)
173    throws FileNotFoundException, IOException
174  {
175    File f = new File(filename);
176    FileReader fr = null;
177    try
178    {
179        fr = new FileReader(f);
180        char[] c = new char[1024];
181        int numread = fr.read(c, 0, 1024);
182        StringBuffer sb = new StringBuffer();
183        while(numread != -1)
184        {
185          sb.append(c, 0, numread);
186          numread = fr.read(c, 0, 1024);
187        }
188        return sb.toString();
189    }
190    finally
191    {
192        if(fr != null)
193        {
194            fr.close();
195        }
196    }
197  }
198  
199  /**
200   * command line interface to this class
201   */
202  public static void main(String[] args)
203  {
204    if(args.length != 1)
205    {
206      System.out.println("You must provide the path to the workflow to run.");
207    }
208    try
209    {
210        
211      Kepler.initialize();
212      Kepler.setJavaPropertiesAndCopyModuleDirectories();
213
214      String workflow = args[0];
215      File workflowFile = new File(workflow);
216      ExecutionEngine engine = ExecutionEngine.getInstance();
217      CompositeActor model = (CompositeActor) ParseWorkflow.parseWorkflow(workflowFile);
218      if(model == null) {
219          MessageHandler.error("Error loading " + args[0]);
220      } else {
221          engine.runModel(model);
222      }
223    }
224    catch(Exception e)
225    {
226      MessageHandler.error("Error running " + args[0], e);
227    }
228    Kepler.shutdown();
229    HSQL.shutdownServers();
230  }
231  
232  /**
233   * implements executionError in ExecutionListener
234   */
235  public void executionError(Manager manager, Throwable throwable)
236  {
237    System.out.println("Execution finished with an error: " + throwable.getMessage());
238  }
239  
240  /**
241   * implements executionFinished in ExecutionListener
242   */
243  public void executionFinished(Manager manager)
244  {
245    System.out.println("Execution finished successfully.");
246  }
247  
248  /**
249   * implements managerStateChanged in ExecutionListener
250   */
251  public void managerStateChanged(Manager manager)
252  {
253    //System.out.println("Manager state changed to " + manager.getState());
254  }
255  
256  /**
257   * start the execution of the model, either in a new thread or in the
258   * current thread.
259   */
260  private void runModel(Manager manager, boolean newThread)
261    throws IllegalActionException, KernelException
262  {
263    if(newThread)
264    {
265      manager.startRun();
266    }
267    else
268    {
269      manager.execute();
270    }
271  }
272  
273  /**
274   * prepare a model for running
275   */
276  private Manager setupModel(CompositeActor actor)
277    throws IllegalActionException
278  {
279    Manager manager = actor.getManager();
280    if (manager == null) 
281    {
282        manager = new Manager(actor.workspace(), "manager");
283        actor.setManager(manager);
284    }
285
286    manager.addExecutionListener(this);
287    for(int i=0; i<exeListeners.size(); i++)
288    {
289      ExecutionListener listener = (ExecutionListener)exeListeners.elementAt(i);
290      manager.addExecutionListener(listener);
291    }
292    return manager;
293  }
294}