package edu.vt.marian.WebGate; import java.io.*; import java.net.*; import java.util.*; import edu.vt.marian.common.*; /** Class name: user Class description: this class represent a marian user an user object can provide many services (more than 30 at this time), many services are provided by it's component classes, but we hide this to the outside and provide a single user concept to them, in this way future changes to the internal implementation are easy to make and will bring no or little effects to classed which use the services provided by this class. Author: Jianxin Zhao Finished time: ????, 1998 Known bugs: none Platform: jdk1.1.5 under UNIX ---------------------------------------------------------------------------- Modified By: Richard Baker Date Modified: May 1, 2000 Platform Modified With: Microsoft Visual J++ 6.0 under Windows NT */ public class user { /** this is just for debugging */ Debug debug; /** this is the login name of the user */ private String login_name; /** this is the full name of the user */ private String full_name; /** this is the id of the user */ private String id; /** this is the current password of the user */ private String password; /** this is the address of the user */ private address addr; /** this is the folders database */ private folder_manager fm; /** this is the money manager of this user */ private money_manager mm; /** this is the preferences of the user */ private preference pre; /** this is the priority of this user, at least two kinds of priorities exist in the system currently: super user and normal user */ private String priority; /** this will record the time when this user is created */ private Date time; /** this is the last access time of this user, this is used for manage memory consumed by a user object. */ private Date last_access_time; /** this is the directory name from which the user object is read out it's also used to write user information back when method unload is called */ private String dir; /** this flag will tell whether or not all the information about this user object has been loaded from disk, used for memory management */ private boolean load_flag; /** this constructor will create an user object based on the information provided */ public user(String username, String full_name, String password, String userid, String dir, Debug debug) { // first initialize data members init(); this.debug = debug; set_user_name(username); set_full_name(full_name); set_password(password); set_id(userid); this.dir = new String(dir); // we need to create the directory here File file = new File(dir); try { file.mkdir(); } catch (SecurityException e) { debug.dumpTrace("class user: cannot create directory"); } fm = new folder_manager(username, dir + File.separator + "folder_manager", debug); pre = new preference(debug); addr = new address(debug); mm = new money_manager(debug); load_flag = true; } /** this constructor will create an user object from the specified directory */ public user(String dir, Debug debug) { // first initialize data members init(); this.debug = debug; // read the user name, password, id and priority information // from the directory File user_config = new File(dir + File.separator + "user.cfg"); String line; String s; String s1; StringTokenizer st; BufferedReader br; try { FileReader fr = new FileReader(user_config); br = new BufferedReader(fr); line = br.readLine(); while (line != null) { st = new StringTokenizer(line); if (st.hasMoreTokens()) // in case an empty line is encoutered { s = st.nextToken(); if (! s.startsWith("#")) // lines begin with "#" will be ignored { // process user_name if (s.equals("user_name")) { s1 = line.substring(9); set_user_name(s1.trim()); } // process full_name else if (s.equals("full_name")) { s1 = line.substring(9); set_full_name(s1.trim()); } // process password else if (s.equals("password")) { s1 = line.substring(8); set_password(s1.trim()); } // process userid else if (s.equals("id")) { s1 = line.substring(2); set_id(s1.trim()); } // process priority else if (s.equals("priority")) { s1 = line.substring(8); set_priority(s1.trim()); } // process creation time else if (s.equals("time")) { s1 = line.substring(4); set_creation_time(s1.trim()); } } } line = br.readLine(); }// end while br.close(); } catch (IOException e3) { debug.dumpTrace("error reading data from " + user_config.getAbsolutePath()); } // other user information will be read out when this object is accessed load_flag = false; this.dir = new String(dir); } /** this constructor will create a user object from a stream, this might be helpful for remote management in the future. (not implemented yet) */ public user(DataInputStream dis, Debug debug) { } /** this method will delete all the information about this user (not implemented yet) */ public String delete() { return null; // this function will be implemented in the future } /** this method will tell whether or not this is a valid user */ public String is_valid() { // more an more checking about a valid user will be added later if (get_user_name() == null) { return "user name empty"; } if (get_password() == null) { return "password empty"; } if (get_password().length() <= 4) { return "password too short"; } if (get_id() == null) { return "user id empty"; } // only four kinds of checking is performed now return "OK"; } /** this method will set the id of this user */ private String set_id(String id) { this.id = id; return "OK"; } /** this method will return the id of this user */ public String get_id() { return id; } /** this method will set the login name of this user */ private String set_user_name(String name) { this.login_name = name; return "OK"; } /** this method will return the name of this user */ public String get_user_name() { return login_name; } /** this method will set the password of this user */ public String set_password(String password) { this.password = password; return "OK"; } /** this method will return the password of this user */ public String get_password() { return password; } /** this method will set the full name of this user */ public String set_full_name(String full_name) { this.full_name = full_name; return "OK"; } /** this method will return the full name of the user */ public String get_full_name() { return full_name; } /** * This method returns all the folders in the user's folder database. */ public Vector get_folders() { // load related information if necessary load(); return fm.get_folders(); } /** * This method sets the current folder in the user's folder database. */ public String set_curr_folder(String folder_number) { // load related information if necessary load(); return fm.set_curr_folder(folder_number); } /** * This method returns the current folder in the user's folder database. */ public folder get_curr_folder() { // load related information if necessary load(); return fm.get_curr_folder(); } /** * This method returns a specified folder in the user's folder database. */ public folder get_folder(String folder_number) { // load related information if necessary load(); return fm.get_folder(folder_number); } /** * This method creates a new folder in the user's folder database. */ public String new_folder(String name) { // load related information if necessary load(); return fm.set_curr_folder(fm.new_folder(name)); } /** * This method opens a specified folder in the user's folder database. */ public String open_folder(String folder_number) { // load related information if necessary load(); fm.set_curr_folder(folder_number); return get_curr_folder().open(); } /** * This method closes a specified folder in the user's folder database. */ public String close_folder(String folder_number) { // load related information if necessary load(); fm.set_curr_folder(folder_number); return get_curr_folder().close(); } /** * This method sets the name of a specified folder to a specified name * in the user's folder database. */ public String set_folder_name(String name) { // load related information if necessary load(); return fm.set_name(name); } /** * This method returns the name of the current folder in the user's * folder database. */ public String get_folder_name() { // load related information if necessary load(); return fm.get_name(); } /** * This method deletes a specified folder from the user's folder database. */ public String delete_folder() { // load related information if necessary load(); return fm.delete_folder(); } /** * This method deletes all the folders in the user's folder database. */ public String delete_folders() { // load related information if necessary load(); return fm.delete_folders(); } /** * This method moves a specified folder to another specified folder * in the user's folder database. */ public String move_folder_to(String folder_number, String parent_folder) { // load related information if necessary load(); fm.set_curr_folder(folder_number); return fm.move_folder_to(parent_folder); } /** * This method returns the children of a specified folder in * the user's folder database. */ public String[] get_children(String folder_number) { // load related information if necessary load(); return fm.get_children(folder_number); } /** * This method moves a specified query to from the current folder to * another specified folder in the user's folder database. */ public String move_query_to(String query_number, String parent_folder) { // load related information if necessary load(); return fm.move_query_to(query_number, parent_folder); } /** * This method returns the HTML code for the folder list. */ public String get_folder_list_html() { // load related information if necessary load(); return fm.get_folder_list_html(); } /** * This method returns the HTML code for the drop down box of folders. */ public String get_drop_box_html() { // load related information if necessary load(); return fm.get_drop_box_html(); } /** this method will submit a query to the user, the return value is the query number of the query for in user */ public String submit_query(query_data qd) { // load related information if necessary load(); // first record this query to money manager mm.record(qd); // submit it to query database return get_curr_folder().submit_query(qd); } /** this method will return the total number of queries performed by this user */ public String get_number_queries() { // load related information if necessary load(); return get_curr_folder().get_number_queries(); } /** this method will return the number of queries the user performed before the specified time */ public String get_number_queries_before(String time) { // load related information if necessary load(); return get_curr_folder().get_number_queries_before(time); } /** this method will return the number of queries the user performed after the specified time */ public String get_number_queries_after(String time) { // load related information if necessary load(); return get_curr_folder().get_number_queries_after(time); } /** this method will return the number of queries the user performed from the start time to the end time */ public String get_number_queries_between(String start_time, String end_time) { // load related information if necessary load(); return get_curr_folder().get_number_queries_between(start_time, end_time); } /** this method will return the number of queries in this object which are matched with the specified query data */ public String get_number_queries(general_query_data gqd) { // load related information if necessary load(); return get_curr_folder().get_number_queries(gqd); } /** this method will return a query of this user, the query is identiofied by the parameter query_number, we use string for it since this allow the queries performed by a user exceed the integer limit (more than 2 billion in java I believe), though this is unlikely. */ public query get_query(String query_number) { // load related information if necessary load(); return get_curr_folder().get_query(query_number); } /** this method will return all the queries the user performed before the specified time */ public Vector get_queries_before(String time) { // load related information if necessary load(); return get_curr_folder().get_queries_before(time); } /** this method will return all the queries thew user performed from the specified time to now */ public Vector get_queries_after(String time) { // load related information if necessary load(); return get_curr_folder().get_queries_after(time); } /** this method will return all the queries the user performed from the start time to the end time */ public Vector get_queries_between(String start_time, String end_time) { // load related information if necessary load(); return get_curr_folder().get_queries_between(start_time, end_time); } /** this method will return all the queries in this object */ public Vector get_queries() { // load related information if necessary load(); return get_curr_folder().get_queries(); } /** this method will return all the queries in this object which are matched with the specified query data */ public Vector get_queries(general_query_data gqd) { // load related information if necessary load(); return get_curr_folder().get_queries(gqd); } /** this method will delete the query with the specified query number from this user */ public String delete_query(String query_number) { // load related information if necessary load(); return get_curr_folder().delete_query(query_number); } /** this method will delete all the queries from this object which are matched with the specified query data */ public String delete_queries(general_query_data gqd) { // load related information if necessary load(); return get_curr_folder().delete_queries(gqd); } /** this method will return all the preference names of this user */ public Vector get_preference_names() { // load related information if necessary load(); return pre.get_names(); } /** this method will return the value of the specified preference of this user */ public String get_preference_value(String name) { // load related information if necessary load(); return pre.get_value(name); } /** this method will add the specified preference with the specified value to this user */ public String add_preference(String name, String value) { // load related information if necessary load(); return pre.add(name, value); } /** this method will set the specified preference with the specified value */ public String set_preference(String name, String value) { // load related information if necessary load(); return pre.set(name, value); } /** this method will delete the specified preference from this user */ public String delete_preference(String name) { // load related information if necessary load(); return pre.delete(name); } /** this method will return the current balance of the user, at least this is helpful when our client want to see how much money left on his/her account */ public String get_current_balance() { // load related information if necessary load(); return mm.get_current_balance(); } /** this method will return the transaction history of this user before the specified time */ public String get_transaction_history_before(String time) { // load related information if necessary load(); return mm.get_transaction_history_before(time); } /** this method will return the transaction history of yhis user after the specified time */ public String get_transaction_history_after(String time) { // load related information if necessary load(); return mm.get_transaction_history_after(time); } /** this method will return the transaction history of this user from the start time to the end time */ public String get_transaction_history_between(String start_time, String end_time) { // load related information if necessary load(); return mm.get_transaction_history_between(start_time, end_time); } /** this method will deposit the specified amount of money to the user's account */ public String deposit(String amount) { // load related information if necessary load(); return mm.deposit(amount); } /** this method will reduce the specified amount of money from the user's account */ public String withdraw(String amount) { // load related information if necessary load(); return mm.withdraw(amount); } /** this method will return all the rate types of this user */ public Vector get_rate_types() { // load related information if necessary load(); return mm.get_rate_types(); } /** this method will add the specified rate type with the specified value to the user */ public String add_rate(String type, String value) { // load related information if necessary load(); return mm.add_rate(type, value); } /** this method will set the specified rate type to the specified value */ public String set_rate(String type, String value) { // load related information if necessary load(); return mm.set_rate(type, value); } /** this method will delete the specified rate from the user */ public String delete_rate(String type) { // load related information if necessary load(); return mm.delete_rate(type); } /** this method will return the value of the specified type of this user */ public String get_rate_value(String type) { // load related information if necessary load(); return mm.get_rate_value(type); } /** this method will set the overdraft value for the user */ public String set_overdraft(String amount) { // load related information if necessary load(); return mm.set_overdraft(amount); } /** this method will return the overdraft amount allowed to this user */ public String get_overdraft() { // load related information if necessary load(); return mm.get_overdraft(); } /** this method will set the priority of this user */ public String set_priority(String priority) { if (priority == null) { this.priority = null; return "ok"; } this.priority = new String(priority); return "OK"; } /** this method will get the priority of this user */ public String get_priority() { if (priority == null) { return null; } return new String(priority); } /** this method will return all the address types currently in this object */ public Vector get_address_types() { // load related information if necessary load(); return addr.get_types(); } /** this method will add a new address type with the specified value into this object */ public String add_address(String type, String value) { // load related information if necessary load(); return addr.add(type, value); } /** this method will set the specified type of address to the specified value */ public String set_address(String type, String value) { // load related information if necessary load(); return addr.set(type, value); } /** this method will delete the specified address type from this object */ public String delete_address(String type) { // load related information if necessary load(); return addr.delete(type); } /** this method will return the value of the specified address type */ public String get_address_value(String type) { // load related information if necessary load(); return addr.get_value(type); } /** this method will set the creation time of this object, this might be useful when an user object is passed from one machine to another */ private String set_creation_time(String time) { this.time = new Date(Long.parseLong(time)); return "OK"; } /** this method will return the time when this user is created */ public String get_creation_time() { return Long.toString(time.getTime()); } /** this method will return the inactive time of this user object, this is used for memory management -- we need to write user information back to disk when this user object is not accessed for some time */ public long get_inactive_time() { Date current_time = new Date(); return (current_time.getTime() - last_access_time.getTime()); } /** this method will load the user information from disk */ private synchronized String load() { // load the user information last_access_time = new Date(); if (load_flag) { // the information has been loaded to memory, so do nothing here return "ok"; } // load the information // load folder manager of this user fm = new folder_manager(full_name, dir + File.separator + "folder_manager", debug); // load this user's preference pre = new preference(dir + File.separator + "preference", debug); // load this user's address addr = new address(dir + File.separator + "address", debug); // load this user's money manager mm = new money_manager(dir + File.separator + "money_manager", debug); load_flag = true; return "ok"; } /** this method will write most of the user information back to disk if the user object has been inactive for the specified time, this is used for memory management */ public synchronized String unload(long time) { // unload the user infotmation if (! load_flag) { // the information has been unloaded, do nothing // debug.dumpTrace("user information has already been unloaded"); return "ok"; } if (get_inactive_time() <= time) { // here we assume the user is still active, but some queries may // have been inactive for a long time, write them back to disk // debug.dumpTrace("unload query manager"); fm.unload(time); return "ok"; } // debug.dumpTrace("unload user information"); // need to write the information back to disk // unload the folder manager fm.save(dir + File.separator + "folder_manager"); fm = null; // unload the preference pre.save(dir + File.separator + "preference"); pre = null; // unload the address addr.save(dir + File.separator + "address"); addr = null; // unload the money manager mm.save(dir + File.separator + "money_manager"); mm = null; load_flag = false; return "ok"; } /** this method will print the content of this object to a stream, this might be helpful for remote management in the future. (not implemented yet) */ public String to_stream(DataOutputStream dos) { return null; // not implemented yet } /** this method will save the information about this user to the specified directory */ public synchronized String save(String dir) { // create the directory File file = new File(dir); try { file.mkdir(); } catch (SecurityException e) { debug.dumpTrace("can not create directory"); } // write user name, password, id and priority to the directory FileOutputStream fos = null; try { fos = new FileOutputStream(dir + File.separator + "user.cfg", false); } catch (IOException e3) { debug.dumpTrace("error opening user config file to write"); } PrintWriter pw = new PrintWriter(fos); pw.println("user_name " + get_user_name()); pw.println("full_name " + get_full_name()); pw.println("password " + get_password()); pw.println("id " + get_id()); pw.println("priority " + get_priority()); pw.println("time " + get_creation_time()); pw.flush(); pw.close(); if ((this.dir != null) && this.dir.equals(dir) && (! load_flag)) { // information has been written back to disk, do nothing return "ok"; } // load information if necessary load(); // save the folder manager fm.save(dir + File.separator + "folder_manager"); // save the preference pre.save(dir + File.separator + "preference"); // save the address addr.save(dir + File.separator + "address"); // save the money manager mm.save(dir + File.separator + "money_manager"); return "ok"; } /** this method will initialize data members of this object */ public void init() { debug = null; login_name = null; full_name = null; password = null; id = null; priority = null; fm = null; pre = null; addr = null; mm = null; time = new Date(); last_access_time = new Date(); dir = null; } // there are many other methods which can be added here just for the // completeness of the user concept, but due to the time limit, I'm // afraid I can't do so at this time. I can give several example s // of the methods which can be added later: // get/set_sex() // get_age() // get/set_birthday() // get/set_occupation() // get/set_marry_status() // get/set_salary() // get/set_citizen() // get/set_hight() // get/set_weight(), ... // at least those are useful for user characteristics analyzings. }