Source Code Cross Referenced for ScriptParser.java in  » Database-Client » SQL-Workbench » workbench » sql » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database Client » SQL Workbench » workbench.sql 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * ScriptParser.java
003:         *
004:         * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005:         *
006:         * Copyright 2002-2008, Thomas Kellerer
007:         * No part of this code maybe reused without the permission of the author
008:         *
009:         * To contact the author please send an email to: support@sql-workbench.net
010:         *
011:         */
012:        package workbench.sql;
013:
014:        import java.io.BufferedReader;
015:        import java.io.File;
016:        import java.io.FileNotFoundException;
017:        import java.io.IOException;
018:        import java.util.ArrayList;
019:        import java.util.Iterator;
020:        import java.util.NoSuchElementException;
021:        import workbench.log.LogMgr;
022:        import workbench.resource.Settings;
023:        import workbench.util.EncodingUtil;
024:        import workbench.util.FileUtil;
025:        import workbench.util.StringUtil;
026:
027:        /**
028:         * A class to parse a SQL script and return the individual commands
029:         * in the script. The actual parsing is done by using an instance
030:         * of {@link IteratingScriptParser}
031:         *
032:         * @author  support@sql-workbench.net
033:         */
034:        public class ScriptParser implements  Iterator {
035:
036:            private String originalScript = null;
037:            private ArrayList<ScriptCommandDefinition> commands = null;
038:            private DelimiterDefinition delimiter = DelimiterDefinition.STANDARD_DELIMITER;
039:            private DelimiterDefinition alternateDelimiter;
040:            private int currentIteratorIndex = -42;
041:            private boolean checkEscapedQuotes = true;
042:            private IteratingScriptParser iteratingParser = null;
043:            private boolean emptyLineIsSeparator = false;
044:            private boolean supportOracleInclude = true;
045:            private boolean checkSingleLineCommands = true;
046:            private boolean returnTrailingWhitesapce = false;
047:            private String alternateLineComment = "--";
048:            private boolean useAlternateDelimiter = false;
049:
050:            private int maxFileSize;
051:
052:            public ScriptParser() {
053:                this (Settings.getInstance().getInMemoryScriptSizeThreshold());
054:            }
055:
056:            /**
057:             *	Create a ScriptParser for the given Script.
058:             *	The delimiter to be used will be evaluated dynamically
059:             */
060:            public ScriptParser(String aScript) {
061:                this .setScript(aScript);
062:            }
063:
064:            /** Create a ScriptParser
065:             *
066:             *	The actual script needs to be specified with setScript()
067:             *  The delimiter will be evaluated dynamically
068:             */
069:            public ScriptParser(int fileSize) {
070:                maxFileSize = fileSize;
071:            }
072:
073:            /**
074:             *	Initialize a ScriptParser from a file.
075:             *	The delimiter will be evaluated dynamically
076:             */
077:            public ScriptParser(File f) throws IOException {
078:                this (f, null);
079:            }
080:
081:            /**
082:             *	Initialize a ScriptParser from a file.
083:             *	The delimiter will be evaluated dynamically
084:             */
085:            public ScriptParser(File f, String encoding) throws IOException {
086:                setFile(f, encoding);
087:            }
088:
089:            public void setFile(File f) throws IOException {
090:                setFile(f, null);
091:            }
092:
093:            /**
094:             * Define the source file for this ScriptParser.
095:             * Depending on the size the file might be read into memory or not
096:             */
097:            public void setFile(File f, String encoding) throws IOException {
098:                if (!f.exists())
099:                    throw new FileNotFoundException(f.getName() + " not found");
100:
101:                if (f.length() < this .maxFileSize) {
102:                    this .readScriptFromFile(f, encoding);
103:                    this .findDelimiterToUse();
104:                } else {
105:                    this .iteratingParser = new IteratingScriptParser(f,
106:                            encoding);
107:                    configureParserInstance(this .iteratingParser);
108:                }
109:            }
110:
111:            public void readScriptFromFile(File f) throws IOException {
112:                this .readScriptFromFile(f, null);
113:            }
114:
115:            public void readScriptFromFile(File f, String encoding)
116:                    throws IOException {
117:                BufferedReader in = null;
118:                StringBuilder content = null;
119:                try {
120:                    content = new StringBuilder((int) f.length());
121:                    in = EncodingUtil.createBufferedReader(f, encoding);
122:                    String line = in.readLine();
123:                    while (line != null) {
124:                        content.append(line);
125:                        content.append('\n');
126:                        line = in.readLine();
127:                    }
128:                } catch (Exception e) {
129:                    LogMgr.logError("ScriptParser.readFile()",
130:                            "Error reading file " + f.getAbsolutePath(), e);
131:                    content = null;
132:                } finally {
133:                    FileUtil.closeQuitely(in);
134:                }
135:                this .setScript(content == null ? "" : content.toString());
136:            }
137:
138:            public void allowEmptyLineAsSeparator(boolean flag) {
139:                this .emptyLineIsSeparator = flag;
140:            }
141:
142:            public void setAlternateLineComment(String comment) {
143:                this .alternateLineComment = comment;
144:            }
145:
146:            public void setReturnStartingWhitespace(boolean flag) {
147:                this .returnTrailingWhitesapce = flag;
148:            }
149:
150:            public void setCheckForSingleLineCommands(boolean flag) {
151:                this .checkSingleLineCommands = flag;
152:            }
153:
154:            public void setSupportOracleInclude(boolean flag) {
155:                this .supportOracleInclude = flag;
156:            }
157:
158:            /**
159:             *	Define the script to be parsed.
160:             *	The delimiter to be used will be checked automatically
161:             *	First the it will check if the script ends with the alternate delimiter
162:             *	if this is not the case, the script will be checked if it ends with GO
163:             *	If so, GO will be used (MS SQL Server script style)
164:             *	If none of the above is true, ; (semicolon) will be used
165:             */
166:            public void setScript(String aScript) {
167:                if (aScript == null)
168:                    throw new NullPointerException("SQL script may not be null");
169:                if (aScript.equals(this .originalScript))
170:                    return;
171:                this .originalScript = aScript;
172:                this .findDelimiterToUse();
173:                this .commands = null;
174:                this .iteratingParser = null;
175:            }
176:
177:            public void setDelimiter(DelimiterDefinition delim) {
178:                this .setDelimiters(delim, null);
179:            }
180:
181:            /**
182:             * Sets the alternate delimiter. This implies that 
183:             * by default the semicolon is used, and only if 
184:             * the alternate delimiter is detected, that will be used.
185:             * 
186:             * If only one delimiter should be used (and no automatic checking
187:             * for an alternate delimiter), use {@link #setDelimiter(DelimiterDefinition)}
188:             */
189:            public void setAlternateDelimiter(DelimiterDefinition alt) {
190:                setDelimiters(DelimiterDefinition.STANDARD_DELIMITER, alt);
191:            }
192:
193:            /**
194:             * Define the delimiters to be used. If the (in-memory) script ends with 
195:             * the defined alternate delimiter, then the alternate is used, otherwise
196:             * the default
197:             */
198:            public void setDelimiters(DelimiterDefinition defaultDelim,
199:                    DelimiterDefinition alternateDelim) {
200:                this .delimiter = defaultDelim;
201:                this .alternateDelimiter = alternateDelim;
202:
203:                if (this .originalScript != null) {
204:                    findDelimiterToUse();
205:                }
206:            }
207:
208:            /**
209:             *	Try to find out which delimiter should be used for the current script.
210:             *	First it will check if the script ends with the alternate delimiter
211:             *	if this is not the case, the script will be checked if it ends with GO
212:             *	If so, GO will be used (MS SQL Server script style)
213:             *	If none of the above is true, ; (semicolon) will be used
214:             */
215:            private void findDelimiterToUse() {
216:                if (this .alternateDelimiter == null)
217:                    return;
218:                if (this .originalScript == null)
219:                    return;
220:
221:                useAlternateDelimiter = (alternateDelimiter
222:                        .terminatesScript(originalScript));
223:                this .commands = null;
224:            }
225:
226:            /**
227:             * Return the index from the overall script mapped to the 
228:             * index inside the specified command. For a single command
229:             * script scriptCursorLocation will be the same as 
230:             * the location inside the dedicated command.
231:             * @param commandIndex the index for the command to check
232:             * @param cursorPos the index in the overall script
233:             * @return the relative index inside the command
234:             */
235:            public int getIndexInCommand(int commandIndex, int cursorPos) {
236:                if (this .commands == null)
237:                    this .parseCommands();
238:                if (commandIndex < 0 || commandIndex >= this .commands.size())
239:                    return -1;
240:                ScriptCommandDefinition b = this .commands.get(commandIndex);
241:                int start = b.getStartPositionInScript();
242:                int end = b.getEndPositionInScript();
243:                int relativePos = (cursorPos - start);
244:                int commandLength = (end - start);
245:                if (relativePos > commandLength) {
246:                    // This can happen when trimming the statements.
247:                    relativePos = commandLength;
248:                }
249:                return relativePos;
250:            }
251:
252:            /**
253:             *	Return the command index for the command which is located at
254:             *	the given index of the current script.
255:             */
256:            public int getCommandIndexAtCursorPos(int cursorPos) {
257:                if (this .commands == null)
258:                    this .parseCommands();
259:                if (cursorPos < 0)
260:                    return -1;
261:                int count = this .commands.size();
262:                if (count == 1)
263:                    return 0;
264:                if (count == 0)
265:                    return -1;
266:                for (int i = 0; i < count - 1; i++) {
267:                    ScriptCommandDefinition b = this .commands.get(i);
268:                    ScriptCommandDefinition next = this .commands.get(i + 1);
269:                    if (b.getWhitespaceStart() <= cursorPos
270:                            && b.getEndPositionInScript() >= cursorPos)
271:                        return i;
272:                    if (cursorPos > b.getEndPositionInScript()
273:                            && cursorPos < next.getEndPositionInScript())
274:                        return i + 1;
275:                    if (b.getEndPositionInScript() > cursorPos
276:                            && next.getWhitespaceStart() <= cursorPos)
277:                        return i + 1;
278:                }
279:                ScriptCommandDefinition b = this .commands.get(count - 1);
280:                if (b.getWhitespaceStart() <= cursorPos
281:                        && b.getEndPositionInScript() >= cursorPos)
282:                    return count - 1;
283:                return -1;
284:            }
285:
286:            /**
287:             *	Get the starting offset in the original script for the command indicated by index
288:             */
289:            public int getStartPosForCommand(int index) {
290:                if (this .commands == null)
291:                    this .parseCommands();
292:                if (index < 0 || index >= this .commands.size())
293:                    return -1;
294:                ScriptCommandDefinition b = this .commands.get(index);
295:                int start = b.getStartPositionInScript();
296:                return start;
297:            }
298:
299:            /**
300:             * Get the starting offset in the original script for the command indicated by index
301:             */
302:            public int getEndPosForCommand(int index) {
303:                if (this .commands == null)
304:                    this .parseCommands();
305:                if (index < 0 || index >= this .commands.size())
306:                    return -1;
307:                ScriptCommandDefinition b = this .commands.get(index);
308:                return b.getEndPositionInScript();
309:            }
310:
311:            /**
312:             * Find the position in the original script for the next start of line
313:             */
314:            public int findNextLineStart(int pos) {
315:                if (this .originalScript == null)
316:                    return -1;
317:                if (pos < 0)
318:                    return pos;
319:                int len = this .originalScript.length();
320:                if (pos >= len)
321:                    return pos;
322:                char c = this .originalScript.charAt(pos);
323:                while (pos < len && (c == '\n' || c == '\r')) {
324:                    pos++;
325:                    c = this .originalScript.charAt(pos);
326:                }
327:                return pos;
328:            }
329:
330:            /**
331:             * Return the command at the given index position.
332:             */
333:            public String getCommand(int index) {
334:                return getCommand(index, true);
335:            }
336:
337:            /**
338:             * Return the command at the given index position.
339:             */
340:            public String getCommand(int index, boolean rightTrimCommand) {
341:                if (this .commands == null)
342:                    this .parseCommands();
343:                if (index < 0 || index >= this .commands.size())
344:                    return null;
345:                ScriptCommandDefinition c = this .commands.get(index);
346:                String s = originalScript
347:                        .substring(c.getStartPositionInScript(), c
348:                                .getEndPositionInScript());
349:                if (rightTrimCommand)
350:                    return StringUtil.rtrim(s);
351:                else
352:                    return s;
353:            }
354:
355:            public int getSize() {
356:                if (this .commands == null)
357:                    this .parseCommands();
358:                return this .commands.size();
359:            }
360:
361:            /**
362:             * Return an Iterator which allows to iterate over 
363:             * the commands from the script. The Iterator
364:             * will return objects of type {@link ScriptCommandDefinition}
365:             */
366:            public Iterator getIterator() {
367:                startIterator();
368:                return this ;
369:            }
370:
371:            public void startIterator() {
372:                this .currentIteratorIndex = 0;
373:                if (this .iteratingParser == null && this .commands == null) {
374:                    this .parseCommands();
375:                } else if (this .iteratingParser != null) {
376:                    configureParserInstance(this .iteratingParser);
377:                    this .iteratingParser.reset();
378:
379:                }
380:            }
381:
382:            public void done() {
383:                if (this .iteratingParser != null) {
384:                    this .iteratingParser.done();
385:                }
386:                this .currentIteratorIndex = -42;
387:            }
388:
389:            /**
390:             * Check for quote characters that are escaped using a 
391:             * backslash. If turned on (flag == true) the following
392:             * SQL statement would be valid (different to the SQL standard):
393:             * <pre>INSERT INTO myTable (column1) VALUES ('Arthurs\'s house');</pre>
394:             * but the following Script would generate an error: 
395:             * <pre>INSERT INTO myTable (file_path) VALUES ('c:\');</pre>
396:             * because the last quote would not bee seen as a closing quote
397:             */
398:            public void setCheckEscapedQuotes(boolean flag) {
399:                this .checkEscapedQuotes = flag;
400:            }
401:
402:            public String getDelimiterString() {
403:                if (this .useAlternateDelimiter)
404:                    return this .alternateDelimiter.getDelimiter();
405:                return this .delimiter.getDelimiter();
406:            }
407:
408:            private void configureParserInstance(IteratingScriptParser p) {
409:                p.setSupportOracleInclude(this .supportOracleInclude);
410:                p.allowEmptyLineAsSeparator(this .emptyLineIsSeparator);
411:                p.setCheckEscapedQuotes(this .checkEscapedQuotes);
412:                p.setDelimiter(useAlternateDelimiter ? this .alternateDelimiter
413:                        : this .delimiter);
414:                p.setReturnStartingWhitespace(this .returnTrailingWhitesapce);
415:                p.setAlternateLineComment(this .alternateLineComment);
416:                p.setDelimiter(useAlternateDelimiter ? this .alternateDelimiter
417:                        : this .delimiter);
418:
419:                if (useAlternateDelimiter) {
420:                    p.setCheckForSingleLineCommands(false);
421:                } else {
422:                    p
423:                            .setCheckForSingleLineCommands(this .checkSingleLineCommands);
424:                }
425:            }
426:
427:            /**
428:             *	Parse the given SQL Script into a List of single SQL statements.
429:             */
430:            private void parseCommands() {
431:                this .commands = new ArrayList<ScriptCommandDefinition>();
432:                IteratingScriptParser p = new IteratingScriptParser();
433:                configureParserInstance(p);
434:                p.setScript(this .originalScript);
435:
436:                ScriptCommandDefinition c = null;
437:                int index = 0;
438:
439:                while ((c = p.getNextCommand()) != null) {
440:                    c.setIndexInScript(index);
441:                    index++;
442:                    this .commands.add(c);
443:                }
444:            }
445:
446:            /**
447:             *	Check if more commands are present. 
448:             */
449:            public boolean hasNext() {
450:                if (this .currentIteratorIndex == -42)
451:                    throw new IllegalStateException("Iterator not initialized");
452:                if (this .iteratingParser != null) {
453:                    return this .iteratingParser.hasMoreCommands();
454:                } else {
455:                    return this .currentIteratorIndex < this .commands.size();
456:                }
457:            }
458:
459:            /**
460:             * Return the next SQL command from the script. 
461:             * This is delegated to {@link #getNextCommand()}
462:             * @return a String object representing the SQL command
463:             * @throws IllegalStateException if the Iterator has not been initialized using {@link #getIterator()}
464:             * @see IteratingScriptParser#getNextCommand()
465:             * @see #getNextCommand()
466:             */
467:            public Object next() throws NoSuchElementException {
468:                if (this .currentIteratorIndex == -42)
469:                    throw new NoSuchElementException("Iterator not initialized");
470:                return getNextCommand();
471:            }
472:
473:            /**
474:             * Return the next {@link ScriptCommandDefinition} from the script. 
475:             * 
476:             * @throws IllegalStateException if the Iterator has not been initialized using {@link #getIterator()}
477:             * @see IteratingScriptParser#getNextCommand()
478:             * @see #next()
479:             */
480:            public String getNextCommand() throws NoSuchElementException {
481:                if (this .currentIteratorIndex == -42)
482:                    throw new NoSuchElementException("Iterator not initialized");
483:                ScriptCommandDefinition command = null;
484:                String result = null;
485:                if (this .iteratingParser != null) {
486:                    command = this .iteratingParser.getNextCommand();
487:                    if (command == null)
488:                        return null;
489:                    result = command.getSQL();
490:                } else {
491:                    command = this .commands.get(this .currentIteratorIndex);
492:                    result = this .originalScript.substring(command
493:                            .getStartPositionInScript(), command
494:                            .getEndPositionInScript());
495:                    this .currentIteratorIndex++;
496:                }
497:
498:                return result;
499:            }
500:
501:            /**
502:             * Not implemented, as removing commands is not possible.
503:             * A call to this method simply does nothing.
504:             */
505:            public void remove() {
506:            }
507:
508:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.