View Javadoc

1   /*
2    *
3    *   Copyright 2006 The Apache Software Foundation.
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   *
17   */
18  package org.apache.commons.scxml.test;
19  
20  import java.io.BufferedReader;
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.InputStreamReader;
24  import java.net.URL;
25  import java.util.StringTokenizer;
26  
27  import org.apache.commons.scxml.Context;
28  import org.apache.commons.scxml.Evaluator;
29  import org.apache.commons.scxml.EventDispatcher;
30  import org.apache.commons.scxml.SCXMLExecutor;
31  import org.apache.commons.scxml.SCXMLHelper;
32  import org.apache.commons.scxml.TriggerEvent;
33  import org.apache.commons.scxml.env.SimpleDispatcher;
34  import org.apache.commons.scxml.env.Tracer;
35  import org.apache.commons.scxml.invoke.SimpleSCXMLInvoker;
36  import org.apache.commons.scxml.io.SCXMLDigester;
37  import org.apache.commons.scxml.io.SCXMLSerializer;
38  import org.apache.commons.scxml.model.ModelException;
39  import org.apache.commons.scxml.model.SCXML;
40  import org.xml.sax.SAXException;
41  
42  /***
43   * Utility methods used by command line SCXML execution, useful for
44   * debugging.
45   *
46   * The following expression languages are supported in SCXML documents:
47   * <ol>
48   *  <li>JEXL - Using Commons JEXL</li>
49   *  <li>EL - Using Commons EL</li>
50   * </ol>
51   *
52   * @see org.apache.commons.scxml.env.jexl
53   * @see org.apache.commons.scxml.env.jsp
54   */
55  public final class StandaloneUtils {
56  
57      /***
58       * Command line utility method for executing the state machine defined
59       * using the SCXML document described by the specified URI and using
60       * the specified expression evaluator.
61       *
62       * @param uri The URI or filename of the SCXML document
63       * @param evaluator The expression evaluator for the expression language
64       *                  used in the specified SCXML document
65       *
66       * <p>RUNNING:</p>
67       * <ul>
68       *  <li>Enter a space-separated list of "events"</li>
69       *  <li>To quit, enter "quit"</li>
70       *  <li>To populate a variable in the current context,
71       *      type "name=value"</li>
72       *  <li>To reset state machine, enter "reset"</li>
73       * </ul>
74       */
75      public static void execute(final String uri, final Evaluator evaluator) {
76          try {
77              String documentURI = getCanonicalURI(uri);
78              Context rootCtx = evaluator.newContext(null);
79              EventDispatcher ed = new SimpleDispatcher();
80              Tracer trc = new Tracer();
81              SCXML doc = SCXMLDigester.digest(new URL(documentURI), trc);
82              if (doc == null) {
83                  System.err.println("The SCXML document " + uri
84                          + " can not be parsed!");
85                  System.exit(-1);
86              }
87              System.out.println(SCXMLSerializer.serialize(doc));
88              SCXMLExecutor exec = new SCXMLExecutor(evaluator, ed, trc);
89              exec.addListener(doc, trc);
90              exec.registerInvokerClass("scxml", SimpleSCXMLInvoker.class);
91              exec.setRootContext(rootCtx);
92              exec.setStateMachine(doc);
93              exec.go();
94              BufferedReader br = new BufferedReader(new
95                  InputStreamReader(System.in));
96              String event = null;
97              while ((event = br.readLine()) != null) {
98                  event = event.trim();
99                  if (event.equalsIgnoreCase("help") || event.equals("?")) {
100                     System.out.println("Enter a space-separated list of "
101                         + "events");
102                     System.out.println("To populate a variable in the "
103                         + "current context, type \"name=value\"");
104                     System.out.println("To quit, enter \"quit\"");
105                     System.out.println("To reset state machine, enter "
106                         + "\"reset\"");
107                 } else if (event.equalsIgnoreCase("quit")) {
108                     break;
109                 } else if (event.equalsIgnoreCase("reset")) {
110                     exec.reset();
111                 } else if (event.indexOf('=') != -1) {
112                     int marker = event.indexOf('=');
113                     String name = event.substring(0, marker);
114                     String value = event.substring(marker + 1);
115                     rootCtx.setLocal(name, value);
116                     System.out.println("Set variable " + name + " to "
117                         + value);
118                 } else if (SCXMLHelper.isStringEmpty(event)
119                            || event.equalsIgnoreCase("null")) {
120                     TriggerEvent[] evts = {new TriggerEvent(null,
121                         TriggerEvent.SIGNAL_EVENT, null)};
122                     exec.triggerEvents(evts);
123                     if (exec.getCurrentStatus().isFinal()) {
124                         System.out.println("A final configuration reached.");
125                     }
126                 } else {
127                     StringTokenizer st = new StringTokenizer(event);
128                     int tkns = st.countTokens();
129                     TriggerEvent[] evts = new TriggerEvent[tkns];
130                     for (int i = 0; i < tkns; i++) {
131                         evts[i] = new TriggerEvent(st.nextToken(),
132                                 TriggerEvent.SIGNAL_EVENT, null);
133                     }
134                     exec.triggerEvents(evts);
135                     if (exec.getCurrentStatus().isFinal()) {
136                         System.out.println("A final configuration reached.");
137                     }
138                 }
139             }
140         } catch (IOException e) {
141             e.printStackTrace();
142         } catch (ModelException e) {
143             e.printStackTrace();
144         } catch (SAXException e) {
145             e.printStackTrace();
146         }
147     }
148 
149     /***
150      * @param uri an absolute or relative URL
151      * @return java.lang.String canonical URL (absolute)
152      * @throws java.io.IOException if a relative URL can not be resolved
153      *         to a local file
154      */
155     private static String getCanonicalURI(final String uri)
156     throws IOException {
157         if (uri.toLowerCase().startsWith("http://")
158             || uri.toLowerCase().startsWith("file://")) {
159                 return uri;
160         }
161         File in = new File(uri);
162         return "file:///" + in.getCanonicalPath();
163     }
164 
165     /***
166      * Discourage instantiation since this is a utility class.
167      */
168     private StandaloneUtils() {
169         super();
170     }
171 
172 }
173