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

Quick Search    Search Deep

Source code: com/tripi/asp/parse/NestedTokenManager.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.parse;
26  
27  import com.tripi.asp.*;
28  
29  import java.io.InputStream;
30  import java.io.IOException;
31  import java.io.StringReader;
32  import java.util.Stack;
33  import jregex.*;
34  import org.apache.log4j.Category;
35  
36  /**
37   * This class is a nested token manager, and handles VBScript tokens 
38   * embedded within ASP files.
39   */
40  public class NestedTokenManager implements TokenManager
41  {
42      /** Debugging class */
43      Category DBG = Category.getInstance(NestedTokenManager.class);
44  
45      /** This inner class contains information about a file being loaded */
46      static class FileInfo
47      {
48          /** Abosolute filename for the file. */
49          String filename; 
50  
51          /** Active token manager for the file. */
52          AspParseTokenManager tokManager;
53      }
54  
55      /** Stack of current parsers */
56      Stack fileInfoStack = new Stack();
57  
58      /** Are we in VBScript or looking as ASP tokens */
59      boolean inScript;
60  
61      /** The token factory we use to read VBScript tokens */
62      TokenManager subTokenManager;
63  
64      /** File Factory used to obtain input streams from fiels */
65      FileFactory fileFactory;
66  
67      /** Next token */
68      Token nextToken = null;
69  
70      /**
71       * Constructor, with an initial filename and file factory.
72       * @param filename Initial filename
73       * @param fileFactory factory used to obtain files
74       * @throws IOException on error
75       */
76      public NestedTokenManager(String filename, FileFactory fileFactory)
77          throws AspException
78      {
79          this.fileFactory = fileFactory;
80          this.inScript = false;
81          FileInfo fileInfo = getFileInfo(filename);
82          fileInfoStack.push(fileInfo);
83      }
84  
85      /**
86       * Get the FileInfo structure for the file.
87       * @param base Base filename
88       * @param filename Relative filename to open
89       * @return FileInfo class containing filename and parser.
90       * @throws IOException on input/output error
91       */
92      FileInfo getFileInfo(String filename) throws AspException
93      {
94          FileInfo fileInfo = new FileInfo();
95          fileInfo.filename = filename;
96  
97          InputStream is = fileFactory.getResource(fileInfo.filename);
98          SimpleCharStream stream = new SimpleCharStream(is);
99          fileInfo.tokManager = new AspParseTokenManager(stream);
100         return fileInfo;
101     }
102 
103     /**
104      * Internal function to find the contents of an SGML token.
105      * @param str String to find contents of
106      * @return contents of SGML token
107      */
108     private String getTokenContents(String str)
109     {
110         final Pattern p = new Pattern("^<[^>]*>(.*)<[^>]*>$",
111             REFlags.MULTILINE | REFlags.IGNORE_SPACES | REFlags.DOTALL);
112         Matcher m = p.matcher(str);
113         if (!m.matches()) throw new AspRuntimeException("Internal error");
114         return m.group(1);
115     }
116 
117     /**
118      * Obtains a token manager for the data contained within the token.
119      * The token should be an ASPScript token, the <%, %> characters will
120      * be stripped.
121      * @param tok ASP Token to parse code from.
122      * @return TokenManager for parsing the code.
123      */
124     TokenManager getTokenManager(Token tok)
125     {
126         String subStr;
127         if (tok.kind == AspParseConstants.ASPSCRIPT ||
128             tok.kind == AspParseConstants.OUTPUTSCRIPT)
129         {
130             subStr = tok.image.substring(2, tok.image.length() - 2);
131         } else if (tok.kind == AspParseConstants.SERVERSCRIPT)
132         {
133             subStr = getTokenContents(tok.image);
134         } else {
135             DebugContext ctx = new DebugContext();
136             tok.fillDebugContext(ctx);
137             throw new AspRuntimeException("Internal parse error: " +
138                 "Unexptected token type " + tok.kind, ctx);
139         }
140         StringReader sr = new StringReader(subStr);
141         SimpleCharStream stream = new SimpleCharStream(sr, tok.beginLine,
142             tok.beginColumn + 2);
143         return new VBScriptTokenManagerInterface(stream);
144     }
145 
146     /**
147      * Obtain the filename from an include specification.
148      * @param include include specification which to obtain file from.
149      * @return filename for the include specification.
150      */
151     String getFilenameFromInclude(String baseFilename, String include)
152         throws AspException
153     {
154         final Pattern p = new Pattern("<!--[ \t]*#include[ \t]*(file|virtual)" +
155             "[ \t]*=[ \t]*\"([^\"]*)\"[ \t]*-->", REFlags.IGNORE_CASE);
156         Matcher m = p.matcher(include);
157         if (!m.matches())
158         {
159             throw new AspRuntimeException("Internal error");
160         }
161         String virtual = m.group(1);
162         String relativeFilename = m.group(2);
163         String filename = fileFactory.resolveFile(baseFilename,
164                     relativeFilename, virtual.equalsIgnoreCase("virtual"));
165         return filename;
166     }
167 
168     /**
169      * Clone the token, keeping debugging information and image.
170      * @param tok Token to close
171      */
172     public Token cloneToken(Token tok)
173     {
174         Token retTok = new Token();
175         retTok.image = tok.image;
176         retTok.kind = 0;
177         retTok.beginLine = tok.beginLine;
178         retTok.beginColumn = tok.beginColumn;
179         retTok.endLine = tok.endLine;
180         retTok.endColumn = tok.endColumn;
181         retTok.filename = tok.filename;
182         return retTok;
183     }
184 
185     /**
186      * Obtain the next token from the stream.
187      * @return next token from the stream.
188      */
189     public Token getNextToken()
190     {
191         if (DBG.isDebugEnabled()) DBG.debug("getNextToken");
192         if (nextToken != null) {
193             Token retTok = nextToken;
194             nextToken = null;   
195             if (DBG.isDebugEnabled()) DBG.debug("nextToken: " + retTok.kind);
196             return retTok;
197         }
198         if (DBG.isDebugEnabled()) DBG.debug("Peek");
199         FileInfo fileInfo = (FileInfo)fileInfoStack.peek();
200         if (DBG.isDebugEnabled()) DBG.debug("inScript: " + inScript);
201         if (inScript)
202         try {
203             if (DBG.isDebugEnabled()) DBG.debug("subTokenManager: " + subTokenManager);
204             Token tok = subTokenManager.getNextToken();
205             if (DBG.isDebugEnabled()) DBG.debug("filename: " + fileInfo.filename);
206             tok.filename = fileInfo.filename;
207             if (DBG.isDebugEnabled()) DBG.debug("Language token: " + tok.kind);
208             if (tok.kind != 0)
209                 return tok;
210             inScript = false;
211         } catch (TokenMgrError e) {
212             DBG.error(e);
213             e.setFilename(fileInfo.filename);
214             throw e;
215         }
216         Token tok = null;
217         try {
218             AspParseTokenManager tm = fileInfo.tokManager;
219             if (DBG.isDebugEnabled()) DBG.debug("Asp getNextToken");
220             tok = tm.getNextToken();
221             if (DBG.isDebugEnabled()) DBG.debug("ASP Token: " + tok.kind);
222             tok.filename = fileInfo.filename;
223             if (tok.kind == 0) {
224                 fileInfoStack.pop();
225                 if (fileInfoStack.empty())
226                 {
227                     return tok;
228                 }
229                 return getNextToken();
230             }
231             switch(tok.kind)
232             {
233                 case AspParseConstants.ASPSCRIPT:
234                     subTokenManager = getTokenManager(tok);
235                     inScript = true;
236                     return getNextToken();
237                 case AspParseConstants.SERVERSCRIPT:
238                     subTokenManager = getTokenManager(tok);
239                     inScript = true;
240                     return getNextToken();
241                 case AspParseConstants.OUTPUTSCRIPT:
242                     subTokenManager = getTokenManager(tok);
243                     inScript = true;
244                     nextToken = cloneToken(tok);
245                     nextToken.kind = VBScriptConstants.OUTPUT;
246 
247                     Token retTok = cloneToken(tok);
248                     retTok.kind = VBScriptConstants.NL;
249                     retTok.image = "\n";
250                     return retTok;
251                 case AspParseConstants.INCLUDE:
252                     String filename = getFilenameFromInclude(
253                     fileInfo.filename, tok.image);
254                     FileInfo subFileInfo = getFileInfo(filename);
255                     fileInfoStack.push(subFileInfo);
256                     return getNextToken();
257                 case AspParseConstants.HTML:
258                     if (!containsOnlyWS(tok.image))
259                     {
260                         Token thisTok = cloneToken(tok);
261 
262                         nextToken = cloneToken(tok);
263                         nextToken.kind = VBScriptConstants.HTML;
264                     }
265 
266                     Token subTok = cloneToken(tok);
267                     subTok.kind = VBScriptConstants.NL;
268                     subTok.image = "\n";
269                     return subTok;
270                 case AspParseConstants.LANGUAGEDEF:
271                     /* Skipped */
272                     return getNextToken();
273                 default:
274                     DebugContext ctx = new DebugContext();
275                     tok.fillDebugContext(ctx);
276                     throw new AspRuntimeException("Unknown token: " + tok.kind,
277                         ctx);
278             }
279         } catch (TokenMgrError e)
280         {
281             e.setFilename(fileInfo.filename);
282             throw e;
283         } catch (AspException ex)
284         {
285             DBG.debug("AspException thrown");
286             if (!ex.hasContext() && tok != null) {
287                 DebugContext ctx = new DebugContext();
288                 tok.fillDebugContext(ctx);
289                 ex.setContext(ctx);
290             }
291             throw new AspRuntimeSubException(ex);
292         }
293     }
294 
295     /**
296      * This function tests if the string contains only whitespace.
297      * @param str String to test for white space
298      * @return <b>true</b> if the string contains only whitespace, <b>false</b>
299      *      otherwise.
300      */
301     public boolean containsOnlyWS(String str)
302     {
303         for (int i = 0; i < str.length(); i++)
304         {
305             if (!Character.isWhitespace(str.charAt(i)))
306                 return false;
307         }
308         return true;
309     }
310 }
311