/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.aries.samples.ariestrader.web; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.io.IOException; import java.math.BigDecimal; import java.net.URL; import java.util.ArrayList; import org.apache.aries.samples.ariestrader.api.TradeDBManager; import org.apache.aries.samples.ariestrader.api.TradeServicesManager; import org.apache.aries.samples.ariestrader.api.TradeServiceUtilities; import org.apache.aries.samples.ariestrader.api.TradeServices; import org.apache.aries.samples.ariestrader.api.persistence.*; import org.apache.aries.samples.ariestrader.util.*; /** * TradeBuildDB uses operations provided by the TradeApplication to * (a) create the Database tables * (b) populate a AriesTrader database without creating the tables. * Specifically, a new AriesTrader User population is created using * UserIDs of the form "uid:xxx" where xxx is a sequential number * (e.g. uid:0, uid:1, etc.). New stocks are also created of the form "s:xxx", * again where xxx represents sequential numbers (e.g. s:1, s:2, etc.) */ public class TradeBuildDB { private static TradeServicesManager tradeServicesManager = null; private static TradeDBManager tradeDBManager = null; /** * Populate a Trade DB using standard out as a log */ public TradeBuildDB() throws Exception { this(new java.io.PrintWriter(System.out), false); } /** * Re-create the AriesTrader db tables and populate them OR just populate a * AriesTrader DB, logging to the provided output stream */ public TradeBuildDB(java.io.PrintWriter out, boolean createTables) throws Exception { String symbol, companyName; int errorCount = 0; // Give up gracefully after 10 errors if (tradeServicesManager == null) { tradeServicesManager = TradeServiceUtilities.getTradeServicesManager(); } TradeServices tradeServices = tradeServicesManager.getTradeServices(); if (tradeDBManager == null) { tradeDBManager = TradeServiceUtilities.getTradeDBManager(); } // TradeStatistics.statisticsEnabled=false; // disable statistics out.println("<HEAD><BR><EM> TradeBuildDB: Building AriesTrader Database...</EM><BR>" + "This operation will take several minutes. Please wait...</HEAD>"); out.println("<BODY>"); if (createTables) { boolean success = false; String dbProductName = null; String fileLocation = null; URL ddlFile = null; Object[] sqlBuffer = null; // Find out the Database being used try { dbProductName = tradeDBManager.checkDBProductName(); } catch (Exception e) { Log.error(e, "TradeBuildDB: Unable to check DB Product name"); } if (dbProductName == null) { out.println("<BR>TradeBuildDB: **** Unable to check DB Product name," + "please check Database/AppServer configuration and retry ****</BR></BODY>"); return; } // Locate DDL file for the specified database try { out.println("<BR>TradeBuildDB: **** Database Product detected: " + dbProductName + " ****</BR>"); if (dbProductName.startsWith("DB2/")) { // if db is DB2 fileLocation = File.separatorChar + "dbscripts" + File.separatorChar + "db2" + File.separatorChar + "Table.ddl"; } else if (dbProductName.startsWith("Apache Derby")) { // if db is Derby fileLocation = File.separatorChar + "dbscripts" + File.separatorChar + "derby" + File.separatorChar + "Table.ddl"; } else if (dbProductName.startsWith("Oracle")) { // if the Db is Oracle fileLocation = File.separatorChar + "dbscripts" + File.separatorChar + "oracle" + File.separatorChar + "Table.ddl"; } else { // Unsupported "Other" Database fileLocation = File.separatorChar + "dbscripts" + File.separatorChar + "other" + File.separatorChar + "Table.ddl"; out.println("<BR>TradeBuildDB: **** This Database is " + "unsupported/untested use at your own risk ****</BR>"); } ddlFile = this.getClass().getResource(fileLocation); } catch (Exception e) { Log.error(e, "TradeBuildDB: Unable to locate DDL file for the specified database"); out.println("<BR>TradeBuildDB: **** Unable to locate DDL file for " + "the specified database ****</BR></BODY>"); return; } // parse the DDL file and fill the SQL commands into a buffer try { sqlBuffer = parseDDLToBuffer(ddlFile); } catch (Exception e) { Log.error(e, "TradeBuildDB: Unable to parse DDL file"); out.println("<BR>TradeBuildDB: **** Unable to parse DDL file for the specified "+ "database ****</BR></BODY>"); return; } if ((sqlBuffer == null) || (sqlBuffer.length == 0)) { 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>"); return; } // send the sql commands buffer to drop and recreate the AriesTrader tables out.println("<BR>TradeBuildDB: **** Dropping and Recreating the AriesTrader tables... ****</BR>"); try { success = tradeDBManager.recreateDBTables(sqlBuffer, out); } catch (Exception e) { Log.error(e, "TradeBuildDB: Unable to drop and recreate AriesTrader Db Tables, "+ "please check for database consistency before continuing"); } if (!success) { out.println("<BR>TradeBuildDB: **** Unable to drop and recreate AriesTrader Db Tables, "+ "please check for database consistency before continuing ****</BR></BODY>"); return; } out.println("<BR>TradeBuildDB: **** AriesTrader tables successfully created! ****</BR><BR><b> "+ "Please Stop and Re-start your AriesTrader application (or your application server) and then use "+ "the \"Repopulate AriesTrader Database\" link to populate your database.</b></BR><BR><BR></BODY>"); return; } // end of createDBTables out.println("<BR>TradeBuildDB: **** Creating " + TradeConfig.getMAX_QUOTES() + " Quotes ****</BR>"); // Attempt to delete all of the Trade users and Trade Quotes first try { tradeDBManager.resetTrade(true); } catch (Exception e) { Log.error(e, "TradeBuildDB: Unable to delete Trade users "+ "(uid:0, uid:1, ...) and Trade Quotes (s:0, s:1, ...)"); } for (int i = 0; i < TradeConfig.getMAX_QUOTES(); i++) { symbol = "s:" + i; companyName = "S" + i + " Incorporated"; try { tradeServices.createQuote(symbol, companyName, new java.math.BigDecimal(TradeConfig.rndPrice())); if (i % 10 == 0) { out.print("....." + symbol); if (i % 100 == 0) { out.println(" -<BR>"); out.flush(); } } } catch (Exception e) { if (errorCount++ >= 10) { 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(); Log.error(e, error); throw e; } } } out.println("<BR>"); out.println("<BR>**** Registering " + TradeConfig.getMAX_USERS() + " Users **** "); errorCount = 0; // reset for user registrations // Registration is a formal operation in Trade 2. for (int i = 0; i < TradeConfig.getMAX_USERS(); i++) { String userID = "uid:" + i; String fullname = TradeConfig.rndFullName(); String email = TradeConfig.rndEmail(userID); String address = TradeConfig.rndAddress(); String creditcard = TradeConfig.rndCreditCard(); double initialBalance = (double) (TradeConfig.rndInt(100000)) + 200000; if (i == 0) { initialBalance = 1000000; // uid:0 starts with a cool million. } try { AccountDataBean accountData = tradeServices.register(userID, "xxx", fullname, address, email, creditcard, new BigDecimal(initialBalance)); if (accountData != null) { if (i % 50 == 0) { out.print("<BR>Account# " + accountData.getAccountID() + " userID=" + userID); } // 0-MAX_HOLDING (inclusive), avg holdings per user = (MAX-0)/2 int holdings = TradeConfig.rndInt(TradeConfig.getMAX_HOLDINGS() + 1); double quantity = 0; for (int j = 0; j < holdings; j++) { symbol = TradeConfig.rndSymbol(); quantity = TradeConfig.rndQuantity(); tradeServices.buy(userID, symbol, quantity, TradeConfig.orderProcessingMode); } if (i % 50 == 0) { out.println(" has " + holdings + " holdings."); out.flush(); } } else { out.println("<BR>UID " + userID + " already registered.</BR>"); out.flush(); } } catch (Exception e) { if (errorCount++ >= 10) { String error = "Populate Trade DB aborting after 10 user registration errors. "+ "Check the log for details. <BR><BR> Exception is: <BR>" + e.toString(); Log.error(e, error); throw e; } } } // end-for out.println("</BODY>"); } public Object[] parseDDLToBuffer(URL ddlFile) throws Exception { BufferedReader br = null; InputStreamReader ir = null; ArrayList sqlBuffer = new ArrayList(30); // initial capacity 30 assuming we have 30 ddl-sql statements to read try { if (Log.doTrace()) Log.traceEnter("TradeBuildDB:parseDDLToBuffer - " + ddlFile); ir = new InputStreamReader(ddlFile.openStream()); br = new BufferedReader(ir); String s; String sql = new String(); while ((s = br.readLine()) != null) { s = s.trim(); if ((s.length() != 0) && (s.charAt(0) != '#')) // Empty lines or lines starting with "#" are ignored { sql = sql + " " + s; if (s.endsWith(";")) // reached end of sql statement { sql = sql.replace(';', ' '); // remove the semicolon sqlBuffer.add(sql); sql = ""; } } } } catch (IOException ex) { Log.error("TradeBuildDB:parseDDLToBuffer Exeception during open/read of File: " + ddlFile, ex); throw ex; } finally { if (br != null) { try { br.close(); } catch (IOException ex) { Log.error("TradeBuildDB:parseDDLToBuffer Failed to close BufferedReader", ex); } } } return sqlBuffer.toArray(); } public static void main(String args[]) throws Exception { new TradeBuildDB(); } }