View Javadoc

1   package org.apache.torque.engine.sql;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.IOException;
20  import java.io.Reader;
21  import java.util.List;
22  import java.util.ArrayList;
23  
24  /***
25   * A simple Scanner implementation that scans an
26   * sql file into usable tokens.  Used by SQLToAppData.
27   *
28   * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
29   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
30   * @author <a href="mailto:andyhot@di.uoa.gr">Andreas Andreou</a>
31   * @version $Id: SQLScanner.java 239624 2005-08-24 12:18:03Z henning $
32   */
33  public class SQLScanner
34  {
35      /*** white spaces */
36      private static final String WHITE = "\f\r\t\n ";
37      /*** alphabetic characters */
38      private static final String ALFA
39              = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
40      /*** numbers */
41      private static final String NUMER = "0123456789";
42      /*** alphanumeric */
43      private static final String ALFANUM = ALFA + NUMER;
44      /*** special characters */
45      private static final String SPECIAL = ";(),'";
46      /*** comment */
47      private static final char COMMENT_POUND = '#';
48      /*** comment */
49      private static final char COMMENT_SLASH = '/';
50      /*** comment */
51      private static final char COMMENT_STAR = '*';
52      /*** comment */
53      private static final char COMMENT_DASH = '-';
54  
55      /*** the input reader */
56      private Reader in;
57      /*** character */
58      private int chr;
59      /*** token */
60      private String token;
61      /*** list of tokens */
62      private List tokens;
63      /*** line */
64      private int line;
65      /*** column */
66      private int col;
67  
68      /***
69       * Creates a new scanner with no Reader
70       */
71      public SQLScanner()
72      {
73          this(null);
74      }
75  
76      /***
77       * Creates a new scanner with an Input Reader
78       *
79       * @param input the input reader
80       */
81      public SQLScanner(Reader input)
82      {
83          setInput(input);
84      }
85  
86      /***
87       * Set the Input
88       *
89       * @param input the input reader
90       */
91      public void setInput(Reader input)
92      {
93          in = input;
94      }
95  
96  
97      /***
98       * Reads the next character and increments the line and column counters.
99       *
100      * @throws IOException If an I/O error occurs
101      */
102     private void readChar() throws IOException
103     {
104         boolean wasLine = (char) chr == '\r';
105         chr = in.read();
106         if ((char) chr == '\n' || (char) chr == '\r' || (char) chr == '\f')
107         {
108             col = 0;
109             if (!wasLine || (char) chr != '\n')
110             {
111                 line++;
112             }
113         }
114         else
115         {
116             col++;
117         }
118     }
119 
120     /***
121      * Scans an identifier.
122      *
123      * @throws IOException If an I/O error occurs
124      */
125     private void scanIdentifier () throws IOException
126     {
127         token = "";
128         char c = (char) chr;
129         while (chr != -1 && WHITE.indexOf(c) == -1 && SPECIAL.indexOf(c) == -1)
130         {
131             token = token + (char) chr;
132             readChar();
133             c = (char) chr;
134         }
135         int start = col - token.length();
136         tokens.add(new Token(token, line, start));
137     }
138 
139     /***
140      * Scans an identifier which had started with the negative sign.
141      *
142      * @throws IOException If an I/O error occurs
143      */
144     private void scanNegativeIdentifier () throws IOException
145     {
146         token = "-";
147         char c = (char) chr;
148         while (chr != -1 && WHITE.indexOf(c) == -1 && SPECIAL.indexOf(c) == -1)
149         {
150             token = token + (char) chr;
151             readChar();
152             c = (char) chr;
153         }
154         int start = col - token.length();
155         tokens.add(new Token(token, line, start));
156     }
157 
158     /***
159      * Scan the input Reader and returns a list of tokens.
160      *
161      * @return a list of tokens
162      * @throws IOException If an I/O error occurs
163      */
164     public List scan () throws IOException
165     {
166         line = 1;
167         col = 0;
168         boolean inComment = false;
169         boolean inCommentSlashStar = false;
170         boolean inCommentDash = false;
171 
172         boolean inNegative;
173 
174         tokens = new ArrayList();
175         readChar();
176         while (chr != -1)
177         {
178             char c = (char) chr;
179             inNegative = false;
180 
181             if (c == COMMENT_DASH)
182             {
183                 readChar();
184                 if ((char) chr == COMMENT_DASH)
185                 {
186                     inCommentDash = true;
187                 }
188                 else
189                 {
190                     inNegative = true;
191                     c = (char) chr;
192                 }
193             }
194 
195             if (inCommentDash)
196             {
197                 if (c == '\n' || c == '\r')
198                 {
199                     inCommentDash = false;
200                 }
201                 readChar();
202             }
203             else if (c == COMMENT_POUND)
204             {
205                 inComment = true;
206                 readChar();
207             }
208             else if (c == COMMENT_SLASH)
209             {
210                 readChar();
211                 if ((char) chr == COMMENT_STAR)
212                 {
213                     inCommentSlashStar = true;
214                 }
215             }
216             else if (inComment || inCommentSlashStar)
217             {
218                 if (c == '*')
219                 {
220                     readChar();
221                     if ((char) chr == COMMENT_SLASH)
222                     {
223                         inCommentSlashStar = false;
224                     }
225                 }
226                 else if (c == '\n' || c == '\r')
227                 {
228                     inComment = false;
229                 }
230                 readChar();
231             }
232             else if (ALFANUM.indexOf(c) >= 0)
233             {
234                 if (inNegative)
235                 {
236                     scanNegativeIdentifier();
237                 }
238                 else
239                 {
240                     scanIdentifier();
241                 }
242             }
243             else if (SPECIAL.indexOf(c) >= 0)
244             {
245                 tokens.add(new Token("" + c, line, col));
246                 readChar();
247             }
248             else
249             {
250                 readChar();
251             }
252         }
253         return tokens;
254     }
255 }