1 /***
2 * Copyright 2007 ATG DUST Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and limitations under the License.
13 */
14
15 package atg.adapter.gsa;
16
17 import java.io.BufferedReader;
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.InputStreamReader;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import org.apache.log4j.Logger;
28
29 /***
30 * THIS IS A REALLY SIMPLE APPLICATION THAT
31 * TAKES A STRING ARRAY OF SQL FILES AND
32 * RETURNS ALL OF THE SQL STATEMENTS THAT
33 * MUST BE EXECUTED WITHIN THE FILES
34 * DATE: MAY 23, 2000
35 *
36 *
37 * @author jb
38 * 7/14/2002
39 */
40 public class SQLFileParser
41 {
42
43 private static Logger log = Logger.getLogger(SQLFileParser.class);
44
45
46
47
48
49
50
51 private String[] sFileNameArray = {""};
52 /*** sets the names of files to be parsed */
53 private void setFileNameArray(String[] pFileNameArray)
54 {
55 sFileNameArray = pFileNameArray;
56 }
57
58 /*** returns the names of files to be parsed */
59
60
61
62
63
64
65 /***
66 * no arg constructor
67 */
68 public SQLFileParser() {}
69
70
71
72
73 private String trimDebuggingCharacters(String sText)
74 {
75 if ( sText == null ) return sText;
76 return sText.trim();
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 }
103
104 private String RemoveWhiteSpaceInFront (String sText)
105 {
106
107
108
109
110 char[] ch = new char [sText.length()];
111 ch = sText.toCharArray();
112
113 for (int i=0; i < sText.length(); i++)
114 {
115 if ((ch[i] == '\n') || (ch[i] == '\r') || (ch[i] == '\t')|| (ch[i] == ' ') || (ch[i] == ' '))
116 {
117
118 }
119 else
120 {
121 return (sText.substring (i, sText.length()));
122 }
123 }
124 return (sText);
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 private String RemoveWhiteSpaceFromString (String sText)
151 {
152 if ( sText == null ) return null;
153 return sText.trim();
154
155
156
157
158
159
160
161
162
163
164 }
165
166
167 private int countFileArraySize(String[] sArray)
168 {
169
170
171
172
173
174
175
176
177
178
179
180 List<String> newList = Arrays.asList(sArray);
181 return (newList.size());
182 }
183
184 private boolean checkForKeywords (String sLineRead)
185 {
186
187
188
189
190
191
192
193
194
195
196
197 String[] sKeywordList = {"BEGIN ", "CREATE ", "INSERT ", "UPDATE ", "DELETE ", "COMMIT ", "COMMIT", "ALTER ", "DROP ", "GRANT ", "GO", "IF OBJECT_ID"};
198 List<String> lList = Arrays.asList(sKeywordList);
199 int iArraySize = lList.size();
200
201 sLineRead = RemoveWhiteSpaceInFront(sLineRead);
202
203
204
205 for (int i=0; i< iArraySize; i++)
206 {
207 if (sLineRead.toUpperCase().startsWith(sKeywordList[i].toUpperCase()) )
208 {
209
210
211
212
213
214 if ( sLineRead.length() == sKeywordList[i].trim().length() ) {
215
216 return true;
217 } else if ( sLineRead.charAt( sKeywordList[i].trim().length() ) == ' ' ) {
218
219 return true;
220 } else if ( sLineRead.charAt( sKeywordList[i].trim().length() ) == '(' ) {
221
222 return true;
223 }
224 }
225 }
226 return (false);
227 }
228
229 private String checkForComments(String sLineRead)
230 {
231
232
233
234
235
236
237
238
239
240 String[] sKeywordList = {"--", "//"};
241 List<String> lList = Arrays.asList(sKeywordList);
242 int iArraySize = lList.size();
243
244
245 for (int i=0; i< iArraySize; i++)
246 {
247 if (sLineRead.toUpperCase().indexOf(sKeywordList[i]) > -1)
248 {
249 return (sLineRead.substring(0,sLineRead.indexOf(sKeywordList[i])));
250 }
251 }
252 return (sLineRead);
253 }
254
255 private String checkForSemiColons(String sCurrentLine)
256 {
257
258
259
260
261
262
263
264
265 if (sCurrentLine.indexOf(";") > -1)
266 {
267 sCurrentLine = sCurrentLine.substring (0, sCurrentLine.indexOf(";"));
268 }
269 return (sCurrentLine);
270
271 }
272
273 private String checkForEndLines(String sCurrentLine)
274 {
275
276
277
278
279
280
281
282
283
284
285 sCurrentLine = RemoveWhiteSpaceFromString(sCurrentLine);
286 int iLength = sCurrentLine.length() -2;
287
288 if ((sCurrentLine.indexOf("/") > -1) && (sCurrentLine.indexOf("/") >= iLength))
289 {
290 sCurrentLine = sCurrentLine.substring (0, sCurrentLine.indexOf("/"));
291 }
292 else if ((sCurrentLine.indexOf("/") > -1) && (sCurrentLine.indexOf("/") == 0))
293 {
294 sCurrentLine = "";
295 }
296
297 sCurrentLine = sCurrentLine + " ";
298 return (sCurrentLine);
299 }
300
301
302
303 private List<String> readFileAndLoadData ()
304 {
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 String sFileName = "";
330 String line = "";
331 String lineTemp = "";
332 String sSqlBuffer = "";
333
334
335 boolean bKeywordAlreadyFound = false;
336 boolean bKeywordInString = false;
337
338 List<String> vSql = new ArrayList<String>();
339
340 BufferedReader in = null;
341
342 File fFile = null;
343 FileInputStream fis = null;
344
345 InputStreamReader Fin = null;
346
347
348
349 int iSizeOfVector = countFileArraySize(sFileNameArray);
350
351
352
353
354
355 for (int iFile = 0; iFile < iSizeOfVector; iFile++)
356 {
357
358
359 sFileName = sFileNameArray[iFile];
360
361 try
362 {
363
364 fFile = new File (sFileName);
365 fis = new FileInputStream(fFile);
366 Fin = new InputStreamReader(fis);
367 in = new BufferedReader(Fin);
368
369
370 }
371 catch (Exception e)
372 {
373
374 return (vSql);
375 }
376
377
378 try
379 {
380
381 sSqlBuffer = "";
382
383 line = in.readLine();
384
385 lineTemp = line;
386
387 while (line != null)
388 {
389
390
391 lineTemp = line;
392 lineTemp = checkForComments(lineTemp);
393 bKeywordInString = checkForKeywords(lineTemp);
394
395
396
397
398 if ( bKeywordInString && isStartOfStoredProcedure( lineTemp ) ) {
399
400 String command = parseStoredProcedure( lineTemp, in );
401 vSql.add( command );
402 line = in.readLine();
403 continue;
404 }
405
406
407
408 if ( bKeywordInString && isStartOfIfExistsCommand( lineTemp ) ) {
409 String command = parseIfExistsCommand( lineTemp, in );
410 vSql.add( command );
411 line = in.readLine();
412 continue;
413 }
414
415 if (bKeywordAlreadyFound)
416 {
417 if (bKeywordInString)
418 {
419 sSqlBuffer = checkForSemiColons(sSqlBuffer);
420 sSqlBuffer = checkForEndLines(sSqlBuffer);
421 vSql.add(sSqlBuffer);
422 sSqlBuffer = lineTemp;
423 }
424 else
425 {
426 sSqlBuffer = sSqlBuffer + " " + lineTemp;
427 }
428 }
429 else
430 {
431 if (bKeywordInString)
432 {
433 bKeywordAlreadyFound = bKeywordInString;
434 sSqlBuffer = sSqlBuffer + lineTemp;
435 }
436 }
437
438
439 line = in.readLine();
440 }
441
442 try
443 {
444 sSqlBuffer = checkForSemiColons(sSqlBuffer);
445 sSqlBuffer = checkForEndLines(sSqlBuffer);
446 vSql.add(sSqlBuffer);
447 }
448 catch (Exception ex)
449 {
450
451
452 }
453
454 }
455 catch (Exception e)
456 {
457
458 return (vSql);
459 }
460
461 try
462 {
463 Fin.close();
464 fis.close();
465
466 }
467 catch (Exception ex)
468 {
469
470 return (vSql);
471 }
472 }
473 return (vSql);
474 }
475
476 /*** this method returns true if this line is the start of a check for whether an object exists
477 * in MS SQL Server. otherwise it returns false.
478 */
479 private boolean isStartOfIfExistsCommand( String pLine ) {
480
481 return pLine.trim().toUpperCase().startsWith("IF OBJECT_ID");
482 }
483
484 /*** used to parse an if-exists method. the parsing logic is different than our usual behavior
485 * so it has been special cased.
486 * @return String the parsed SQL command
487 * @exception Exception if an error occurs
488 */
489 private String parseIfExistsCommand( String pCommand, BufferedReader pIn )
490 throws Exception
491 {
492
493 String line = pIn.readLine();
494 if ( line != null ) line = line.trim();
495 while ( line != null && (! line.toUpperCase().startsWith("GO")) )
496 {
497 pCommand = pCommand + " " + line;
498 line = pIn.readLine();
499 if ( line != null ) line = line.trim();
500 }
501
502 return pCommand;
503 }
504
505 /*** this method returns true if this line is the start of a definition for a stored procedure.
506 * otherwise, it returns false.
507 */
508 private boolean isStartOfStoredProcedure( String pLine ) {
509
510
511 return pLine.trim().toUpperCase().startsWith( "CREATE OR REPLACE PROCEDURE" );
512 }
513
514 /*** this method is used to parse a stored procedure. since stored procedures may contain
515 * sub-commands within them, we use a special process to parse them.
516 *
517 * @return String the parsed SQL command
518 * @exception Exception if an error occurs
519 */
520 private String parseStoredProcedure( String pCommand, BufferedReader pIn )
521 throws Exception
522 {
523
524
525 String line = pIn.readLine();
526 if ( line != null ) line = line.trim();
527 while ( line != null && (! line.startsWith("/")) )
528 {
529 pCommand = pCommand + " " + line;
530 line = pIn.readLine();
531 if ( line != null ) line = line.trim();
532 }
533
534 return pCommand;
535 }
536
537
538 public synchronized Collection<String> parseSQLFiles( String[] pFiles )
539 {
540 setFileNameArray( pFiles );
541
542
543
544
545
546
547
548 List<String> v = new ArrayList<String>();
549 v = readFileAndLoadData();
550 String s = "";
551 for (int i=0;i<v.size();i++)
552 {
553 s = v.get(i).toString();
554 s = trimDebuggingCharacters (s);
555
556 if ( logToSystemOut ) {
557
558 } else {
559
560 }
561 }
562
563 return v;
564 }
565
566 public Collection<String> parseSQLFile( String pFile )
567 {
568 String[] files = { pFile };
569 return parseSQLFiles( files );
570 }
571
572
573 public boolean logToSystemOut = false;
574 public static void main (String[] args)
575 {
576 SQLFileParser t = new SQLFileParser();
577 t.logToSystemOut = true;
578 Iterator<String> cmds = t.parseSQLFiles( args ).iterator();
579 while ( cmds.hasNext() ) {
580 log.info("\n\n" + cmds.next() );
581 }
582 }
583
584
585
586 }
587