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 }