/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   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 org.bodington.installation;

import org.apache.log4j.Logger;

import java.sql.*;
import java.util.*;
import java.io.*;

import org.bodington.database.*;
import org.bodington.server.*;
import org.bodington.server.realm.*;
import org.bodington.server.resources.*;
import org.bodington.text.*;


public class Installer
	{
    
    private static Logger log = Logger.getLogger(Installer.class);
    
	public static final String[] system_tables =
        {
            "classes", "fields", "objects",
            "xml_objects", "xml_elements", "xml_attributes", 
            "xml_cdata", "xml_tokens", "xml_words" 
        };

        public static final String[] system_sql =
        {
          "/org/bodington/sqldatabase/Setup.sql",
          "/org/bodington/xml/Xml.sql",
          "/org/bodington/server/realm/AliasEditor.sql",
          "/org/bodington/server/resources/HeadingResource.sql"
        };
        
        public static final String sql_upgrade_2_0_to_2_1 = "/org/bodington/installation/upgrade_2_0_to_2_1.sql";
        public static final String sql_upgrade_2_1_to_2_1_1 = "/org/bodington/installation/upgrade_2_1_to_2_1_1.sql";
                                      
    public static final int TABLE = 0;
    public static final int FILE = 1;
	public static final String[][] tables_sql_in_order = {
		{ "zones",                  "/org/bodington/server/realm/Zone.sql" },
		{ "users",                  "/org/bodington/server/realm/User.sql" },
		{ "pass_phrases",           "/org/bodington/server/realm/PassPhrase.sql" },
		{ "acls",                   "/org/bodington/server/realm/Acl.sql" },
		{ "aliases",                "/org/bodington/server/realm/Alias.sql" },
		{ "alias_entries",          "/org/bodington/server/realm/AliasEntry.sql" },
		{ "big_strings",            "/org/bodington/text/BigString.sql" },
		{ "resources",              "/org/bodington/server/resources/Resource.sql" },
		{ "groups",                 "/org/bodington/server/realm/Group.sql" },
		{ "members",                "/org/bodington/server/realm/Member.sql" },
		{ "acl_entries",            "/org/bodington/server/realm/AclEntry.sql" },
		{ "uploaded_files",         "/org/bodington/server/resources/UploadedFile.sql" },
		{ "user_details",           "/org/bodington/server/realm/UserDetail.sql" },
		{ "user_event_setups",      "/org/bodington/server/events/UserEventSetup.sql" },
		{ "resource_event_users",   "/org/bodington/server/events/ResourceEventUser.sql" },
		{ "mcq_papers",             "/org/bodington/assessment/McqPaper.sql" },
		{ "pigeonholes",           "/org/bodington/assessment/PigeonHole.sql" },
		{ "questionnaires",         "/org/bodington/assessment/Questionnaire.sql" },
		{ "textq_papers",           "/org/bodington/assessment/TextQPaper.sql" },

		{ "mcq_questions",          "/org/bodington/assessment/McqQuestion.sql" },
		{ "mcq_results",            "/org/bodington/assessment/McqResult.sql" },
		{ "mcq_responses",          "/org/bodington/assessment/McqResponse.sql" },

		{ "pigeonhole_questions",  "/org/bodington/assessment/PigeonHoleQuestion.sql" },
		{ "pigeonhole_entries",    "/org/bodington/assessment/PigeonHoleEntry.sql" },
		{ "pigeonhole_responses",  "/org/bodington/assessment/PigeonHoleResponse.sql" },

		{ "questionnaire_questions",    "/org/bodington/assessment/QuestionnaireQuestion.sql" },
		{ "questionnaire_results",      "/org/bodington/assessment/QuestionnaireResult.sql" },
		{ "questionnaire_responses",    "/org/bodington/assessment/QuestionnaireResponse.sql" },

		{ "text_questions",            "/org/bodington/assessment/TextQuestion.sql" },
		{ "textq_results",              "/org/bodington/assessment/TextQResult.sql" },
		{ "textq_responses",            "/org/bodington/assessment/TextQResponse.sql" },

		{ "messaging_rooms",            "/org/bodington/messaging/MessagingRoom.sql" },
		{ "messages",                   "/org/bodington/messaging/Message.sql" },

		{ "events",                     "/org/bodington/server/events/Event.sql" },
		{ "assessment_events",          "/org/bodington/server/events/AssessmentEvent.sql" },
		{ "messaging_events",           "/org/bodington/server/events/MessagingEvent.sql" },
		{ "navigation_events",          "/org/bodington/server/events/NavigationEvent.sql" },
		{ "opinion_events",             "/org/bodington/server/events/OpinionEvent.sql" },
        { "resource_events",            "/org/bodington/server/events/ResourceEvent.sql" },
		{ "user_events",                "/org/bodington/server/events/UserEvent.sql" },
		{ "user_file_events",           "/org/bodington/server/events/UserFileEvent.sql" },
		{ "user_management_events",     "/org/bodington/server/events/UserManagementEvent.sql" },

		{ "jobs",                       "/org/bodington/server/Job.sql" },
		{ "job_results",                "/org/bodington/server/JobResult.sql" },
		{ "metadata",                   "/org/bodington/text/Metadatum.sql" },

		{ "log_books",                  "/org/bodington/logbook/server/LogBook.sql" },
		{ "log_book_sections",          "/org/bodington/logbook/server/LogBookSection.sql" },
		{ "log_book_questions",         "/org/bodington/logbook/server/LogBookQuestion.sql" },
		{ "log_book_pages",             "/org/bodington/logbook/server/LogBookPage.sql" },
		{ "log_book_entries",           "/org/bodington/logbook/server/LogBookEntry.sql" },
		{ "log_book_events",            "/org/bodington/logbook/server/LogBookEvent.sql" },
		  
		  // WebLearn additions (16/12/04) A O'Connor --->>>
		{ "quick_links",            	"/org/bodington/server/resources/QuickLink.sql" },
		{ "sentient_lists",            	"/org/bodington/server/resources/SentientLink.sql" },
		{ "newsfeeds",            		"/org/bodington/server/resources/NewsFeedResource.sql" },
		{ "blogs",            			"/org/bodington/server/resources/BlogResource.sql" },          
		  // WebLearn addition (26/04/05) Colin Tatham
		{ "textblocks",            		"/org/bodington/server/resources/TextBlockResource.sql" },          
		  // WebLearn addition (05/05/05) Colin Tatham
		{ "imageblocks",            	"/org/bodington/server/resources/ImageBlockResource.sql" },
          // WebLearn addition (03/08/05) Matthew Buckett
		{ "web_auth_user",			"/org/bodington/server/realm/WebAuthUser.sql" },
          // <<<--- WebLearn additions.
		  
		{ "user_x509s",                 "/org/bodington/server/realm/UserX509.sql" },
        { "home_container",           "/org/bodington/server/resources/HomeContainerResource.sql" },
        { "home_container_events",    "/org/bodington/server/events/HomeContainerEvent.sql"},
        { "home_resource",           "/org/bodington/server/resources/HomeResource.sql" },
        { "easyedit_resource",       "/org/bodington/server/resources/EasyEditResource.sql"},
        { " easyedit_events",        "/org/bodington/server/events/EasyEditEvent.sql"},
        {  "peer_mark_papers",           "/org/bodington/assessment/PeerMarkerPaper.sql"},
        {  "peer_mark_questions",        "/org/bodington/assessment/PeerMarkerQuestion.sql"},
        {  "peer_mark_results",          "/org/bodington/assessment/PeerMarkerResult.sql"},
        {  "peer_mark_responses",        "/org/bodington/assessment/PeerMarkerResponse.sql"},
		{  "export_events",           "/org/bodington/server/events/ExportEvent.sql" }
        };

    // Substitutions to make in installation SQL files for different RDBMS products
	//TODO replacement is currently case-sensitive!!
	// replacement doesn't consider 'words' eg: 'open_timestamp' is replaced with open_DATETIME'
	
	// Array columns constants
    public static final int ORGINAL = 0;
    public static final int REPLACE = 1;
    
    public static final String[][] SQL_REPLACE_MS =
    {
        {"VARCHAR", "NVARCHAR"},
        {"LONG VARCHAR", "NTEXT"},
        {"TIMESTAMP", "DATETIME"},
        {"CURRENT_TIMESTAMP", "getdate()"}
    };
    
    public static final String[][] SQL_REPLACE_PG =
    {
        {"DEFAULT", "CONSTRAINT DEF_# DEFAULT"},
        {"LONG VARCHAR", "text"},
        {"tinyint", "int2"},
        {"CURRENT_TIMESTAMP", "timestamp(now)"}
    };
   
    public static final String[][] SQL_REPLACE_OR =
    {
        {"tinyint", "NUMERIC(3)"},
        {"short", "NUMERIC(5)"},
        {"int ", "NUMERIC(10) "},
        {"int, ", "NUMERIC(10) "},
        {"varchar", "VARCHAR2"},
        {"VARCHAR", "VARCHAR2"},
        {"LONG VARCHAR", "LONG"},
        {"TIMESTAMP", "DATE"}
    };
    
    public static final String[][] SQL_REPLACE_HS =
    {
        { "LONG VARCHAR",  "LONGVARCHAR"}, 
        { "(-1)", "-1"}
    };
    
        public static int tableCount()
        {
            return system_tables.length + tables_sql_in_order.length;
        }
        
	public static String[] extraTables( DatabaseMetaData dbmeta )
		throws SQLException
		{
		return checkTables( dbmeta, true );
		}
		
	public static String[] existingTables( DatabaseMetaData dbmeta )
		throws SQLException
		{
		return checkTables( dbmeta, false );
		}
	
        public static String[] missingTables( String[] tables )
        {
            int i;
            Hashtable existing = new Hashtable();
            for ( i=0; i< tables.length; i++ )
                existing.put( tables[i], tables[i] );

            Vector missing = new Vector();

            for ( i=0; i<system_tables.length; i++ )
                if ( !existing.containsKey( system_tables[i] ) )
                    missing.addElement( system_tables[i] );

            for ( i=0; i<tables_sql_in_order.length; i++ )
            {
                if ( !existing.containsKey( tables_sql_in_order[i][TABLE] ) )
                    missing.addElement( tables_sql_in_order[i][TABLE] );
            }
            
            String[] list = new String[missing.size()];
            for ( i=0; i<missing.size(); i++ )
                list[i] = (String)missing.elementAt( i );
            
            return list;
        }
        
        public static boolean has2_0Tables( String[] tables )
        {
            // if it has system tables but doesn't have job_results
            // assume it is v.2.0.x
            
            int i, j;
            boolean found;

            for ( j=0; j<system_tables.length; j++ )
            {
                found=false;
                for ( i=0; i<tables.length && !found; i++ )
                    if ( tables[i].equalsIgnoreCase( system_tables[j] ) )
                        found=true;
                
                if ( !found )
                    return false;
            }

            for ( i=0; i<tables.length; i++ )
                if ( "job_results".equalsIgnoreCase( tables[i] ) )
                    return false;
            
            return true;
        }
        
        public static boolean has2_1Tables( Connection con )
            throws SQLException
        {
            // This method may need to be revised with future versions of Bodington
            
            // if wrong fields in the xml_tokens and xml_words tables, assume it is v.2.1.0
            // assumes that this method is not called if has2_0Tables was called and returned
            // true
            Statement s;
            ResultSet results;

            s = con.createStatement();
            
            try
            {
                results = s.executeQuery( "select xml_token_id from xml_tokens where xml_token_id < 0" );
                results.close();
                results = s.executeQuery( "select xml_word_id from xml_words where xml_word_id < 0" );
                results.close();
            }
            catch ( SQLException e )
            {
                // lacks whole table so must be earlier than 2.1
                s.close();
                return false;
            }
            
            try
            {
                // this check won't work if future versions of Bodington take these fields out again
                results = s.executeQuery( "select tertiary_id, secondary_id, primary_id, token from xml_tokens where xml_token_id < 0" );
                results.close();
            }
            catch ( SQLException e )
            {
                // lacks 2.1.1 fields - so this is 2.1.0
                s.close();
                return true;
            }
            
            
            // no exceptions so this is later than 2.1.1 or later
            s.close();
            return false;
        }
        
        
    /**
     * Attempt to guess the schema that we should be using.
     * This allows us to work a little better with oracle by defaulting to 
     * the schema the same as the username. If the default schema for
     * the user has been changed this will break.
     * @param metadata The connection metadata.
     * @return The schema we should be using, % if we can't find out.
     * @throws SQLException If something goes wrong.
     */
    private static String guessSchema( DatabaseMetaData metadata ) throws SQLException
    {

        String url = metadata.getURL();
        if (url != null)
        {
            String urlSections[] = url.split(":");
            if (urlSections[1].equalsIgnoreCase("oracle"))
            {
                System.out.println("WARNING: Using username as schema, this may not work.");
                return metadata.getUserName();
            }
        }
        return "%";
    }
        
    /**
     * Finds tables that Bodington can see.
     * @param dbmeta The DatabaseMetaData that if from the database connection.
     * @param extra If True then also return the tables that are not part of the 
     * known Bodington set of tables.
     * @return As array of table names.
     * @throws SQLException If we have problems getting table information.
     */
	private static String[] checkTables( DatabaseMetaData dbmeta, boolean extra )
            throws SQLException
            {
		int i;
        String schema = guessSchema(dbmeta);
		ResultSet results = dbmeta.getTables( null, schema, "%", new String[]{"TABLE"});
		Vector list = new Vector();
		String table;
                Hashtable table_table = new Hashtable();
		while ( results!=null && results.next() )
		{
                    table = results.getString( "TABLE_NAME" );
                    table_table.put( table.toLowerCase(), table.toLowerCase() );
                }
		results.close();
                
		for ( i=0; i<system_tables.length; i++ )
                    if ( table_table.containsKey( system_tables[i] ) )
                        list.addElement( system_tables[i] );
                            
		for ( i=0; i<tables_sql_in_order.length; i++ )
                    if ( table_table.containsKey( tables_sql_in_order[i][TABLE] ) )
                        list.addElement( tables_sql_in_order[i][TABLE] );
                    
                
                String[] ret;
                if ( !extra )
                {
                    ret = new String[list.size()];
                    for ( i=0; i<ret.length; i++ )
    			ret[i] = (String)list.elementAt( i );
		return ret;
                }
                
                ret = new String[table_table.size()-list.size()];
                Enumeration enumeration = table_table.keys();
                i=0;
                while ( enumeration.hasMoreElements() )
                {
                    table = (String)enumeration.nextElement();
                    if ( !list.contains( table ) )
                        ret[i++] = table;
                }
        	return ret;
            }

	
	/**
	 * Drop all the Bodington tables we can find.
	 * @param con The database connection to remove the tables from.
	 * @throws SQLException If we have problem finding the tables of deleting one
	 * of them.
	 */
	public static void deleteTables( Connection con )
		throws SQLException
		{
		DatabaseMetaData dbmeta = con.getMetaData();
		String[] tables = existingTables( dbmeta );
		Statement st = con.createStatement();
		// Loop through the tables backwards so that we don't have problems with
		// foreign key constraints preventing us from dropping them.
		for ( int i=tables.length-1; i>=0 ; i-- )
			st.executeUpdate( "DROP TABLE " + tables[i] );
		
		st.close();
		}
		

	static int type_length;
	static String alt_type;
	static int next_constraint=1;
	
	static int nextIndex( String line, int n,
	    String[][] sql_substitutions)
	{

	    if ( sql_substitutions == null )
	        return -1;
	    
	    int r, i;
	    int[] index= new int[sql_substitutions.length];
	    
	    // find first instance of each keyword that has an alternative
	    for ( i=0; i<sql_substitutions.length; i++ )
	        index[i] = line.indexOf( sql_substitutions[i][ORGINAL], n );
	    
	    // of those found which was first?
	    r=-1;
	    for ( i=0; i<index.length; i++ )
	    {
	        if ( index[i] >=0 )
	            if ( r<0 || index[i]<index[r] )
	                r=i;
	    }
	    
	    // return -1 if no keyword found 
	    if ( r<0 )
	        return -1;
	    
	    type_length = sql_substitutions[r][ORGINAL].length();
	    
	    // does substitution require insertion of a number?  (e.g. for a constraint)
	    // signalled by a # at end of alternative
	    
	    i=sql_substitutions[r][REPLACE].indexOf( '#' );
	    if ( i >= 0 )
	        alt_type = sql_substitutions[r][REPLACE].substring( 0, i )  + (next_constraint++) + sql_substitutions[r][REPLACE].substring( i+1 );
	    else
	        alt_type = sql_substitutions[r][REPLACE];
	    
	    return index[r];
	}

	public static void executeSQLFromResource( BufferedReader input, Connection c,
																	String[][] sql_substitutions)
		throws SQLException, IOException
		{
	    int n, m;
	    Statement st = c.createStatement();
	    StringBuffer buffer = new StringBuffer();
	    String line, full = null;

	    try
	    {
	        line=input.readLine();
	        while ( line!=null )
	        {
	            n=0;
	            while ( (m = nextIndex( line, n, sql_substitutions)) >=0 )
	            {
	                buffer.append( line.substring( n, m ) );
	                buffer.append( alt_type );
	                n = m + type_length;
	            }
	            buffer.append( line.substring( n, line.length() ) );
	            buffer.append( "\n" );
	            line=input.readLine();

	            if ( line!=null )
	            {
	                if ( line.startsWith( "go" ) || line.startsWith( "GO" ) )
	                {
	                    full = buffer.toString();
	                    log.info( full );
	                    st.executeUpdate( full );
	                    buffer.setLength( 0 );
	                    line=input.readLine();
	                }
	            }
	        }
	        st.close();
	    }
	    catch (SQLException sqle)
	    {
	        log.error("SQL Problem: "+ full, sqle);
	        throw sqle;
	    }
		}

/*
public static synchronized void upgradeTablesFrom2_0(	
    Connection con, 
    Class ref_class, 
    String db_user, 
    String[] sql_substitutions, 
    String[] sql_alternatives )
    throws SQLException, IOException
{
    int i;

    DatabaseMetaData dbmeta = con.getMetaData();
    String[] tables = existingTables( dbmeta );
    Hashtable existing = new Hashtable();
    for ( i=0; i< tables.length; i++ )
        existing.put( tables[i], tables[i] );
    
    Vector sql_to_execute = new Vector();
    sql_to_execute.addElement( sql_upgrade_2_0_to_2_1 );
    
    InputStream instream;
    BufferedReader input;

    //st.executeUpdate( "USE " + dbname );
    for ( i=0; i<sql_in_2_1.length; i++ )
    {
        System.err.println( "Executing SQL from " + sql_in_2_1[i] + "\n" );
        instream = ref_class.getResourceAsStream( sql_in_2_1[i] );
        if ( instream == null )
            throw new IOException( "Data file not found." );
        input = new BufferedReader( new InputStreamReader( instream ) );
        if ( input == null )
            throw new IOException( "Buffered reader not created." );
        executeSQLFromResource( input, con, sql_substitutions, sql_alternatives );
        input.close();
    }

        Statement st = con.createStatement();

        String sysuser = con.getMetaData().getUserName();

    if ( db_user != null && !sysuser.equalsIgnoreCase( db_user ) )
    {
        String sql;
        for ( i=0; i<tables_created_in_2_1.length; i++ )
        {
            sql = "GRANT  SELECT ,  INSERT ,  DELETE ,  UPDATE  ON " + tables_created_in_2_1[i] + " TO " + db_user;
            st.executeUpdate( sql );
        }
    }
    st.close();
}        
  */
        
        
    public static synchronized void createTables(	
        Connection con, 
        Class ref_class, 
        String db_user, 
        String[][] sql_substitutions, 
        boolean upgrade,
        String version_previous,
        String version_current )
        throws SQLException, IOException
    {
        int i;

        DatabaseMetaData dbmeta = con.getMetaData();
        String[] tables = existingTables( dbmeta );
        Hashtable existing = new Hashtable();
        for ( i=0; i< tables.length; i++ )
            existing.put( tables[i], tables[i] );

        Vector sql_to_execute = new Vector();
        
        if ( upgrade )
        {
            if ( version_previous.startsWith( "2.0." ) )
            {
                if ( version_current.startsWith( "2.1." ) )
                {
            sql_to_execute.addElement( sql_upgrade_2_0_to_2_1 );
            sql_to_execute.addElement( "/org/bodington/server/Job.sql" );
        }
            }
            if ( version_previous.startsWith( "2.0." ) || version_previous.startsWith( "2.1." ) )
            {
                if ( version_current.startsWith( "2.1.1" ) )
                {
                    sql_to_execute.addElement( sql_upgrade_2_1_to_2_1_1 );
                }
            }
        }
        else
        {
            for ( i=0; i<system_sql.length; i++ )
                sql_to_execute.addElement( system_sql[i] );
        }
        
        for ( i=0; i<tables_sql_in_order.length; i++ )
        {
            if ( !existing.containsKey( tables_sql_in_order[i][TABLE] ) )
                sql_to_execute.addElement( tables_sql_in_order[i][FILE] );
        }
        
        InputStream instream;
        BufferedReader input;
        String sql_file;
        
        //st.executeUpdate( "USE " + dbname );
        for ( i=0; i<sql_to_execute.size(); i++ )
        {
            sql_file = (String)sql_to_execute.elementAt( i );
            log.info( "Executing SQL from " + sql_file + "\n" );
            //message.append( "Executing SQL from " + sql_in_order[i] + "\n" );
            instream = ref_class.getResourceAsStream( sql_file );
            if ( instream == null )
                throw new IOException( "Data file not found: "+ sql_file );
            input = new BufferedReader( new InputStreamReader( instream ) );
            if ( input == null )
                throw new IOException( "Buffered reader not created." );
            executeSQLFromResource( input, con, sql_substitutions);
            input.close();
        }

        
        tables = existingTables( dbmeta );
        Statement st = con.createStatement();

        String sysuser = con.getMetaData().getUserName();

        if ( db_user != null && !sysuser.equalsIgnoreCase( db_user ) )
        {
            String sql;
            //message.append( "Setting permissions on tables.\n" );
            for ( i=0; i<tables.length; i++ )
            {
                sql = "GRANT  SELECT ,  INSERT ,  DELETE ,  UPDATE  ON " + tables[i] + " TO " + db_user;
                st.executeUpdate( sql );
            }
        }
        st.close();
    }

    
    

	static String system_zone_prefix = "sys";
	static String system_zone_name = "System Administration";
	
	static Integer admin_zone_user_group_id;
								
	static Integer sys_zone_user_group_id;
	static Integer sys_zone_staff_group_id;
	static Integer sys_zone_student_group_id;
	static Integer sys_zone_other_group_id;
    static Integer public_group_id    ;
	static Integer all_user_group_id		;
	static Integer all_staff_group_id		;
	static Integer all_student_group_id	;
	static Integer all_other_group_id		;
								
								
	static String building_name_recycler = "recycler";
	static String building_title_recycler = "Recycling Building";
	static String building_description_recycler = "This building is where deleted resources go.";
	
	static String building_name_admin = "admin";
	static String building_title_admin = "Site Administration Building";
	static String building_description_admin = "This building is for site administation.";
								
								
	static String u_name_sysadmin			= "System Administrator";
	static String u_surname_sysadmin		= "Administrator";
	static String u_initials_sysadmin 	= "SA";
	static String u_user_name_sysadmin	= "sysadmin";
	
	static String u_name_anon1			= "Anonymous Internet User";
	static String u_surname_anon1		= "Anonymous";
	static String u_initials_anon1 	= "AIU1";

        
        private static void addProperty( PrimaryKey resid, String name, String value )
        throws BuildingServerException
        {
            Metadatum m=new Metadatum();
            m.setObjectId( resid );
            m.setName( name );
            m.setValue( value );
            m.save();                
        }
        
        private static void setProperty ( PrimaryKey resourceId, String name, String value )
        throws BuildingServerException
        {
            Metadatum meta = Metadatum.findMetadatumByIdAndName(resourceId, name);
            if (meta == null)
            {
                meta = new Metadatum();
                meta.setObjectId(resourceId);
                meta.setName( name );
            }
            meta.setValue(value);
            meta.save();
        }

	public static void createMinimalData( Properties props )
		throws Exception
		{
		int bs_status = BuildingServer.getStatus();
		if ( bs_status != BuildingServer.STATUS_NONE )
			throw new Exception( "Can't setup data because the BuildingServer has already been started." );
		
		log.info( "About to create Instance of BuildingServer" );

		BuildingServer.createInstance( true, props );
		
		log.info( "Created Instance of BuildingServer" );

		bs_status = BuildingServer.getStatus();
		if ( bs_status != BuildingServer.STATUS_READY_FOR_SETUP )
			throw new Exception( "Can't setup data because the BuildingServer failed to start." );

		log.info( "Instance of BuildingServer in appropriate state." );
		
		int n=1;
		
		// not really ids - these are special group flag numbers
        public_group_id   = new Integer(0);
		all_user_group_id		= new Integer(n++);
		all_staff_group_id		= new Integer(n++);
		all_student_group_id	= new Integer(n++);
		all_other_group_id		= new Integer(n++);
		sys_zone_user_group_id= new Integer(n++);
		sys_zone_staff_group_id= new Integer(n++);
		sys_zone_student_group_id= new Integer(n++);
		sys_zone_other_group_id= new Integer(n++);

		
		log.info( "About to get BuildingContext." );

		BuildingContext context = BuildingContext.getContext();

		log.info( "Got BuildingContext." );
		        
		Zone sys_zone;
		User sysadmin, anon1;
		PassPhrase sysadminpass;
		        
		Group publicGroup, allusers, allstaff, allstudents, allothers, sysadmins, anonymi;
		Acl siteacl, recycleracl;
		AclEntry newaclentry;
		Resource res0, res1, res2, res3, res4, res5, recycler=null;
		ResourceTree tree;
				


		sys_zone = new Zone();
		sys_zone.setPrefix( system_zone_prefix );
		sys_zone.setName( system_zone_name );
		sys_zone.save();

		sysadmin=new User();
		sysadmin.setName( u_name_sysadmin );
		sysadmin.setSurname( u_surname_sysadmin );
		sysadmin.setInitials( u_user_name_sysadmin );
		sysadmin.setZone( sys_zone );
		sysadmin.save();

		sysadminpass=new PassPhrase(sysadmin);
		sysadminpass.setUserName( u_user_name_sysadmin );
		sysadminpass.changePassPhrase( u_user_name_sysadmin );
		sysadminpass.save();

		anon1=new User();
		anon1.setName( u_name_anon1 );
		anon1.setSurname( u_surname_anon1 );
		anon1.setInitials( u_initials_anon1);
		anon1.setZone( sys_zone );
		anon1.save();

      context.setUser( sysadmin );


		tree = ResourceTreeManager.getInstance();
		
		res0=new Resource();
		res0.setZone( sys_zone );
		res0.setName( "site" );
		res0.setTitle( "Bodington System Site" );
		res0.setDescription( "This site description may appear in search results but is not normally visible " +
									"when simply navigating the site. " );
		res0.setIntroduction( "This is a web site newly created with the Bodington System. The system " +
									"administrator can change this text, the title of the site and create " +
									"resources by logging in and using the commands that will appear on the pages. " );
		res0.setHttpFacilityNo( 24 );
		tree.addResource( null, res0 );

                addProperty( res0.getResourceId(), "style_specified", "yes" );
                addProperty( res0.getResourceId(), "style_background_colour", "#f0f0e0" );
                addProperty( res0.getResourceId(), "style_background_image", "none" );
                addProperty( res0.getResourceId(), "style_foreground_colour", "#202040" );
                addProperty( res0.getResourceId(), "style_emphasis_colour", "#aa6600" );
                addProperty( res0.getResourceId(), "style_link_colour", "#403399" );
                addProperty( res0.getResourceId(), "style_link_visited_colour", "#333380" );
                addProperty( res0.getResourceId(), "style_link_active_colour", "#333399" );
                addProperty( res0.getResourceId(), "style_link_hover_colour", "#000066" );
                addProperty( res0.getResourceId(), "style_graphic_background_colour", "#f0f0e0" );
                addProperty( res0.getResourceId(), "style_graphic_foreground_colour", "#202040" );
                
                addProperty( res0.getResourceId(), "style_navigation_background_colour", "#007c88" );
                addProperty( res0.getResourceId(), "style_navigation_background_image", "none" );
                addProperty( res0.getResourceId(), "style_navigation_foreground_colour", "#ffffff" );
                addProperty( res0.getResourceId(), "style_navigation_emphasis_colour", "#ffa401" );
                addProperty( res0.getResourceId(), "style_navigation_link_colour", "#aaaaff" );
                addProperty( res0.getResourceId(), "style_navigation_link_visited_colour", "#aaaaee" );
                addProperty( res0.getResourceId(), "style_navigation_link_active_colour", "#333399" );
                addProperty( res0.getResourceId(), "style_navigation_link_hover_colour", "#ffffff" );
                addProperty( res0.getResourceId(), "style_navigation_graphic_background_colour", "#007c88" );
                addProperty( res0.getResourceId(), "style_navigation_graphic_foreground_colour", "#ffffff" );
                
		siteacl=res0.getAcl();
		Enumeration entries = siteacl.entries();
		if ( entries.hasMoreElements() )
	      {
	      newaclentry = (AclEntry)entries.nextElement();
	      newaclentry.addPermission( Permission.SYSADMIN );
	      newaclentry.save();
	      }

		res1=new Resource();
		res1.setName( building_name_admin );
		res1.setTitle( building_title_admin );
		res1.setDescription( building_description_admin );
		res1.setIntroduction( building_description_admin );
		res1.setHttpFacilityNo( 23 );
		tree.addResource( res0, res1 );

        NewsFeedResource news = new NewsFeedResource();
        news.setHttpFacilityNo( 101 );
        news.setName( "news" );
        news.setTitle( "News" );
        news.setDescription( "News feed to be displayed in left-hand panel." );
        news.setIntroduction( "" );
        news.setURL( "http://rss.oucs.ox.ac.uk/oucs/weblearn-news/atom10.xml" );
        news.setNewsFeedFlags( 36 );
        tree.addResource( res1, news );
        
        

		recycler=new Resource();
		recycler.setName( building_name_recycler );
		recycler.setTitle( building_title_recycler );
		recycler.setDescription( building_description_recycler );
		recycler.setIntroduction( building_description_recycler );
		recycler.setHttpFacilityNo( 30 );
		recycler.setHttpUIStyle( new Integer( 0 ) );
		tree.addResource( res0, recycler );
		recycleracl=recycler.getAcl();

        HomeContainerResource users = new HomeContainerResource("users", "MyWebLearn", "Users Space", "");
        users.setHttpFacilityNo(105);
        tree.addResource(res0, users );

		res2=new Resource();
		res2.setName( "ground" );
		res2.setTitle( "Ground Floor" );
		res2.setDescription( "Ground floor contains tools for administering the site." );
		res2.setIntroduction( "Ground floor contains tools for administering the site." );
		res2.setHttpFacilityNo( 3 );
		tree.addResource( res1, res2 );
		
		
		
		res3=new Resource();
		res3.setName( system_zone_prefix );
		res3.setTitle( "User Administration for " + system_zone_name + " zone." );
		res3.setDescription( "Contains tools for administration of users." );
		res3.setIntroduction( "This room contains tools for administration of users." );
		res3.setHttpFacilityNo( 5 );
		tree.addResource( res2, res3 );
		       	
		res4=new AliasEditor();
		res4.setName( "userid" );
	   res4.setTitle( "Unique Identifier Tool" );
		res4.setDescription( "Use this tool to manage identifiers for users." );
	   res4.setIntroduction( "Use this tool to manage identifiers for users." );
		res4.setHttpFacilityNo( 25 );
		tree.addResource( res3, res4 );

		res4=new AliasEditor();
		res4.setName( "usercreate" );
	   res4.setTitle( "User Creation Tool" );
		res4.setDescription( "Use this tool to create users." );
	   res4.setIntroduction( "Use this tool to create users." );
		res4.setHttpFacilityNo( 26 );
		tree.addResource( res3, res4 );

		res4=new AliasEditor();
		res4.setName( system_zone_prefix );
	   res4.setTitle( "Groups of Users" );
		res4.setDescription( "Use this tool to put users into named groups." );
	   res4.setIntroduction( "Use this tool to put users into named groups." );
		res4.setHttpFacilityNo( 27 );
		tree.addResource( res3, res4 );

		res5=new Resource();
		res5.setName( "anonymous" );
		res5.setTitle( "anonymous" );
		res5.setDescription( "People who access the site without logging in." );
		res5.setIntroduction( res5.getDescription() );
		res5.setHttpFacilityNo( 6 );
		tree.addResource( res4, res5 );
      anonymi = new Group();
      anonymi.setResourceId( res5.getResourceId() );
      anonymi.setName( "anonymous" );
      anonymi.setDescription( res5.getDescription() );
      anonymi.save();
		anonymi.addMember( anon1 );
      anonymi.save();
		
        res5=new Resource();
        res5.setName( "public" );
        res5.setTitle( "public" );
        res5.setDescription( "Everyone who can access the site. Including people with accounts and without" );
        res5.setIntroduction( res5.getDescription() );
        res5.setHttpFacilityNo( 6 );
        tree.addResource( res4, res5 );
        publicGroup = new Group();
        publicGroup.setResourceId( res5.getResourceId() );
        publicGroup.setName( "public" );
        publicGroup.setDescription( res5.getDescription() );
        publicGroup.setSpecialGroup( public_group_id );
        publicGroup.save();
        
		res5=new Resource();
		res5.setName( "allusers" );
		res5.setTitle( "allusers" );
		res5.setDescription( "All types of users who have accounts in the system for this site."  );
		res5.setIntroduction( res5.getDescription() );
		res5.setHttpFacilityNo( 6 );
		tree.addResource( res4, res5 );
      allusers = new Group();
      allusers.setResourceId( res5.getResourceId() );
      allusers.setName( "allusers" );
      allusers.setDescription( res5.getDescription() );
      allusers.setSpecialGroup( all_user_group_id );
      allusers.save();
		allusers.addMember( sysadmin );
      allusers.save();
        	

		res5=new Resource();
		res5.setName( "allstudents" );
		res5.setTitle( "allstudents" );
		res5.setDescription( "All students who have accounts in the system for this site."  );
		res5.setIntroduction( res5.getDescription() );
		res5.setHttpFacilityNo( 6 );
		tree.addResource( res4, res5 );
      allstudents = new Group();
      allstudents.setResourceId( res5.getResourceId() );
      allstudents.setName( "allstudents" );
      allstudents.setDescription( res5.getDescription() );
      allstudents.setSpecialGroup( all_student_group_id );
      allstudents.save();
        	
		res5=new Resource();
		res5.setName( "allstaff" );
		res5.setTitle( "allstaff" );
		res5.setDescription( "All staff who have accounts in the system for this site."  );
		res5.setIntroduction( res5.getDescription() );
		res5.setHttpFacilityNo( 6 );
		tree.addResource( res4, res5 );
      allstaff = new Group();
      allstaff.setResourceId( res5.getResourceId() );
      allstaff.setName( "allstaff" );
      allstaff.setDescription( res5.getDescription() );
      allstaff.setSpecialGroup( all_staff_group_id );
      allstaff.save();
        	
		res5=new Resource();
		res5.setName( "allothers" );
		res5.setTitle( "allothers" );
		res5.setDescription( "All users, other than staff abd students who have accounts in the system for this site."  );
		res5.setIntroduction( res5.getDescription() );
		res5.setHttpFacilityNo( 6 );
		tree.addResource( res4, res5 );
      allothers = new Group();
      allothers.setResourceId( res5.getResourceId() );
      allothers.setName( "allothers" );
      allothers.setDescription( res5.getDescription() );
      allothers.setSpecialGroup( all_other_group_id );
      allothers.save();
		allothers.addMember( sysadmin );
      allothers.save();
        	
		res5=new Resource();
		res5.setName( "sysadmins" );
		res5.setTitle( "sysadmins" );
		res5.setDescription( "System administrators for this web site."  );
		res5.setIntroduction( res5.getDescription() );
		res5.setHttpFacilityNo( 6 );
		tree.addResource( res4, res5 );
      sysadmins = new Group();
      sysadmins.setResourceId( res5.getResourceId() );
      sysadmins.setName( "sysadmins" );
      sysadmins.setDescription( res5.getDescription() );
      sysadmins.save();
      sysadmins.addMember( sysadmin );
      sysadmins.save();
		sysadmins.addMember( sysadmin );
      sysadmins.save();


		
	   newaclentry = new AclEntry();
	   newaclentry.setPrincipal( allusers );
	   newaclentry.addPermission( Permission.SEE );
	   newaclentry.addPermission( Permission.VIEW );
	   siteacl.addEntry( newaclentry );
	   siteacl.save();
		
	   newaclentry = new AclEntry();
	   newaclentry.setPrincipal( anonymi );
	   newaclentry.addPermission( Permission.SEE );
	   newaclentry.addPermission( Permission.VIEW );
	   siteacl.addEntry( newaclentry );
	   siteacl.save();
		
	   newaclentry = new AclEntry();
	   newaclentry.setPrincipal( allusers );
	   newaclentry.addPermission( Permission.SEE );
	   newaclentry.addPermission( Permission.VIEW );
	   newaclentry.addPermission( Permission.CREATE );
	   recycleracl.addEntry( newaclentry );
	   recycleracl.save();
	   
       createOxfordData();
       
	   BuildingServer.setupComplete();
		}
    
    public static void createOxfordData() throws BuildingServerException
    {
        Resource resource = ResourceTreeManager.getInstance().findRootResource();
        PrimaryKey resourceId = resource.getPrimaryKey();
        
        setOxfordColourData();
        
        // Create the zone and alias for the userimport code.
        Zone oxford_zone = new Zone();
        oxford_zone.setPrefix("campus");
        oxford_zone.setName("Oxford Zone");
        oxford_zone.save();
        
        Alias alias = new Alias();
        alias.setZoneId( oxford_zone.getPrimaryKey() );
        alias.setAliasName( "oucsldap_id" );
        alias.setAliasType( new Integer(Alias.TYPE_PRIMARY)); 
        alias.setUserCategory( "staff,students" );
        alias.save();
        
        ResourceTree tree = ResourceTreeManager.getInstance();
        Resource ground_floor = tree.findResource("/admin/ground/");
        
        Resource campus_room = new Resource();
		campus_room.setName( "campus" );
		campus_room.setTitle( "User Administration for Our Online Campus zone." ); // !!
		campus_room.setDescription( "Contains tools for administration of users." );
		campus_room.setIntroduction( "This room contains tools for administration of users." );
		campus_room.setHttpFacilityNo( 5 );
		tree.addResource( ground_floor, campus_room );
		
		Resource user_create = new Resource();
        user_create.setName( "usercreate" );
        user_create.setTitle( "User Creation Tool" );
        user_create.setDescription( "Use this tool to create users." );
        user_create.setIntroduction( "Use this tool to create users." );
        user_create.setHttpFacilityNo( 26 );
        tree.addResource( campus_room, user_create );
		
		Resource campus_group_container= new AliasEditor();
		campus_group_container.setName( "campus" );
		campus_group_container.setTitle( "Groups of Users" );
		campus_group_container.setDescription( "Use this tool to put users into named groups." );
		campus_group_container.setIntroduction( "Use this tool to put users into named groups." );
		campus_group_container.setHttpFacilityNo( 27 );
		tree.addResource( campus_room, campus_group_container );
		
		Resource staff_group = new Resource();
		staff_group.setName("staff");
		staff_group.setTitle("campus.staff");
		staff_group.setDescription("Staff of Our On-Line Campus.");
		staff_group.setIntroduction("Staff of Our On-Line Campus.");
		staff_group.setHttpFacilityNo( 6 );
		tree.addResource(campus_group_container, staff_group);
		
		Group staff = new Group();
		staff.setResourceId(staff_group.getResourceId());
		staff.setName(staff_group.getTitle());
		staff.setDescription(staff_group.getDescription());
		staff.save();
		
		
		Resource student_group = new Resource();
		student_group.setName("students");
		student_group.setTitle("campus.students");
		student_group.setDescription("Students of Our On-Line Campus.");
		student_group.setIntroduction("Students of Our On-Line Campus.");
		student_group.setHttpFacilityNo( 6 );
		tree.addResource(campus_group_container, student_group);
		
		Group students = new Group();
		students.setResourceId(student_group.getResourceId());
		students.setName(student_group.getTitle());
		students.setDescription(student_group.getDescription());
		students.save();
		
		Resource notify_tool = new Resource();
		notify_tool.setName("notify");
		notify_tool.setTitle("Notification Tool");
		notify_tool.setDescription(notify_tool.getTitle());
		notify_tool.setIntroduction(notify_tool.getTitle());
		notify_tool.setHttpFacilityNo( 15 );
		tree.addResource(campus_room, notify_tool);
		    
    }

	public static void setOxfordColourData()
			throws BuildingServerException {
		
		Resource resource = ResourceTreeManager.getInstance().findRootResource();
        PrimaryKey resourceId = resource.getPrimaryKey();
		
		setProperty( resourceId, "style_specified", "yes" );
        setProperty( resourceId, "style_background_colour", "#ffffff" );
        setProperty( resourceId, "style_background_image", "none" );
        setProperty( resourceId, "style_foreground_colour", "#000000" );
        setProperty( resourceId, "style_emphasis_colour", "#2f556b" );
        setProperty( resourceId, "style_link_colour", "#0000ff" );
        setProperty( resourceId, "style_link_visited_colour", "#0000ff" );
        setProperty( resourceId, "style_link_active_colour", "#0000ff" );
        setProperty( resourceId, "style_link_hover_colour", "#0000ff" );
        setProperty( resourceId, "style_graphic_background_colour", "#ffffff" );
        setProperty( resourceId, "style_graphic_foreground_colour", "#999999" );
        setProperty( resourceId, "style_table_colour", "#f8f8f8" );
        setProperty( resourceId, "style_table_emphasis_colour", "#eeeeee" );
        
        setProperty( resourceId, "style_navigation_background_colour", "#ffffff" );
        setProperty( resourceId, "style_navigation_background_image", "none" );
        setProperty( resourceId, "style_navigation_foreground_colour", "#000000" );
        
        setProperty(resourceId, "style_navigation_menu_highlight_colour_1","#ffffff");
        setProperty(resourceId, "style_navigation_menu_highlight_colour_2","#fffffe");
        setProperty(resourceId, "style_navigation_menu_header_colour","#f3f8f7");
        setProperty(resourceId, "style_navigation_menu_border_colour","#666666");
        
        setProperty( resourceId, "style_navigation_emphasis_colour", "#2f556b" );
        setProperty( resourceId, "style_navigation_link_colour", "#0000ff" );
        setProperty( resourceId, "style_navigation_link_visited_colour", "#0000ff" );
        setProperty( resourceId, "style_navigation_link_active_colour", "#0000ff" );
        setProperty( resourceId, "style_navigation_link_hover_colour", "#0000ff" );
        setProperty( resourceId, "style_navigation_graphic_background_colour", "#ffffff" );
        setProperty( resourceId, "style_navigation_graphic_foreground_colour", "#999999" );
        setProperty( resourceId, "style_navigation_table_colour", "#f8f8f8" );
        setProperty( resourceId, "style_navigation_table_emphasis_colour", "#eeeeee" );
        
        setProperty( resourceId, "ui_navigation_menu_big_icons", "yes" );
        setProperty( resourceId, "ui_navigation_menu_type", "attached" );
        setProperty( resourceId, "ui_navigation_menu_lines", "no" );
	}
	
public static void moveGeneratedMenusFrom2_0( File old_gen_pub_dir )
throws IOException, BuildingServerException
{
    PassPhrase pass_phrase = PassPhrase.findPassPhraseByUserName( "sysadmin" );
    Resource resource = ResourceTreeManager.getInstance().findRootResource();
    
       Job j = new Job();
       
        j.setUserId( pass_phrase.getUserId() );
        j.setResourceId( resource.getResourceId() );
        j.setSessionName( "org.bodington.installation.FileUpgrader2_0_to_2_1" );
        j.setMethodName( "fetchMenus" );
        j.setParameter( old_gen_pub_dir.getAbsolutePath() );
        j.setState( Job.STATE_OVERDUE );
        j.setSubmissionTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setFromTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setToTime( null );
	j.setRepeatSpec( 0 );
	j.setRepeatType( Job.REPEAT_TYPE_ONCE );
        j.setRepeatPeriod( 1 );
	j.setFirstExecutionTime();
        j.save();
	
	
}

		
public static void upgradeMetadataFrom2_1()
throws IOException, BuildingServerException
{
    PassPhrase pass_phrase = PassPhrase.findPassPhraseByUserName( "sysadmin" );
    Resource resource = ResourceTreeManager.getInstance().findRootResource();
		
       Job j = new Job();
       
        j.setUserId( pass_phrase.getUserId() );
        j.setResourceId( resource.getResourceId() );
        j.setSessionName( "org.bodington.installation.MetadataUpgrader2_1_to_2_1_1" );
        j.setMethodName( "upgradeMetadata" );
        j.setParameter( "" );
        j.setState( Job.STATE_OVERDUE );
        j.setSubmissionTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setFromTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setToTime( null );
	j.setRepeatSpec( 0 );
	j.setRepeatType( Job.REPEAT_TYPE_ONCE );
        j.setRepeatPeriod( 1 );
	j.setFirstExecutionTime();
        j.save();
	
	
}


		
public static void createDemoData( String param )
throws IOException, BuildingServerException
{
    PassPhrase pass_phrase = PassPhrase.findPassPhraseByUserName( "sysadmin" );
    Resource resource = ResourceTreeManager.getInstance().findRootResource();
    
       Job j = new Job();
       
        j.setUserId( pass_phrase.getUserId() );
        j.setResourceId( resource.getResourceId() );
        j.setSessionName( "org.bodington.installation.DemoSiteBuilder" );
        j.setMethodName( "createSite" );
        j.setParameter( param );
        j.setState( Job.STATE_OVERDUE );
        j.setSubmissionTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setFromTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setToTime( null );
	j.setRepeatSpec( 0 );
	j.setRepeatType( Job.REPEAT_TYPE_ONCE );
        j.setRepeatPeriod( 1 );
	j.setFirstExecutionTime();
        j.save();
	
}

public static void moveUploadedFilesFrom2_0( File old_web_pub_dir )
throws IOException, BuildingServerException
{
    PassPhrase pass_phrase = PassPhrase.findPassPhraseByUserName( "sysadmin" );
    Resource resource = ResourceTreeManager.getInstance().findRootResource();
    
       Job j = new Job();
       
        j.setUserId( pass_phrase.getUserId() );
        j.setResourceId( resource.getResourceId() );
        j.setSessionName( "org.bodington.installation.FileUpgrader2_0_to_2_1" );
        j.setMethodName( "fetchFiles" );
        j.setParameter( old_web_pub_dir.getAbsolutePath() );
        j.setState( Job.STATE_OVERDUE );
        j.setSubmissionTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setFromTime( new java.sql.Timestamp( System.currentTimeMillis() )       );
        j.setToTime( null );
	j.setRepeatSpec( 0 );
	j.setRepeatType( Job.REPEAT_TYPE_ONCE );
        j.setRepeatPeriod( 1 );
	j.setFirstExecutionTime();
        j.save();
	
	
}

public static String getJobStatus( String class_name, String function )
throws BuildingServerException
{
    Enumeration enumeration = Job.findJobs( 
	"session_name = '" + class_name + "' AND method_name = '" + function + "'", "submission_time" );
    
    if ( !enumeration.hasMoreElements() )
	return null;
    
    // find most recent submitted job
    Job job = null;
    while ( enumeration.hasMoreElements() )
	job = (Job)enumeration.nextElement();

    // find most recent job result...
    enumeration = JobResult.findJobResults( "job_id = " + job.getJobId().toString(), "execution_time" );
    if ( !enumeration.hasMoreElements() )
	return "The job hasn't started yet.";
    
    JobResult job_result = null;
    while ( enumeration.hasMoreElements() )
	job_result = (JobResult)enumeration.nextElement();
    
    StringBuffer response = new StringBuffer();
    
    switch ( job_result.getResultCode() )
    {
	case JobResult.RESULT_INCOMPLETE:
	    response.append( "Still processing\n" );
	    break;
	case JobResult.RESULT_OK:
	    response.append( "Completed processing\n" );
	    break;
	case JobResult.RESULT_ERROR:
	    response.append( "Aborted processing\n" );
	    break;
    }
    
    if ( job_result.getBigStringId() == null )
	return response.toString();

    BigString message = BigString.findBigString( job_result.getBigStringId() );
    response.append( message );
    return response.toString();
    
}

/**
 * Gets the substitutions that have to be made against the SQL for creating
 * the tables.
 * @param user_input_driver The SQL driver class.
 * @return The String array of substitutions.
 */
public static String[][] getSQLSubstitutions(String user_input_driver)
{
    String subs[][] = null;
    if ( user_input_driver.equals( "connect.microsoft.MicrosoftDriver" ) ||
    user_input_driver.equals( "com.microsoft.jdbc.sqlserver.SQLServerDriver"	) )
    {
        subs = SQL_REPLACE_MS;
    }
    else if ( user_input_driver.equals( "org.postgresql.Driver" ) )
    {
        subs = SQL_REPLACE_PG;
    }
    else if ( user_input_driver.equals( "oracle.jdbc.driver.OracleDriver" ) )
    {
        subs = SQL_REPLACE_OR;
    }
    else if (user_input_driver.equals( "org.hsqldb.jdbcDriver") )
    {
    		subs = SQL_REPLACE_HS;
    }
    return subs;
}


	}
