View Javadoc

1   /*
2    * Copyright 1999-2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.struts.flow.core;
17  
18  import java.io.OutputStream;
19  import java.util.ArrayList;
20  import java.util.Map;
21  
22  /***
23   * Abstract superclass for various scripting languages used by Cocoon
24   * for flow control. Defines some useful behavior like the ability to
25   * reload script files if they get modified (useful when doing
26   * development), and passing the control to Cocoon's sitemap for
27   * result page generation.
28   * <p>
29   * Flow intrepreters belonging to different sitemaps should be isolated. To achieve this,
30   * class implements the {@link org.apache.avalon.framework.thread.SingleThreaded}. Since
31   * the sitemap engine looks up the flow intepreter once at sitemap build time, this ensures
32   * that each sitemap will use a different instance of this class. But that instance will
33   * handle all flow calls for a given sitemap, and must therefore be thread safe.
34   *
35   * @author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
36   * @since March 15, 2002
37   * @version CVS $Id: AbstractInterpreter.java 123711 2004-12-30 10:23:03Z cziegeler $
38   */
39  public abstract class AbstractInterpreter implements Interpreter {
40  
41      // The instance ID of this interpreter, used to identify user scopes
42      private String instanceID;
43  
44      /***
45       * List of source locations that need to be resolved.
46       */
47      protected ArrayList needResolve = new ArrayList();
48  
49      protected ContinuationsManager continuationsMgr;
50  
51      /***
52       * Whether reloading of scripts should be done. Specified through
53       * the "reload-scripts" attribute in <code>flow.xmap</code>.
54       */
55      protected boolean reloadScripts;
56  
57      /***
58       * Interval between two checks for modified script files. Specified
59       * through the "check-time" XML attribute in <code>flow.xmap</code>.
60       */
61      protected long checkTime;
62      
63      public AbstractInterpreter() {
64           try {
65              continuationsMgr = Factory.getContinuationsManager();
66          } catch (Exception e) {
67              Factory.getLogger().error(e);
68          }
69      }
70  
71      /***
72       * Set the unique ID for this interpreter, which can be used to distinguish user value scopes
73       * attached to the session.
74       */
75      public void setInterpreterID(String interpreterID) {
76          this.instanceID = interpreterID;
77      }
78  
79      /***
80       * Get the unique ID for this interpreter, which can be used to distinguish user value scopes
81       * attached to the session.
82       *
83       * @return a unique ID for this interpreter
84       */
85      public String getInterpreterID() {
86          return this.instanceID;
87      }
88  
89      /***
90       *  Sets the interval between when the script should be looked at to see if
91       *  it needs to be reloaded
92       *
93       *@param  time  The interval time in milliseconds
94       */
95      public void setCheckTime(long time) {
96          checkTime = time;
97      }
98  
99  
100     /***
101      *  Sets whether to try to reload modified scripts or not
102      *
103      *@param  val  True to reload
104      */
105     public void setReloadScripts(boolean val) {
106         reloadScripts = val;
107     }
108 
109     /***
110      * Registers a source file with the interpreter. Using this method
111      * an implementation keeps track of all the script files which are
112      * compiled. This allows them to reload the script files which get
113      * modified on the file system.
114      *
115      * <p>The parsing/compilation of a script file by an interpreter
116      * happens in two phases. In the first phase the file's location is
117      * registered in the <code>needResolve</code> array.
118      *
119      * <p>The second is possible only when a Cocoon
120      * <code>Environment</code> is passed to the Interpreter. This
121      * allows the file location to be resolved using Cocoon's
122      * <code>SourceFactory</code> class.
123      *
124      * <p>Once a file's location can be resolved, it is removed from the
125      * <code>needResolve</code> array and placed in the
126      * <code>scripts</code> hash table. The key in this hash table is
127      * the file location string, and the value is a
128      * DelayedRefreshSourceWrapper instance which keeps track of when
129      * the file needs to re-read.
130      *
131      * @param source the location of the script
132      *
133      * @see org.apache.cocoon.environment.Environment
134      * @see org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper
135      */
136     public void register(String source) {
137         synchronized (this) {
138             needResolve.add(source);
139         }
140     }
141 }