All Downloads are FREE. Search and download functionalities are using the official Maven repository.

atg.adapter.gsa.SQLFileParser Maven / Gradle / Ivy

Go to download

ATG DUST is a framework for building JUnit tests for applications built on the ATG Dynamo platform. This framework allows one to quickly write test code that depends up Nucleus or ATG Repositories. By using this framework one can drastically cut down on development time. It takes only a few seconds to start up a test with a repository, but it may take multiple minutes to start up an application server. To get started with DUST, take a look at http://atgdust.sourceforge.net/first-test.html. This page will walk you through the process of running a basic test which starts Nucleus. After that, read the other getting started guides to describe how to create standalone Junit tests which can startup repositories and use the DynamoHttpServletResponse classes. For only ATG10 and tested.

The newest version!
/**
 * Copyright 2007 ATG DUST Project
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and limitations under the License.
 */

package atg.adapter.gsa;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

/**
* THIS IS A REALLY SIMPLE APPLICATION THAT
* TAKES A STRING ARRAY OF SQL FILES AND
* RETURNS ALL OF THE SQL STATEMENTS THAT
* MUST BE EXECUTED WITHIN THE FILES
* DATE: MAY 23, 2000
* 
*
* @author jb
* 7/14/2002
*/
public class SQLFileParser
{
  
  private static Logger log = Logger.getLogger(SQLFileParser.class);

// ****************************************
// THERE IS ONLY ONE CLASS VARIABLE
// FOR THIS CLASS.  THAT VARIABLE IS TO
// STORE THE FILE NAMES.
// ****************************************

    private String[] sFileNameArray = {""};
    /** sets the names of files to be parsed */
    private void setFileNameArray(String[] pFileNameArray)
    {
            sFileNameArray = pFileNameArray;
    }
    
//    /** returns the names of files to be parsed */
//    private String[] getFileNameArray()
//    {
//            return (sFileNameArray);
//    }

// ============== CONSTRUCTORS =================
      /**
      * no arg constructor
      */
      public SQLFileParser() {}

// ================= PUBLIC METHODS =================


	private String trimDebuggingCharacters(String sText)
	{
            if ( sText == null ) return sText;
            return sText.trim();
            /*
		char[] ch = new char [sText.length()];
		ch = sText.toCharArray();
		String sTemp = "";
		for (int i=0; i < sText.length(); i++)
		{
			if ((ch[i] == '\n') || (ch[i] == '\r') || (ch[i] == '\t') || (ch[i] == '	'))
			{
				// Keep going
				sTemp = sTemp + " ";
			}
			else
			{
				sTemp = sTemp + ch[i];
			}
		}
		if (sTemp.length() > DEBUGGING_LENGTH)
		{
			return (sTemp.substring(0,DEBUGGING_LENGTH));
		}
		else
		{
			return (sTemp);
		}
              */
	}

	private  String RemoveWhiteSpaceInFront (String sText)
	{
// **********************************************************************************
//  THIS FUNCTION REMOVES WHITESPACE IN THE FRONT OF A STRING. FOR INSTANCE
//  IF A STRING IS PASSED TO IT AS '   SPACE', THEN IT WILL RETURN 'SPACE.
// **********************************************************************************
		char[] ch = new char [sText.length()];
		ch = sText.toCharArray();
		//String sTemp;
		for (int i=0; i < sText.length(); i++)
		{
			if ((ch[i] == '\n') || (ch[i] == '\r') || (ch[i] == '\t')|| (ch[i] == ' ') || (ch[i] == '	'))
			{
				// Keep going
			}
			else
			{
				return (sText.substring (i, sText.length()));
			}
		}
		return (sText);
	}

//	private  String RemoveWhiteSpaceInEnd (String sText)
//	{
//// **********************************************************************************
////  THIS FUNCTION REMOVES WHITESPACE IN THE END OF A STRING. FOR INSTANCE
////  IF A STRING IS PASSED TO IT AS 'SPACE   ', THEN IT WILL RETURN 'SPACE.
//// **********************************************************************************
//		char[] ch = new char [sText.length()];
//		ch = sText.toCharArray();
//		String sTemp;
//		for (int i= sText.length() - 1; i > 0; i--)
//		{
//			if ((ch[i] == '\n') || (ch[i] == '\r') || (ch[i] == '\t')|| (ch[i] == ' ') || (ch[i] == '	'))
//			{
//				// Keep going
//			}
//			else
//			{
//				return (sText.substring (0, i +1));
//			}
//		}
//		return (sText);
//	}

	private  String RemoveWhiteSpaceFromString (String sText)
	{
            if ( sText == null ) return null;
            return sText.trim();

// **********************************************************************************
//  THIS FUNCTION REMOVES WHITESPACE IN THE FRONT AND END OF A STRING. FOR INSTANCE
//  IF A STRING IS PASSED TO IT AS '   SPACE   ', THEN IT WILL RETURN 'SPACE.
// **********************************************************************************
/*
		sText = RemoveWhiteSpaceInFront (sText);
		sText = RemoveWhiteSpaceInEnd (sText);
		return (sText);
*/
	}


	private int countFileArraySize(String[] sArray)
	{

// ****************************************
// THIS IS A USEFUL FUNCTION TO
// COUNT THE SIZE OF AN ARRAY. IT
// TAKES AN ARRAY AS A PARAMETER
// AND IT RETURNS AN INTEGER AS
// THE COUNT.  IN THIS CASE WE
// DO NOT NEED TO PASS THE ARRAY
// SINCE IT IS A CLASS VARIABLE
// ****************************************

		List newList = Arrays.asList(sArray);
		return (newList.size());
	}

	private boolean checkForKeywords (String sLineRead)
	{

// ****************************************
// THIS IS ONE OF THE MOST CRITICAL
// FUNCTIONS IN THIS PROGRAM.  IT
// TAKES THE RESERVED WORDS FROM
// SQL INSTALL SCRIPTS AND RESERVES
// THEM WITHIN THIS APPLICATION.
// EACH WORD LISTED BELOW STARTS
// A SQL STATEMENT.
// ****************************************

		String[] sKeywordList = {"BEGIN ", "CREATE ", "INSERT ", "UPDATE ", "DELETE ", "COMMIT ", "COMMIT", "ALTER ", "DROP ", "GRANT ", "GO", "IF OBJECT_ID"};
		List lList = Arrays.asList(sKeywordList);
		int iArraySize = lList.size();

		sLineRead = RemoveWhiteSpaceInFront(sLineRead);
                //sLineRead = sLineRead.trim();
                // something about using trim() doesn't work with the overall logic of the program.

		for (int i=0; i< iArraySize; i++)
		{
			if (sLineRead.toUpperCase().startsWith(sKeywordList[i].toUpperCase()) )
			{
                            // we need to check more than just whether the line starts
                            // with the keyword.  we also have to try to determine that
                            // the keyword we found is actually NOT just the beginning of a
                            // bigger word.  for example, GOogle.
                            // so...
                            if ( sLineRead.length() == sKeywordList[i].trim().length() ) {
                                // if the whole line is just the keyword...
				return true;
                            } else if ( sLineRead.charAt( sKeywordList[i].trim().length() ) == ' ' ) {
                                // if the char after the word is a space
                                return true;
                            } else if ( sLineRead.charAt( sKeywordList[i].trim().length() ) == '(' ) {
                                // if the char after the word is a right paren "("
                                return true;
                            }
			}
		}
		return (false);
	}

	private String checkForComments(String sLineRead)
	{

// ****************************************
// THIS FUNCTION HAS ONE DUTY.  IT CHECKS
// FOR LINES IN  SQL SCRIPT THAT HAVE
// COMMENTS IN THEM.  IF IT FINDS A LINE
// IN A SQL SCRIPT THAT WOULD BE RESERVED
// FOR A COMMENT IT WILL SKIP THAT LINE.
// ****************************************

		String[] sKeywordList = {"--", "//"};
		List lList = Arrays.asList(sKeywordList);
		int iArraySize = lList.size();

		//sLineRead = sLineRead;
		for (int i=0; i< iArraySize; i++)
		{
			if (sLineRead.toUpperCase().indexOf(sKeywordList[i]) > -1)
			{
				return (sLineRead.substring(0,sLineRead.indexOf(sKeywordList[i])));
			}
		}
		return (sLineRead);
	}

	private String checkForSemiColons(String sCurrentLine)
	{

// ****************************************
// THIS FUNCTION HAS ONE DUTY.  IT CHECKS
// FOR SQL STATEMENTS THAT END IN THE
// SEMICOLON PUNCTUATION AND REMOVES
// THE SEMICOLON.
// ****************************************

		if (sCurrentLine.indexOf(";") > -1)
		{
			sCurrentLine = sCurrentLine.substring (0, sCurrentLine.indexOf(";"));
		}
		return (sCurrentLine);

	}

	private String checkForEndLines(String sCurrentLine)
	{

// ****************************************
// THIS FUNCTION HAS ONE DUTY.  IT CHECKS
// FOR SQL STATEMENTS THAT END IN THE
// SEMICOLON PUNCTUATION AND REMOVES
// THE SEMICOLON.  Sometimes if there
// is division in a view that is created
// the end line will be used, and sometimes
// it is used to execute a statement.
// ****************************************
		sCurrentLine = RemoveWhiteSpaceFromString(sCurrentLine);
		int iLength = sCurrentLine.length() -2;
		//int iIndex = sCurrentLine.indexOf("/");
		if ((sCurrentLine.indexOf("/") > -1) && (sCurrentLine.indexOf("/") >= iLength))
		{
			sCurrentLine = sCurrentLine.substring (0, sCurrentLine.indexOf("/"));
		}
		else if ((sCurrentLine.indexOf("/") > -1) && (sCurrentLine.indexOf("/") == 0))
		{
			sCurrentLine = "";
		}

		sCurrentLine = sCurrentLine + " ";
		return (sCurrentLine);
	}



	private List readFileAndLoadData ()
	{

// ****************************************
// THIS FUNCTION IS THE ENGINE FOR THIS
// APPLICATION. THIS FUNCTION OPENS
// THE FIRST FILE FROM THE FILE ARRAY
// LIST.  THEN IT READS THROUGH THE
// FILE LINE BY LINE BUILDING A VECTOR
// OF SQL SCRIPT COMMANDS.  WHEN IT IS
// DONE PROCESSING IT PASSES A NEAT
// VECTOR OF SQL COMMANDS TO THE
// PROGRAM THAT CALLED THIS FUNCTION
// ****************************************
// THIS PARTICULAR METHOD IS LONG AND
// TERRIBLE TO READ BECAUSE IT WAS WRITTEN
// IN ONE SITTING. AND SINCE IT SEEMED
// LIKE THE TYPE OF FUNCTION THAT LOOKS
// SO BAD TO A CODE REVIEWER, BY LEAVING
// IT IN THE CODE IT PROVIDES GOOD
// HUMOR RELIEF FOR THE DEVELOPER GIVING
// A CODE REVIEW TO THIS PROGRAM.
// ****************************************

// ****************************************
// VARIABLE DECLARATIONS
		String sFileName = "";
		String line = "";
		String lineTemp = "";
		String sSqlBuffer = "";
		//String sFindSemiColon = "";

		boolean bKeywordAlreadyFound = false;
		boolean bKeywordInString = false;

		List vSql = new ArrayList();

		BufferedReader in = null;

		File fFile = null;
		FileInputStream fis = null;

		InputStreamReader Fin = null;

		//Object obj = null;

		int iSizeOfVector = countFileArraySize(sFileNameArray);
// END VARIABLE DECLARATIONS
// ****************************************

// ****************************************
// LOOPING THROUGH THE VECTOR OF FILE NAMES
		for (int iFile = 0; iFile < iSizeOfVector; iFile++)
		{

		// GETTING THE FIRST FILE NAME FROM THE VECTOR
			sFileName = sFileNameArray[iFile];

			try // Try to open the file
			{
				//File fFile = new File (sDirectory, sFilename);
				fFile = new File (sFileName);
				fis = new FileInputStream(fFile);
				Fin = new InputStreamReader(fis);
				in = new BufferedReader(Fin);

				//if (isLoggingDebug()) logDebug ("Able to open file: " + sFileName);
			}
			catch (Exception e)
			{
			//	logError("* Error opening file :" + sFileName + ": *");
				return (vSql);
			} // Unable to open the file


			try // Try to read the file line by line
			{
				//String sSqlStatement = "";
				sSqlBuffer = "";
				// Open file and read first line
				line = in.readLine();

				lineTemp = line;

				while (line != null) // It is not the end of the file, LOOK FOR KEY WORDS
				{
					//log.info ("DEBUG:" + line);

					lineTemp = line;
					lineTemp = checkForComments(lineTemp);
					bKeywordInString = checkForKeywords(lineTemp);

					// if this line is starting a stored procedure declaration, parse it
					// specially. added this block to correctly parse stored procedures in oracle.
					// marty - 7/11/2002
					if ( bKeywordInString && isStartOfStoredProcedure( lineTemp ) ) {

						String command = parseStoredProcedure( lineTemp, in );
						vSql.add( command );
						line = in.readLine();
						continue;
					}

                                        // if this line is starting an 'if exists...' statement for MS SQL Server, parse
                                        // if specially.  added to work around bug 64622
                                        if ( bKeywordInString && isStartOfIfExistsCommand( lineTemp ) ) {
                                                String command = parseIfExistsCommand( lineTemp, in );
                                                vSql.add( command );
                                                line = in.readLine();
                                                continue;
                                        }

					if (bKeywordAlreadyFound)
					{
						if (bKeywordInString)
						{
							sSqlBuffer = checkForSemiColons(sSqlBuffer);
							sSqlBuffer = checkForEndLines(sSqlBuffer);
							vSql.add(sSqlBuffer);
							sSqlBuffer = lineTemp;
						}
						else // (!bKeywordInString}
						{
							sSqlBuffer = sSqlBuffer + " " + lineTemp;
						}
					}
					else
					{
						if (bKeywordInString)
						{
							bKeywordAlreadyFound = bKeywordInString;
							sSqlBuffer = sSqlBuffer + lineTemp;
						}
					}

					//Get the next line
					line = in.readLine();
				} // End while

				try
				{
					sSqlBuffer = checkForSemiColons(sSqlBuffer);
					sSqlBuffer = checkForEndLines(sSqlBuffer);
					vSql.add(sSqlBuffer);
				}
				catch (Exception ex)
				{
					//logError ("No element to add" + ex);

				}

			}
			catch (Exception e)
			{
				//logError("Could not read one line in file: " + sFileName + "\n");
				return (vSql);
			} // Unable to read one of the lines in the file

			try // To close the file streams
			{
				Fin.close();
				fis.close();
				//fFile.close();
			}
			catch (Exception ex)
			{
				//logError ("Unable to close files\n");
				return (vSql);
			} // If the files could not be closed
		}
		return (vSql);
	}

        /** this method returns true if this line is the start of a check for whether an object exists
         *  in MS SQL Server.  otherwise it returns false.
         */
        private boolean isStartOfIfExistsCommand( String pLine ) {
            // i think this is only on MS SQL Server.  hard-coding the logic.
            return pLine.trim().toUpperCase().startsWith("IF OBJECT_ID");
        }

        /** used to parse an if-exists method.  the parsing logic is different than our usual behavior
         *  so it has been special cased.
	 *  @return String the parsed SQL command
	 *  @exception Exception if an error occurs
         */
        private String parseIfExistsCommand( String pCommand, BufferedReader pIn )
            throws Exception
        {
		// a pretty big hack, but just parse until we find the next "go"
		String line = pIn.readLine();
		if ( line != null ) line = line.trim();
 		while ( line != null && (! line.toUpperCase().startsWith("GO")) )
 		{
			pCommand = pCommand + " " + line;
			line = pIn.readLine();
			if ( line != null ) line = line.trim();
		}

		return pCommand;
        }

	/** this method returns true if this line is the start of a definition for a stored procedure.
	 *  otherwise, it returns false.
	 */
	 private boolean isStartOfStoredProcedure( String pLine ) {
		 // i only know of this on oracle, so i'm temporarily coding it to work specifically
		 // with oracle.
		 return pLine.trim().toUpperCase().startsWith( "CREATE OR REPLACE PROCEDURE" );
	 }

	/** this method is used to parse a stored procedure.  since stored procedures may contain
	 *  sub-commands within them, we use a special process to parse them.
	 *
	 *  @return String the parsed SQL command
	 *  @exception Exception if an error occurs
	 */
	private String parseStoredProcedure( String pCommand, BufferedReader pIn )
		throws Exception
	{
		// this is pretty much a total hack, but i just want to get it working for now
		// ASSUME we just parse until we find a line that starts with "/"
		String line = pIn.readLine();
		if ( line != null ) line = line.trim();
 		while ( line != null && (! line.startsWith("/")) )
 		{
			pCommand = pCommand + " " + line;
			line = pIn.readLine();
			if ( line != null ) line = line.trim();
		}

		return pCommand;
	}


	public synchronized Collection parseSQLFiles( String[] pFiles )
	{
                setFileNameArray( pFiles );
// ****************************************
// THIS FUNCTION CALLS THE FUNCTION THAT
// READS THROUGH THE ARRAY OF FILES PASSED
// TO IT AND IT RETURNS A VECTOR OF SQL
// STATEMENTS.  MOST OF THESE WILL TEND
// TO BE CREATE AND DROP STATEMENTS.
// ****************************************
		List v = new ArrayList();
		v = readFileAndLoadData();
		String s = "";
		for (int i=0;i parseSQLFile( String pFile )
        {
            String[] files = { pFile };
            return parseSQLFiles( files );
        }

	// This is useful for debugging this application
	public boolean logToSystemOut = false;
	public static void main (String[] args)
	{
		SQLFileParser t = new SQLFileParser();
		t.logToSystemOut = true;
		Iterator cmds = t.parseSQLFiles( args ).iterator();
		  while ( cmds.hasNext() ) {
		   log.info("\n\n" + cmds.next() );
		  }
	}



}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy