KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > flow > AbstractInterpreter


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.cocoon.components.flow;
17
18 import java.io.OutputStream JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import org.apache.avalon.framework.activity.Disposable;
23 import org.apache.avalon.framework.component.Component;
24 import org.apache.avalon.framework.configuration.Configurable;
25 import org.apache.avalon.framework.configuration.Configuration;
26 import org.apache.avalon.framework.configuration.ConfigurationException;
27 import org.apache.avalon.framework.context.ContextException;
28 import org.apache.avalon.framework.context.Contextualizable;
29 import org.apache.avalon.framework.logger.AbstractLogEnabled;
30 import org.apache.avalon.framework.service.ServiceException;
31 import org.apache.avalon.framework.service.ServiceManager;
32 import org.apache.avalon.framework.service.Serviceable;
33 import org.apache.avalon.framework.thread.SingleThreaded;
34 import org.apache.cocoon.Constants;
35 import org.apache.cocoon.components.ContextHelper;
36 import org.apache.cocoon.components.flow.util.PipelineUtil;
37 import org.apache.cocoon.environment.Context;
38 import org.apache.cocoon.environment.Redirector;
39 import org.apache.excalibur.source.SourceUtil;
40
41 /**
42  * Abstract superclass for various scripting languages used by Cocoon
43  * for flow control. Defines some useful behavior like the ability to
44  * reload script files if they get modified (useful when doing
45  * development), and passing the control to Cocoon's sitemap for
46  * result page generation.
47  * <p>
48  * Flow intrepreters belonging to different sitemaps should be isolated. To achieve this,
49  * class implements the {@link org.apache.avalon.framework.thread.SingleThreaded}. Since
50  * the sitemap engine looks up the flow intepreter once at sitemap build time, this ensures
51  * that each sitemap will use a different instance of this class. But that instance will
52  * handle all flow calls for a given sitemap, and must therefore be thread safe.
53  *
54  * @author <a HREF="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
55  * @since March 15, 2002
56  * @version CVS $Id: AbstractInterpreter.java 106089 2004-11-21 13:26:02Z lgawron $
57  */

58 public abstract class AbstractInterpreter
59         extends AbstractLogEnabled
60         implements Component, Serviceable, Contextualizable, Interpreter,
61                    SingleThreaded, Configurable, Disposable {
62
63     // The instance ID of this interpreter, used to identify user scopes
64
private String JavaDoc instanceID;
65
66     protected org.apache.avalon.framework.context.Context avalonContext;
67
68     /**
69      * List of source locations that need to be resolved.
70      */

71     protected ArrayList JavaDoc needResolve = new ArrayList JavaDoc();
72
73     protected org.apache.cocoon.environment.Context context;
74     protected ServiceManager manager;
75     protected ContinuationsManager continuationsMgr;
76
77     /**
78      * Whether reloading of scripts should be done. Specified through
79      * the "reload-scripts" attribute in <code>flow.xmap</code>.
80      */

81     protected boolean reloadScripts;
82
83     /**
84      * Interval between two checks for modified script files. Specified
85      * through the "check-time" XML attribute in <code>flow.xmap</code>.
86      */

87     protected long checkTime;
88
89     public AbstractInterpreter() {
90     }
91
92     /**
93      * Set the unique ID for this interpreter, which can be used to distinguish user value scopes
94      * attached to the session.
95      */

96     public void setInterpreterID(String JavaDoc interpreterID) {
97         this.instanceID = interpreterID;
98     }
99
100     /**
101      * Get the unique ID for this interpreter, which can be used to distinguish user value scopes
102      * attached to the session.
103      *
104      * @return a unique ID for this interpreter
105      */

106     public String JavaDoc getInterpreterID() {
107         return this.instanceID;
108     }
109
110     public void configure(Configuration config) throws ConfigurationException {
111         reloadScripts = config.getChild("reload-scripts").getValueAsBoolean(false);
112         checkTime = config.getChild("check-time").getValueAsLong(1000L);
113     }
114
115     /**
116      * Serviceable
117      */

118     public void service(ServiceManager sm) throws ServiceException {
119         this.manager = sm;
120         this.continuationsMgr = (ContinuationsManager)sm.lookup(ContinuationsManager.ROLE);
121     }
122
123     public void contextualize(org.apache.avalon.framework.context.Context context)
124     throws ContextException{
125         this.avalonContext = context;
126         this.context = (Context)context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
127     }
128
129     /* (non-Javadoc)
130      * @see org.apache.avalon.framework.activity.Disposable#dispose()
131      */

132     public void dispose() {
133         if ( this.manager != null ) {
134             this.manager.release( this.continuationsMgr );
135             this.continuationsMgr = null;
136             this.manager = null;
137         }
138     }
139
140     /**
141      * Registers a source file with the interpreter. Using this method
142      * an implementation keeps track of all the script files which are
143      * compiled. This allows them to reload the script files which get
144      * modified on the file system.
145      *
146      * <p>The parsing/compilation of a script file by an interpreter
147      * happens in two phases. In the first phase the file's location is
148      * registered in the <code>needResolve</code> array.
149      *
150      * <p>The second is possible only when a Cocoon
151      * <code>Environment</code> is passed to the Interpreter. This
152      * allows the file location to be resolved using Cocoon's
153      * <code>SourceFactory</code> class.
154      *
155      * <p>Once a file's location can be resolved, it is removed from the
156      * <code>needResolve</code> array and placed in the
157      * <code>scripts</code> hash table. The key in this hash table is
158      * the file location string, and the value is a
159      * DelayedRefreshSourceWrapper instance which keeps track of when
160      * the file needs to re-read.
161      *
162      * @param source the location of the script
163      *
164      * @see org.apache.cocoon.environment.Environment
165      * @see org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper
166      */

167     public void register(String JavaDoc source) {
168         synchronized (this) {
169             needResolve.add(source);
170         }
171     }
172
173     /**
174      * Call the Cocoon sitemap for the given URI, sending the output of the
175      * eventually matched pipeline to the specified outputstream.
176      *
177      * @param uri The URI for which the request should be generated.
178      * @param biz Extra data associated with the subrequest.
179      * @param out An OutputStream where the output should be written to.
180      * @exception Exception If an error occurs.
181      */

182     public void process(String JavaDoc uri, Object JavaDoc biz, OutputStream JavaDoc out)
183     throws Exception JavaDoc {
184         // FIXME (SW): should we deprecate this method in favor of PipelineUtil?
185
PipelineUtil pipeUtil = new PipelineUtil();
186         try {
187             pipeUtil.contextualize(this.avalonContext);
188             pipeUtil.service(this.manager);
189             pipeUtil.processToStream(uri, biz, out);
190         } finally {
191             pipeUtil.dispose();
192         }
193     }
194
195     public void forwardTo(String JavaDoc uri, Object JavaDoc bizData,
196                           WebContinuation continuation,
197                           Redirector redirector)
198     throws Exception JavaDoc {
199         if (SourceUtil.indexOfSchemeColon(uri) == -1) {
200             uri = "cocoon:/" + uri;
201             Map JavaDoc objectModel = ContextHelper.getObjectModel(this.avalonContext);
202             FlowHelper.setWebContinuation(objectModel, continuation);
203             FlowHelper.setContextObject(objectModel, bizData);
204             if (redirector.hasRedirected()) {
205                 throw new IllegalStateException JavaDoc("Pipeline has already been processed for this request");
206             }
207             // this is a hint for the redirector
208
objectModel.put("cocoon:forward", "true");
209             redirector.redirect(false, uri);
210         } else {
211             throw new Exception JavaDoc("uri is not allowed to contain a scheme (cocoon:/ is always automatically used)");
212         }
213     }
214 }
215
Popular Tags