Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/tripi/asp/AspContext.java


1   /**
2    * ArrowHead ASP Server 
3    * This is a source file for the ArrowHead ASP Server - an 100% Java
4    * VBScript interpreter and ASP server.
5    *
6    * For more information, see http://www.tripi.com/arrowhead
7    *
8    * Copyright (C) 2002  Terence Haddock
9    *
10   * This program is free software; you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation; either version 2 of the License, or
13   * (at your option) any later version.
14   *
15   * This program is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   * GNU General Public License for more details.
19   *
20   * You should have received a copy of the GNU General Public License
21   * along with this program; if not, write to the Free Software
22   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23   *
24   */
25  package com.tripi.asp;
26  
27  import java.lang.reflect.InvocationTargetException;
28  import java.lang.reflect.Method;
29  import java.net.MalformedURLException;
30  import java.net.URL;
31  import java.util.Enumeration;
32  import java.util.Hashtable;
33  import java.util.Stack;
34  import java.util.Vector;
35  
36  import org.apache.log4j.Category;
37  
38  /**
39   * This class implements a class to hold the current state of ASP 
40   * execution.
41   *
42   * @author Terence Haddock
43   */
44  public class AspContext
45  {
46      /** Debugging information */
47      private static final Category DBG = Category.getInstance(AspContext.class);
48  
49      /** Universal scope */
50      Hashtable   universalScope;
51  
52      /** Global scope */
53      Hashtable   globalScope;
54  
55      /** Subroutine scope */
56      Stack       subroutineScope;
57  
58      /** Vector of objects to call OnPageEnd to */
59      Vector      onPageEnd;
60      
61      /** Are we option explicit? */
62      boolean     optionExplicit = false;
63  
64      /**
65       * Constructor.
66       * @param universalScope Universal scope
67       */
68      public AspContext(Hashtable universalScope)
69      {
70          this.universalScope = universalScope;
71          this.globalScope = new Hashtable();
72          this.subroutineScope = new Stack();
73          onPageEnd = new Vector();
74      }
75  
76      /**
77       * This function clones this context.
78       * @return a cloned snapshop of this context.
79       */
80      protected Object clone()
81      {
82          AspContext ctx = new AspContext(universalScope);
83          ctx.globalScope = (Hashtable)globalScope.clone();
84          ctx.subroutineScope = (Stack)subroutineScope.clone();
85          ctx.onPageEnd = onPageEnd;
86          ctx.optionExplicit = optionExplicit;
87          return ctx;
88      }
89  
90      /**
91       * This function determines if a variable is directly in scope.
92       * This is slightly different from inScope, as the variable is not
93       * tested against the global scope if we are in a subroutine.
94       *
95       * @param ident identifier to check
96       * @return <b>true</b> if the variable is in scope, <b>false</b> otherwise.
97       */
98      public boolean inDirectScope(IdentNode ident)
99      {
100         if (DBG.isDebugEnabled())
101             DBG.debug("inDirectScope(" + ident + ")");
102         if (!subroutineScope.empty())
103         {
104             Hashtable subScope = (Hashtable)subroutineScope.peek();
105             if (subScope.containsKey(ident))
106                 return true;
107         } else {
108             if (globalScope.containsKey(ident))
109                 return true;
110         }
111         if (universalScope.containsKey(ident))
112             return true;
113         return false;
114     }
115 
116     /**
117      * This function determines if a variable is in scope.
118      *
119      * @param ident identifier to check
120      * @return <b>true</b> if the variable is in scope, <b>false</b>
121      * otherwise.
122      */
123     public boolean inScope(IdentNode ident)
124     {
125         if (DBG.isDebugEnabled())
126             DBG.debug("inScope(" + ident + ")");
127         if (!subroutineScope.empty())
128         {
129             Hashtable subScope = (Hashtable)subroutineScope.peek();
130             if (subScope.containsKey(ident))
131                 return true;
132         }
133         if (globalScope.containsKey(ident))
134             return true;
135         if (universalScope.containsKey(ident))
136             return true;
137         return false;
138     }
139 
140     /**
141      * This function forces an identifier's scope to the current context.
142      *
143      * @param ident Identifier to force
144      */
145     public void forceScope(IdentNode ident)
146     {
147         if (!subroutineScope.empty())
148         {
149             Hashtable subScope = (Hashtable)subroutineScope.peek();
150             subScope.put(ident, Constants.undefinedValueNode);
151             return;
152         }
153         globalScope.put(ident, Constants.undefinedValueNode);
154     }
155 
156     /**
157      * This function obtains the value of a variable
158      *
159      * @param ident Identifier to obtain
160      * @return Value of the variable.
161      * @throws AspException on error
162      */
163     public Object getValue(IdentNode ident) throws AspException
164     {
165         if (DBG.isDebugEnabled())
166             DBG.debug("getValue(" + ident + ")");
167         if (!subroutineScope.empty())
168         {
169             Hashtable subScope = (Hashtable)subroutineScope.peek();
170             if (subScope.containsKey(ident))
171                 return subScope.get(ident);
172         }
173         if (globalScope.containsKey(ident))
174             return globalScope.get(ident);
175         if (universalScope.containsKey(ident))
176             return universalScope.get(ident);
177         if (optionExplicit)
178             throw new AspException("Undefined variable: " + ident);
179         return Constants.undefinedValueNode;
180     }
181 
182     /**
183      * Set the value of an identifier.
184      *
185      * @param ident Identifier name
186      * @param value New value of object
187      * @throws AspException on error
188      */
189     public void setValue(IdentNode ident, Object value) throws AspException
190     {
191         if (DBG.isDebugEnabled())
192             DBG.debug("setValue(" + ident + ")=" + value);
193         if (value == null) value = Constants.nullNode;
194         /**
195          * If the variable is in subroutine scope: store it in sub.
196          * Otherwise, if the variable is in global scope, store it in global.
197          * Otherwise, if subroutine scope exists, store it there.
198          * Otherwise, store it in global scope.
199          */
200         if (!subroutineScope.empty()) {
201             Hashtable subScope = (Hashtable)subroutineScope.peek();
202             if (subScope.containsKey(ident) || !globalScope.containsKey(ident))
203             {
204                 subScope.put(ident, value);
205                 return;
206             }
207         }
208         globalScope.put(ident, value);
209         return;
210     }
211 
212     /**
213      * Sets the option explicit flag.
214      * @throws AspException on error
215      */
216     void setOptionExplicit() throws AspException
217     {
218         if (optionExplicit) 
219             throw new AspException("Option Explicit can be called only once");
220         optionExplicit = true;
221     }
222 
223     /**
224      * Pushes a new subroutine scope onto the scope stack.
225      * @param scope new subroutine scope
226      * @throws AspException on error
227      */
228     void pushSubroutineScope(Hashtable scope) throws AspException
229     {
230         subroutineScope.push(scope);
231     }
232 
233     /**
234      * Pops a subroutine scope off of the scope stack.
235      * @return old subroutine scope, or null if there is no scopes left
236      * @throws AspException on error
237      */
238     Hashtable popSubroutineScope() throws AspException
239     {
240         return (Hashtable)subroutineScope.pop();
241     }
242 
243     /**
244      * Utility function to obtain the Server object.
245      * XXX Should this be here, or in a separate class?
246      * @return Server object
247      * @throws AspException on error
248      */
249     public Server getAspServer() throws AspException
250     {
251         final IdentNode serverIdent = new IdentNode("Server");
252         JavaObjectNode jon = (JavaObjectNode)getValue(serverIdent);
253         return (Server)jon.getSubObject();
254     }
255 
256     /**
257      * Utility function to obtain the Session object.
258      * @return Session object
259      * @throws AspException on error
260      */
261     public Session getAspSession() throws AspException
262     {
263         final IdentNode sessionIdent = new IdentNode("Session");
264         JavaObjectNode jon = (JavaObjectNode)getValue(sessionIdent);
265         return (Session)jon.getSubObject();
266     }
267 
268     /**
269      * Utility function to obtain the Application object.
270      * @return Application object
271      * @throws AspException on error
272      */
273     public Application getAspApplication() throws AspException
274     {
275         final IdentNode appIdent = new IdentNode("Application");
276         JavaObjectNode jon = (JavaObjectNode)getValue(appIdent);
277         return (Application)jon.getSubObject();
278     }
279 
280     /**
281      * Utility function to obtain the Request object.
282      * @return Request object
283      * @throws AspException on error
284      */
285     public Request getAspRequest() throws AspException
286     {
287         final IdentNode rspIdent = new IdentNode("Request");
288         JavaObjectNode jon = (JavaObjectNode)getValue(rspIdent);
289         return (Request)jon.getSubObject();
290     }
291 
292     /**
293      * Utility function to obtain the Response object.
294      * @return Response object
295      * @throws AspException on error
296      */
297     public Response getAspResponse() throws AspException
298     {
299         final IdentNode rspIdent = new IdentNode("Response");
300         JavaObjectNode jon = (JavaObjectNode)getValue(rspIdent);
301         return (Response)jon.getSubObject();
302     }
303 
304     /**
305      * Adds a class to call the OnPageEnd when the page ends.
306      * @param obj Object to call the OnPageEnd method.
307      */
308     public void addOnPageEnd(Object obj)
309     {
310         if (DBG.isDebugEnabled()) DBG.debug("Adding OnPageEnd for " + obj);
311         onPageEnd.add(obj);
312     }
313 
314     /**
315      * Calls the OnPageEnd methods of the object.
316      */
317     public synchronized void callOnPageEnd()
318     {
319         if (DBG.isDebugEnabled()) DBG.debug("Calling all OnPageEnd");
320         for (Enumeration eItems = onPageEnd.elements(); eItems.hasMoreElements();)
321         {
322             Object obj = eItems.nextElement();
323             callOnPageEnd(obj);
324         }
325         onPageEnd.clear();
326     }
327 
328     /**
329      * Calls the OnPageEnd method of a particular object.
330      * @param obj Object to call
331      */
332     void callOnPageEnd(Object obj)
333     {
334         if (DBG.isDebugEnabled()) DBG.debug("OnPageEnd for " + obj);
335         Class paramTypes[] = new Class[1];
336         paramTypes[0] = Object.class;
337         Object paramArguments[] = new Object[1];
338         paramArguments[0] = this;
339 
340         Class cls = obj.getClass();
341         try {
342             Method met = cls.getMethod("OnPageEnd", paramTypes);
343             met.invoke(obj, paramArguments);
344         } catch (NoSuchMethodException ex)
345         {
346         } catch (IllegalAccessException ex)
347         {
348         } catch (InvocationTargetException ex)
349         {
350         }
351     }
352 
353     /**
354      * Calls the OnPageStart method of a particular object.
355      * @param obj Object to call
356      */
357     void callOnPageStart(Object obj)
358     {
359         if (DBG.isDebugEnabled()) DBG.debug("OnPageStart for " + obj);
360         Class paramTypes[] = new Class[1];
361         paramTypes[0] = Object.class;
362         Object paramArguments[] = new Object[1];
363         paramArguments[0] = this;
364 
365         Class cls = obj.getClass();
366         try {
367             Method met = cls.getMethod("OnPageStart", paramTypes);
368             met.invoke(obj, paramArguments);
369         } catch (NoSuchMethodException ex)
370         {
371         } catch (IllegalAccessException ex)
372         {
373         } catch (InvocationTargetException ex)
374         {
375         }
376     }
377 
378     /**
379      * This utility function checks if ResumeNext is in effect.
380      *
381      * @param context Current Context
382      * @return true if resume next is in effect, false otherwise
383      * @throws AspException on error
384      */
385     boolean resumeNext() throws AspException
386     {
387         final IdentNode ident = new IdentNode("_err");
388         if (DBG.isDebugEnabled()) DBG.debug("Resume next test");
389         if (inScope(ident)) {
390             Object obj = getValue(ident);
391             if (DBG.isDebugEnabled()) DBG.debug("Resume next: " + obj);
392             if (obj == null || obj instanceof NullNode) {
393                 return true;
394             }
395         }
396         return false;
397     }
398 
399     /**
400      * This function handles error processing.
401      * 
402      * @param ex Exception thrown
403      * @param ctx Current debugging context
404      * @throws AspException on error
405      */
406     public void processException(Exception ex, DebugContext ctx)
407         throws AspException
408     {
409         if (ex instanceof AspExitException) throw (AspExitException)ex;
410 
411         final IdentNode Err = new IdentNode("Err");
412         AspException aspEx = new AspNestedException(ex, ctx);
413         setValue(Err, new JavaObjectNode(aspEx));
414         if (!resumeNext())
415         {
416             throw aspEx;
417         }
418     }
419 
420     /**
421      * This function obtains the URL associated with the given filename.
422      *
423      * @param filename Full pathname to file
424      * @return URL associated with the given filename
425      * @throws AspException on error
426      */
427     public URL getURL(String filename) throws AspException
428     {
429         /* Get the server object */
430         final IdentNode serverIdent = new IdentNode("server");
431         JavaObjectNode serverNode = (JavaObjectNode)getValue(serverIdent);
432         Server server = (Server)serverNode.getSubObject();
433 
434         try {
435             if (DBG.isDebugEnabled()) DBG.debug("Getting URL for: " + filename);
436             /* Get the URL for the file */
437             URL url = server.servletContext.getResource(filename);
438 
439             if (DBG.isDebugEnabled()) DBG.debug("URL for: " + filename + "=" + url);
440 
441             if (url == null) url = new URL("file://" + filename);
442 
443             return url;
444         } catch (MalformedURLException ex) {
445             throw new AspNestedException(ex);
446         }
447     }
448 }
449