001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.samples.daytrader.web;
018    
019    import java.io.BufferedReader;
020    import java.io.File;
021    import java.io.FileReader;
022    import java.io.IOException;
023    import java.math.BigDecimal;
024    import java.util.ArrayList;
025    
026    import org.apache.geronimo.samples.daytrader.direct.TradeDirect;
027    import org.apache.geronimo.samples.daytrader.util.*;
028    
029    import org.apache.geronimo.samples.daytrader.*;
030    
031    /**
032     * TradeBuildDB uses operations provided by the TradeApplication to (a) create the Database tables
033     * (b)populate a DayTrader database without creating the tables. Specifically, a 
034     * new DayTrader User population is created using UserIDs of the form "uid:xxx" 
035     * where xxx is a sequential number (e.g. uid:0, uid:1, etc.). New stocks are also created of the 
036     * form "s:xxx", again where xxx represents sequential numbers (e.g. s:1, s:2, etc.)
037     */
038    public class TradeBuildDB {
039    
040            private boolean verbose = true;
041            private TradeConfig t = new TradeConfig();
042    
043            /**
044              * Populate a Trade DB using standard out as a log
045              */
046            public TradeBuildDB() throws Exception {
047                    this(new java.io.PrintWriter(System.out), null);
048            }
049    
050            /**
051                    * Re-create the DayTrader db tables and populate them OR just populate a DayTrader DB, logging to the provided output stream
052                    */
053            public TradeBuildDB(java.io.PrintWriter out, String warPath) throws Exception {
054                    String symbol, companyName;
055                    int errorCount = 0; // Give up gracefully after 10 errors
056                    TradeAction tradeAction = new TradeAction();
057    
058                    //  TradeStatistics.statisticsEnabled=false;  // disable statistics
059                    out.println(
060                            "<HEAD><BR><EM> TradeBuildDB: Building DayTrader Database...</EM><BR> This operation will take several minutes. Please wait...</HEAD>");
061                    out.println("<BODY>");
062                    
063                    if (warPath != null)
064                    {       
065                            //out.println("<BR>TradeBuildDB: **** warPath= "+warPath+" ****</BR></BODY>");
066                            
067                            TradeDirect tradeDirect = new TradeDirect();
068                            boolean success = false;
069                            String dbProductName = null;
070                            File ddlFile = null;
071                            Object[] sqlBuffer = null;
072                            
073                            //Find out the Database being used
074                            try
075                            {
076                                    dbProductName = tradeDirect.checkDBProductName();
077                            }
078                            catch (Exception e)
079                            {
080                                    Log.error(e, "TradeBuildDB: Unable to check DB Product name");
081                            }
082                            if (dbProductName == null)
083                            {
084                                    out.println("<BR>TradeBuildDB: **** Unable to check DB Product name, please check Database/AppServer configuration and retry ****</BR></BODY>");
085                                    return;
086                            }
087                            
088                            //Locate DDL file for the specified database
089                            try
090                            {
091                                    out.println("<BR>TradeBuildDB: **** Database Product detected: "+dbProductName+" ****</BR>");
092                                    if (dbProductName.startsWith("DB2/")) // if db is DB2
093                                    {
094                                            ddlFile = new File(warPath+File.separatorChar+"dbscripts"+File.separatorChar+"db2"+File.separatorChar+"Table.ddl");
095                                    }
096                                    else if (dbProductName.startsWith("Apache Derby")) //if db is Derby
097                                    {
098                                            ddlFile = new File(warPath+File.separatorChar+"dbscripts"+File.separatorChar+"derby"+File.separatorChar+"Table.ddl");
099                                    }
100                                    else if (dbProductName.startsWith("Oracle")) // if the Db is Oracle
101                                    {
102                                            ddlFile = new File(warPath+File.separatorChar+"dbscripts"+File.separatorChar+"oracle"+File.separatorChar+"Table.ddl");
103                                    }
104                                    else // Unsupported "Other" Database
105                                    {
106                                            ddlFile = new File(warPath+File.separatorChar+"dbscripts"+File.separatorChar+"other"+File.separatorChar+"Table.ddl");
107                                            out.println("<BR>TradeBuildDB: **** This Database is unsupported/untested use at your own risk ****</BR>");
108                                    }
109                                    
110                                    if (!ddlFile.exists())
111                                    {
112                                            Log.error("TradeBuildDB: DDL file doesnt exist at path "+ ddlFile.getCanonicalPath()+" , please provide the file and retry");
113                                            out.println("<BR>TradeBuildDB: DDL file doesnt exist at path <I>"+ ddlFile.getCanonicalPath()+"</I> , please provide the file and retry ****</BR></BODY>");
114                                            return;
115                                    }
116                                    out.println("<BR>TradeBuildDB: **** The DDL file at path <I>"+ ddlFile.getCanonicalPath()+"</I> will be used ****</BR>");
117                                    out.flush();
118                            }
119                            catch (Exception e)
120                            {
121                                    Log.error(e, "TradeBuildDB: Unable to locate DDL file for the specified database");
122                                    out.println("<BR>TradeBuildDB: **** Unable to locate DDL file for the specified database ****</BR></BODY>");
123                                    return;
124                            }
125                            
126                            //parse the DDL file and fill the SQL commands into a buffer
127                            try
128                            {
129                                    sqlBuffer = parseDDLToBuffer(ddlFile);
130                            }
131                            catch (Exception e)
132                            {
133                                    Log.error(e, "TradeBuildDB: Unable to parse DDL file");
134                                    out.println("<BR>TradeBuildDB: **** Unable to parse DDL file for the specified database ****</BR></BODY>");
135                                    return;
136                            }
137                            if ((sqlBuffer == null)||(sqlBuffer.length == 0))
138                            {
139                                    out.println("<BR>TradeBuildDB: **** Parsing DDL file returned empty buffer, please check that a valid DB specific DDL file is available and retry ****</BR></BODY>");
140                                    return;
141                            }
142                            
143                            // send the sql commands buffer to drop and recreate the Daytrader tables
144                            out.println("<BR>TradeBuildDB: **** Dropping and Recreating the DayTrader tables... ****</BR>");
145                            try
146                            {
147                                    success = tradeDirect.recreateDBTables(sqlBuffer, out);
148                            }
149                            catch (Exception e)
150                            {
151                                    Log.error(e, "TradeBuildDB: Unable to drop and recreate DayTrader Db Tables, please check for database consistency before continuing");
152                            }
153                            if (!success)
154                            {
155                                    out.println("<BR>TradeBuildDB: **** Unable to drop and recreate DayTrader Db Tables, please check for database consistency before continuing ****</BR></BODY>");
156                                    return;
157                            }
158                            out.println("<BR>TradeBuildDB: **** DayTrader tables successfully created! ****</BR><BR><b> Please Stop and Re-start your Daytrader application (or your application server) and then use the \"Repopulate Daytrader Database\" link to populate your database.</b></BR><BR><BR></BODY>");
159                            return;
160                    } // end of createDBTables
161                    
162                    out.println("<BR>TradeBuildDB: **** Creating " + TradeConfig.getMAX_QUOTES() + " Quotes ****</BR>");
163                    //Attempt to delete all of the Trade users and Trade Quotes first
164                    try
165                    {
166                            tradeAction.resetTrade(true);
167                    }
168                    catch (Exception e)
169                    {
170                            Log.error(e, "TradeBuildDB: Unable to delete Trade users (uid:0, uid:1, ...) and Trade Quotes (s:0, s:1, ...)");
171                    }
172                    for (int i = 0; i < TradeConfig.getMAX_QUOTES(); i++) {
173                            symbol = "s:" + i;
174                            companyName = "S" + i + " Incorporated";
175                            try {
176                                    QuoteDataBean quoteData =
177                                            tradeAction.createQuote(
178                                                    symbol,
179                                                    companyName,
180                                                    new java.math.BigDecimal(TradeConfig.rndPrice()));
181                                    if (i % 10 == 0) {
182                                            out.print("....." + symbol);
183                                            if (i % 100 == 0) {
184                                                    out.println(" -<BR>");
185                                                    out.flush();
186                                            }
187                                    }
188                            } catch (Exception e) {
189                                    if (errorCount++ >= 10) {
190                                            String error = "Populate Trade DB aborting after 10 create quote errors. Check the EJB datasource configuration. Check the log for details <BR><BR> Exception is: <BR> " + e.toString();                                              
191                                            Log.error(e, error);
192                                            throw e;
193                                    }       
194                            }
195                    }
196                    out.println("<BR>");
197                    out.println("<BR>**** Registering " + TradeConfig.getMAX_USERS() + " Users **** ");
198                    errorCount = 0; //reset for user registrations
199    
200                    // Registration is a formal operation in Trade 2. 
201                    for (int i = 0; i < TradeConfig.getMAX_USERS(); i++) {
202                            String userID = "uid:" + i;
203                            String fullname = TradeConfig.rndFullName();
204                            String email = TradeConfig.rndEmail(userID);
205                            String address = TradeConfig.rndAddress();
206                            String creditcard = TradeConfig.rndCreditCard();
207                            double initialBalance = (double) (TradeConfig.rndInt(100000)) + 200000;
208                            if (i == 0) {
209                                    initialBalance = 1000000; // uid:0 starts with a cool million.
210                            }
211                            try {
212                                    AccountDataBean accountData =
213                                            tradeAction.register(
214                                                    userID,
215                                                    "xxx",
216                                                    fullname,
217                                                    address,
218                                                    email,
219                                                    creditcard,
220                                                    new BigDecimal(initialBalance));
221                                    String results;
222                                    if (accountData != null) {
223                                            if (i % 50 == 0) {
224                                                    out.print("<BR>Account# " +accountData.getAccountID() + " userID=" + userID);
225                                            } // end-if
226    
227                                            int holdings = TradeConfig.rndInt(TradeConfig.getMAX_HOLDINGS()+1); // 0-MAX_HOLDING (inclusive), avg holdings per user = (MAX-0)/2
228                                            double quantity = 0;
229                                            OrderDataBean orderData;
230                                            for (int j = 0; j < holdings; j++) {
231                                                    symbol = TradeConfig.rndSymbol();
232                                                    quantity = TradeConfig.rndQuantity();
233                                                    orderData = tradeAction.buy(userID, symbol, quantity, TradeConfig.orderProcessingMode);
234                                            } // end-for
235                                            if (i % 50 == 0) {
236                                                    out.println(" has " + holdings + " holdings.");
237                                                    out.flush();
238                                            } // end-if
239                                    } else {
240                                            out.println("<BR>UID " + userID + " already registered.</BR>");
241                                            out.flush();
242                                    } // end-if
243    
244                            } catch (Exception e) {
245                                    if (errorCount++ >= 10) {
246                                            AccountProfileDataBean accountProfileData = null;
247    
248                                            String error = "Populate Trade DB aborting after 10 user registration errors. Check the log for details. <BR><BR> Exception is: <BR>" + e.toString();
249                                            Log.error(e, error);
250                                            throw e;                                        
251                                    }
252                            }
253                    } // end-for
254                    out.println("</BODY>");
255            }
256            
257            public Object[] parseDDLToBuffer(File ddlFile) throws Exception 
258            {
259            BufferedReader br = null;
260            ArrayList sqlBuffer = new ArrayList(30); //initial capacity 30 assuming we have 30 ddl-sql statements to read
261    
262            try 
263            {
264                    if (Log.doTrace()) Log.traceEnter("TradeBuildDB:parseDDLToBuffer - " + ddlFile);
265                    
266                            br = new BufferedReader(new FileReader(ddlFile));
267                String s;
268                            String sql = new String();
269                while ((s = br.readLine()) != null) 
270                {
271                                    s = s.trim();
272                                    if ((s.length() != 0) && (s.charAt(0) != '#'))  // Empty lines or lines starting with "#" are ignored
273                                    {
274                                            sql = sql +" "+ s;
275                                            if (s.endsWith(";")) // reached end of sql statement
276                                            {
277                                                    sql = sql.replace(';', ' '); //remove the semicolon
278                                                    //System.out.println (sql);
279                                                    sqlBuffer.add(sql);
280                                                    sql = "";
281                                            }
282                                    }
283                }
284            } 
285            catch (IOException ex)
286            {
287                    Log.error("TradeBuildDB:parseDDLToBuffer Exeception during open/read of File: " + ddlFile, ex);
288                    throw ex;
289            }
290            finally 
291            {
292                if (br != null) 
293                {
294                    try 
295                    {
296                        br.close();
297                    } catch(IOException ex) 
298                    {
299                            Log.error("TradeBuildDB:parseDDLToBuffer Failed to close BufferedReader", ex);
300                    }
301                }
302            }
303            return sqlBuffer.toArray();
304            }
305            
306            public static void main(String args[]) throws Exception {
307                    new TradeBuildDB();
308    
309            }
310    }