001    /*
002     * Copyright 1999-2001,2004 The Apache Software Foundation.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.workflow.demo;
018    
019    
020    import java.io.File;
021    import org.apache.commons.digester.Digester;
022    import org.apache.commons.workflow.Activity;
023    import org.apache.commons.workflow.Context;
024    import org.apache.commons.workflow.ContextEvent;
025    import org.apache.commons.workflow.ContextListener;
026    import org.apache.commons.workflow.base.BaseContext;
027    import org.apache.commons.workflow.base.BaseRuleSet;
028    import org.apache.commons.workflow.core.CoreRuleSet;
029    import org.apache.commons.workflow.io.IoRuleSet;
030    import org.apache.commons.workflow.web.WebRuleSet;
031    
032    
033    /**
034     * <p>Demonstration program to illustrate how the Workflow Management System
035     * is utilized.  It accepts a command line argument to an XML file that
036     * contains an <code>&lt;activity&gt;</code> to be parsed and then executed.
037     * If no file is specified, a default XML document will be utilized.</p>
038     *
039     * <p><strong>WARNING</strong> - This program is for illustration only while
040     * the workflow management system is being developed, and it will not be
041     * part of the final package.  Indeed, much of its functionality (such as
042     * the parsing of XML files describing activities) will need to be encapsulated
043     * inside the system, in ways that support the per-namespace step definitions
044     * as outlined in the original proposal.</p>
045     *
046     * <p><strong>WARNING</strong> - This code depends on the version of Digester
047     * currently in SVN - the 1.0 released version will not work correctly with
048     * namespace prefixes.</p>
049     *
050     * <p><strong>WARNING</strong> - The namespace URLs in the example XML document
051     * are not official - they are simply used to satisfy the syntax requirements
052     * of the XML parser.  Official namespace URIs <em>will</em> be required for a
053     * formal release of this technology, because that is key to the extensibility
054     * of Step implementations.</p>
055     *
056     * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
057     * @author Craig R. McClanahan
058     */
059    
060    public class Main implements ContextListener {
061    
062    
063        // ----------------------------------------------------------- Main Program
064    
065    
066        /**
067         * The main program for the demo.
068         *
069         * @param args Command line arguments
070         */
071        public static void main(String args[]) {
072    
073            // Make sure there is a filename argument
074            if (args.length != 1) {
075                System.out.println("Usage:  java org.apache.commons.workflow.demo.Main {XML-file}");
076                System.exit(1);
077            }
078    
079            // Construct and utilize a new instance of this class
080            Main main = new Main();
081            main.process(args[0]);
082    
083        }
084    
085    
086        // ----------------------------------------------------- Instance Variables
087    
088    
089        /**
090         * The Activity constructed by our Digester.
091         */
092        protected Activity activity = null;
093    
094    
095        /**
096         * The Digester used to process input files.
097         */
098        protected Digester digester = null;
099    
100    
101        // ------------------------------------------------------------ Constructor
102    
103    
104        /**
105         * Construct a new instance of this class to process input files.
106         */
107        public Main() {
108    
109            super();
110            digester = createDigester();
111    
112        }
113    
114    
115        // -------------------------------------------------------- Support Methods
116    
117    
118        /**
119         * <p>Create a Digester instance that knows how to parse activities using
120         * the <code>core</code> and <code>io</code> built-in Steps.</p>
121         *
122         * <p><strong>WARNING</strong> - This will ultimately be abstracted into
123         * a mechanism to register the set of rule definitions associated with
124         * a namespace.</p>
125         */
126        protected Digester createDigester() {
127    
128            // Construct and configure a new Digester instance
129            Digester digester = new Digester();
130            //        digester.setDebug(999);
131            digester.setNamespaceAware(true);
132            digester.setValidating(false);
133            digester.push(this);
134    
135            // Add rules to recognize the built-in steps that we know about
136            BaseRuleSet brs = new BaseRuleSet();
137            digester.addRuleSet(brs);
138            digester.addRuleSet(new CoreRuleSet());
139            digester.addRuleSet(new IoRuleSet());
140    
141            // Add a rule to register the Activity being created
142            digester.setRuleNamespaceURI(brs.getNamespaceURI());
143            digester.addSetNext("activity", "setActivity",
144                                "org.apache.commons.workflow.Activity");
145    
146            // Return the completed instance
147            return (digester);
148    
149        }
150    
151    
152        /**
153         * Save the Activity that our Digester has constructed.
154         *
155         * @param activity The newly constructed Activity
156         */
157        public void setActivity(Activity activity) {
158    
159            this.activity = activity;
160    
161        }
162    
163    
164        /**
165         * Process the specified file.
166         *
167         * @param pathname Pathname of the specified XML file containing
168         *  an activity definition
169         */
170        public void process(String pathname) {
171    
172            // Parse the activity definition
173            try {
174                System.out.println("Main:  Parsing activity file " + pathname);
175                digester.parse(new File(pathname));
176            } catch (Throwable t) {
177                t.printStackTrace(System.out);
178                return;
179            }
180    
181            // Create a context and execute this activity
182            try {
183                System.out.println("Main:  Executing parsed activity");
184                Context context = new BaseContext();
185                context.setActivity(activity);
186                context.addContextListener(this);
187                context.execute();
188            } catch (Throwable t) {
189                t.printStackTrace(System.out);
190                return;
191            }
192    
193        }
194    
195    
196        // ------------------------------------------------ ContextListener Methods
197    
198    
199        /**
200         * Invoked immediately after execution of the related Activity has
201         * been completed normally, been suspended, or been aborted by
202         * the throwing of a StepException.  The Step included in this event
203         * will be the last one to be executed.
204         *
205         * @param event The <code>ContextEvent</code> that has occurred
206         */
207        public void afterActivity(ContextEvent event) {
208    
209            System.out.println("CL: afterActivity()");
210    
211        }
212    
213    
214        /**
215         * Invoked immediately after the specified Step was executed.
216         *
217         * @param event The <code>ContextEvent</code> that has occurred
218         */
219        public void afterStep(ContextEvent event) {
220    
221            System.out.println("CL: afterStep(" + event.getStep().getId() + ")");
222    
223        }
224    
225    
226        /**
227         * Invoked immediately before execution of the related Activity has
228         * started.  The Step included in this event will be the first one
229         * to be executed.
230         *
231         * @param event The <code>ContextEvent</code> that has occurred
232         */
233        public void beforeActivity(ContextEvent event) {
234    
235            System.out.println("CL: beforeActivity()");
236    
237        }
238    
239    
240        /**
241         * Invoked immediately before the specified Step is executed.
242         *
243         * @param event The <code>ContextEvent</code> that has occurred
244         */
245        public void beforeStep(ContextEvent event) {
246    
247            System.out.println("CL: beforeStep(" + event.getStep().getId() + ")");
248    
249        }
250    
251    
252    }