View Javadoc

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