Initial commit (v2)
This commit is contained in:
parent
36d4aaac81
commit
3a07a83a85
15 changed files with 856 additions and 310 deletions
1
bin/1. rmireg.bat
Executable file
1
bin/1. rmireg.bat
Executable file
|
@ -0,0 +1 @@
|
||||||
|
start rmiregistry
|
3
bin/2. compile.bat
Executable file
3
bin/2. compile.bat
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
set CLASSPATH=%CLASSPATH%;C:\JGroups\jgroups-3.6.0.Final.jar;
|
||||||
|
javac -Xlint:unchecked *.java
|
||||||
|
pause
|
3
bin/3. startServer.bat
Executable file
3
bin/3. startServer.bat
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
set CLASSPATH=%CLASSPATH%;C:\JGroups\jgroups-3.6.0.Final.jar;
|
||||||
|
java -Djava.net.preferIPv4Stack=true AuctionServer
|
||||||
|
pause
|
3
bin/4. startClient.bat
Executable file
3
bin/4. startClient.bat
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
set /p id="Username (leave blank for new user): "
|
||||||
|
java -Djava.net.preferIPv4Stack=true AuctionClient %id%
|
||||||
|
pause
|
|
@ -1 +0,0 @@
|
||||||
javac *.java && start rmiregistry
|
|
|
@ -1 +0,0 @@
|
||||||
javac *.java && java AuctionClient
|
|
|
@ -1 +0,0 @@
|
||||||
javac *.java && java AuctionServer
|
|
118
src/Auction.java
118
src/Auction.java
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* AuctionProg 1.0
|
* AuctionProg 2.0
|
||||||
* Copyright © 2016 Ben Goldsworthy (rumps)
|
* Copyright © 2016 Ben Goldsworthy (rumps)
|
||||||
*
|
*
|
||||||
* A program to facilitate a networked auction system.
|
* A program to facilitate a networked auction system.
|
||||||
|
@ -31,34 +31,37 @@ import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
** @author Ben Goldsworthy (rumps) <bgoldsworthy96 @ gmail.com>
|
||||||
** @version 1.0
|
** @version 2.0
|
||||||
**/
|
**/
|
||||||
public interface Auction extends java.rmi.Remote {
|
public interface Auction extends java.rmi.Remote {
|
||||||
/**
|
/*
|
||||||
** Creates an auction with the given details, generating a new ID for
|
* Methods to validate operations and then remotely invoke methods
|
||||||
** it.
|
* using JGroups.
|
||||||
**
|
*
|
||||||
** @param desc The auction description.
|
*/
|
||||||
** @param owner The auction owner/creator.
|
|
||||||
** @param startingPrice The auction starting price.
|
|
||||||
** @param reserve The auction reserve price.
|
|
||||||
**/
|
|
||||||
public void createAuction(String desc, UserWrapper owner, float startingPrice, float reserve) throws java.rmi.RemoteException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Removes an auction, provided the user calling the method owns it.
|
** Invokes the creation of a new auction.
|
||||||
** If the reserve price was met, also returns the winning bidder.
|
|
||||||
**
|
**
|
||||||
** @param id The ID of the auction to remove.
|
** @param newAuction The new auction to create.
|
||||||
** @param currentUser The user calling the method.
|
|
||||||
** @return The `UserWrapper` of the highest bidder, if applicable.
|
|
||||||
**/
|
**/
|
||||||
public UserWrapper removeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException;
|
public void openNewAuction(AuctionWrapper newAuction) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Bids on a given auction, provided the bid is more than the
|
** Validates that the calling user owns the auction in question, and
|
||||||
** current highest price.
|
** if invokes the closing of the auction, returning the winning
|
||||||
|
** bidder (if applicaable).
|
||||||
|
**
|
||||||
|
** @param id The ID of the auction to bid on.
|
||||||
|
** @param currentUser The user placing the bid.
|
||||||
|
** @return The highest bidder, or `null`.
|
||||||
|
**/
|
||||||
|
public void closeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Validates a bid is higher than the given auctions current price,
|
||||||
|
** and if so invokes the setting the a new bid and bidder.
|
||||||
**
|
**
|
||||||
** @param id The ID of the auction in question.
|
** @param id The ID of the auction in question.
|
||||||
** @param bidder The user bidding on the auction.
|
** @param bidder The user bidding on the auction.
|
||||||
|
@ -67,28 +70,33 @@ public interface Auction extends java.rmi.Remote {
|
||||||
public void bidOnAuction(int id, UserWrapper bidder, float price) throws java.rmi.RemoteException;
|
public void bidOnAuction(int id, UserWrapper bidder, float price) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Retrieves a list of all the auctions.
|
** Invokes the returning of a list of all the current auctions.
|
||||||
**
|
**
|
||||||
** @return An `ArrayList` of `AuctionWrapper`s.
|
** @return An `ArrayList` of `AuctionWrapper`s.
|
||||||
**/
|
**/
|
||||||
public ArrayList<AuctionWrapper> getAuctions() throws java.rmi.RemoteException;
|
public ArrayList<AuctionWrapper> showAllAuctions() throws java.rmi.RemoteException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Gets a user, or creates a new one if non
|
** Accessor Method. Invokes the retrieval of a preexisting user,
|
||||||
** exists with the given details.
|
** if it exists.
|
||||||
**
|
**
|
||||||
** @param name The user's name.
|
** @param username The user's username.
|
||||||
** @param email The user's email address.
|
|
||||||
** @return The relevant `UserWrapper`.
|
** @return The relevant `UserWrapper`.
|
||||||
**/
|
**/
|
||||||
public UserWrapper getUser(String username) throws java.rmi.RemoteException;
|
public UserWrapper getUser(String username) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
public UserWrapper registerUser(String name, String email, String username) throws java.rmi.RemoteException;
|
/**
|
||||||
|
** Tests that the username entered is not already taken, and
|
||||||
|
** invokes the creation of a new user with the given details if not.
|
||||||
|
**
|
||||||
|
** @param newUser The new user to validate and create.
|
||||||
|
** @return The newly-created user.
|
||||||
|
**/
|
||||||
|
public UserWrapper registerUser(UserWrapper newUser) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
public void close() throws java.rmi.RemoteException;
|
/*
|
||||||
|
* Methods that are called by the `AuctionClient` program via RMI.
|
||||||
public PublicKey getPublicKey() throws java.rmi.RemoteException;
|
*/
|
||||||
public void sendPublicKey(PublicKey key, String username) throws java.rmi.RemoteException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Gets the status resulting from the last action
|
** Accessor Method. Gets the status resulting from the last action
|
||||||
|
@ -98,9 +106,55 @@ public interface Auction extends java.rmi.Remote {
|
||||||
**/
|
**/
|
||||||
public String getStatusofLast() throws java.rmi.RemoteException;
|
public String getStatusofLast() throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Accessor Method. Gets the server's public key.
|
||||||
|
**
|
||||||
|
** @return The public key.
|
||||||
|
**/
|
||||||
|
public PublicKey getPublicKey() throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Retrieves a user's public key and writes it to a file.
|
||||||
|
**
|
||||||
|
** @param key The user's public key.
|
||||||
|
** @param usernam The user's username.
|
||||||
|
**/
|
||||||
|
public void sendPublicKey(PublicKey key, String username) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Sends back a user's challenge, signed with the server's private
|
||||||
|
** key.
|
||||||
|
**
|
||||||
|
** @param challenge The user's challenge.
|
||||||
|
** @return The signature.
|
||||||
|
**/
|
||||||
public byte[] challengeServer(byte[] challenge) throws java.rmi.RemoteException;
|
public byte[] challengeServer(byte[] challenge) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Sends a user's a challenge.
|
||||||
|
**
|
||||||
|
** @return The challenge.
|
||||||
|
**/
|
||||||
public byte[] getChallenge() throws java.rmi.RemoteException;
|
public byte[] getChallenge() throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Takes a returned challenge from the user and verifies the
|
||||||
|
** signature.
|
||||||
|
**
|
||||||
|
** @param retChal The returned signature from the user.
|
||||||
|
** @param username The user's username.
|
||||||
|
** @return Whether the user has been verified or not.
|
||||||
|
**/
|
||||||
public boolean returnChallenge(byte[] retChal, String username) throws java.rmi.RemoteException;
|
public boolean returnChallenge(byte[] retChal, String username) throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Creates a new replica of the server.
|
||||||
|
**/
|
||||||
|
public void replicate() throws java.rmi.RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Closes the server and replicas.
|
||||||
|
**/
|
||||||
|
public void close() throws java.rmi.RemoteException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* AuctionProg 1.0
|
* AuctionProg 2.0
|
||||||
* Copyright © 2016 Ben Goldsworthy (rumps)
|
* Copyright © 2016 Ben Goldsworthy (rumps)
|
||||||
*
|
*
|
||||||
* A program to facilitate a networked auction system.
|
* A program to facilitate a networked auction system.
|
||||||
|
@ -37,85 +37,108 @@ import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** @author Ben Goldsworthy (rumps) <bgoldsworthy96 @ gmail.com>
|
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
||||||
** @version 1.0
|
** @version 2.0
|
||||||
**/
|
**/
|
||||||
public class AuctionClient {
|
public class AuctionClient {
|
||||||
// This regex is used to ensure the email address entered is a valid
|
// This regex is used to ensure the email address entered is a valid
|
||||||
// email address format
|
// RFC 2822 email address format
|
||||||
// (Source: http://stackoverflow.com/a/153751/4580273)
|
// (Source: http://stackoverflow.com/a/153751/4580273)
|
||||||
private static final Pattern rfc2822 = Pattern.compile("^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$");
|
private static final Pattern rfc2822 = Pattern.compile("^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$");
|
||||||
|
private static Auction a;
|
||||||
|
private static ArrayList<String> options, debugOptions;
|
||||||
|
private static boolean debugMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Displays the UI.
|
** Sets up the program and runs the event loop.
|
||||||
**
|
**
|
||||||
** @param args Command-line arguments.
|
** @param args Command-line arguments.
|
||||||
**/
|
**/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
debugMode = true;
|
||||||
|
|
||||||
|
displayIntro();
|
||||||
|
|
||||||
// Create the reference to the remote object through the
|
// Create the reference to the remote object through the
|
||||||
// remiregistry. This comes first because if it fails we can
|
// remiregistry. This comes first because if it fails we can
|
||||||
// skip doing everything else.
|
// skip doing everything else.
|
||||||
Auction a = (Auction) Naming.lookup("rmi://localhost/AuctionService");
|
try {
|
||||||
|
a = (Auction) Naming.lookup("rmi://localhost/AuctionService");
|
||||||
|
|
||||||
// Declares some variables that'll be used later on.
|
setOptions();
|
||||||
Scanner in = new Scanner(System.in);
|
|
||||||
UserWrapper currentUser = null;
|
|
||||||
int id;
|
|
||||||
float price;
|
|
||||||
|
|
||||||
// Authenticates the user, if the program is run with a username
|
// Authenticates the user, if the program is run with a username
|
||||||
// as an argument. Otherwise, prompts the user to create a new
|
// as an argument. Otherwise, prompts the user to create a new
|
||||||
// user.
|
// user.
|
||||||
currentUser = login(a, (args.length > 0) ? args[0] : "server");
|
UserWrapper currentUser = login((args.length > 0) ? args[0] : "server");
|
||||||
|
|
||||||
|
eventLoop(currentUser);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loops indefinitely, taking user input for various options.
|
||||||
|
*/
|
||||||
|
private static void eventLoop(UserWrapper currentUser) throws Exception {
|
||||||
|
Scanner in = new Scanner(System.in);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
// Resets the variables after each run through.
|
|
||||||
price = 0.0f;
|
|
||||||
|
|
||||||
printOptions();
|
printOptions();
|
||||||
|
try {
|
||||||
|
int enteredOption = Integer.parseInt(in.nextLine());
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
switch(in.nextLine()) {
|
if(enteredOption < options.size()) {
|
||||||
|
switch(options.get(enteredOption)) {
|
||||||
// This case takes auction details from the user and then
|
// This case takes auction details from the user and then
|
||||||
// creates a new auction with those.
|
// creates a new auction with those.
|
||||||
case "1":
|
case "Create auction":
|
||||||
createNewAuction(a, currentUser);
|
createNewAuction(currentUser);
|
||||||
break;
|
break;
|
||||||
// This case removes the auction with the given ID, provided it
|
// This case removes the auction with the given ID, provided it
|
||||||
// is owned by the current user.
|
// is owned by the current user.
|
||||||
case "2":
|
case "Close auction":
|
||||||
deleteAuction(a, currentUser);
|
closeAuction(currentUser);
|
||||||
break;
|
break;
|
||||||
// This case displays all the currently-available auctions.
|
// This case displays all the currently-available auctions.
|
||||||
case "3":
|
case "View all auctions":
|
||||||
displayAuctions(a);
|
displayAuctions();
|
||||||
break;
|
break;
|
||||||
// This case places a bid on an auction.
|
// This case places a bid on an auction.
|
||||||
case "4":
|
case "Bid on auction":
|
||||||
placeBid(a, currentUser);
|
placeBid(currentUser);
|
||||||
break;
|
break;
|
||||||
// This case exits the program.
|
case "Quit":
|
||||||
case "5":
|
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
break;
|
break;
|
||||||
// The below cases are remote debug commands.
|
default: break;
|
||||||
// This case remotely shuts down the server.
|
}
|
||||||
case "6":
|
} else if(debugMode) {
|
||||||
|
switch(debugOptions.get(enteredOption-options.size())) {
|
||||||
|
case "Replicate server":
|
||||||
|
System.out.println("Server replicating...");
|
||||||
|
a.replicate();
|
||||||
|
System.out.println(a.getStatusofLast());
|
||||||
|
break;
|
||||||
|
case "Close server":
|
||||||
a.close();
|
a.close();
|
||||||
break;
|
break;
|
||||||
default:
|
default: break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (NumberFormatException e) {
|
||||||
System.out.println();
|
System.out.println("\nError: That is not a valid option.\n");
|
||||||
System.out.println("Exception");
|
}
|
||||||
System.out.println(e);
|
|
||||||
}
|
}
|
||||||
System.exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UserWrapper login(Auction a, String username) throws java.rmi.RemoteException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, java.security.SignatureException {
|
/*
|
||||||
|
* Logs a user in if they are preexisting (after authentication), or
|
||||||
|
* prompts a user to create a new user if not.
|
||||||
|
*/
|
||||||
|
private static UserWrapper login(String username) throws java.rmi.RemoteException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, java.security.SignatureException {
|
||||||
UserWrapper user = null;
|
UserWrapper user = null;
|
||||||
|
|
||||||
// If the user has run the program with a username argument,
|
// If the user has run the program with a username argument,
|
||||||
|
@ -169,8 +192,8 @@ public class AuctionClient {
|
||||||
System.out.print("Enter name: ");
|
System.out.print("Enter name: ");
|
||||||
name = in.nextLine();
|
name = in.nextLine();
|
||||||
|
|
||||||
System.out.print("Enter email: ");
|
|
||||||
while (!rfc2822.matcher(email).matches()) {
|
while (!rfc2822.matcher(email).matches()) {
|
||||||
|
System.out.print("Enter email: ");
|
||||||
email = in.nextLine();
|
email = in.nextLine();
|
||||||
if (!rfc2822.matcher(email).matches()) System.out.println("\nError: invalid email address\n");
|
if (!rfc2822.matcher(email).matches()) System.out.println("\nError: invalid email address\n");
|
||||||
}
|
}
|
||||||
|
@ -180,8 +203,13 @@ public class AuctionClient {
|
||||||
username = in.nextLine();
|
username = in.nextLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
user = a.registerUser(name, email, username);
|
try {
|
||||||
|
user = a.registerUser(new UserWrapper(name, email, username));
|
||||||
System.out.println(a.getStatusofLast());
|
System.out.println(a.getStatusofLast());
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
System.out.println(a.getStatusofLast());
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upon a successful user creation, new keys are generated and
|
// Upon a successful user creation, new keys are generated and
|
||||||
|
@ -198,12 +226,44 @@ public class AuctionClient {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the suite of options to present to the user.
|
||||||
|
*/
|
||||||
|
private static void setOptions() {
|
||||||
|
options = new ArrayList<String>();
|
||||||
|
options.add("Create auction");
|
||||||
|
options.add("Close auction");
|
||||||
|
options.add("View all auctions");
|
||||||
|
options.add("Bid on auction");
|
||||||
|
options.add("Quit");
|
||||||
|
|
||||||
|
debugOptions = new ArrayList<String>();
|
||||||
|
debugOptions.add("Replicate server");
|
||||||
|
debugOptions.add("Close server");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints the options for the user.
|
||||||
|
*/
|
||||||
private static void printOptions() {
|
private static void printOptions() {
|
||||||
System.out.println("1\tCreate auction\n2\tDelete auction\n3\tView auctions\n4\tBid on auction\n5\tQuit\n6\tClose server");
|
for(String option: options) {
|
||||||
|
System.out.println(options.indexOf(option) +"\t"+option);
|
||||||
|
}
|
||||||
|
if (debugMode) {
|
||||||
|
System.out.println("DEBUG");
|
||||||
|
int num = options.size();
|
||||||
|
for(String option: debugOptions) {
|
||||||
|
System.out.println((num++)+"\t"+option);
|
||||||
|
}
|
||||||
|
}
|
||||||
System.out.print("Choose option: ");
|
System.out.print("Choose option: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void createNewAuction(Auction a, UserWrapper currentUser) throws java.rmi.RemoteException {
|
/*
|
||||||
|
* Prompts for auction details and then sends it off to be validated
|
||||||
|
* and created.
|
||||||
|
*/
|
||||||
|
private static void createNewAuction(UserWrapper currentUser) throws java.rmi.RemoteException {
|
||||||
float startPrice = 0.0f;
|
float startPrice = 0.0f;
|
||||||
float reservePrice = 0.0f;
|
float reservePrice = 0.0f;
|
||||||
Scanner in = new Scanner(System.in);
|
Scanner in = new Scanner(System.in);
|
||||||
|
@ -220,38 +280,73 @@ public class AuctionClient {
|
||||||
reservePrice = Float.parseFloat(in.nextLine());
|
reservePrice = Float.parseFloat(in.nextLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
a.createAuction(desc, currentUser, startPrice, reservePrice);
|
a.openNewAuction(new AuctionWrapper(0, desc, currentUser, startPrice, reservePrice));
|
||||||
System.out.println(a.getStatusofLast());
|
System.out.println(a.getStatusofLast());
|
||||||
} catch(NumberFormatException ex){
|
} catch(NumberFormatException ex){
|
||||||
System.out.println("\nError: not a valid price\n");
|
System.out.println("\nError: not a valid price\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void deleteAuction(Auction a, UserWrapper currentUser) throws java.rmi.RemoteException {
|
/*
|
||||||
|
* Closes an auction (after sending the request off for validation).
|
||||||
|
*/
|
||||||
|
private static void closeAuction(UserWrapper currentUser) throws java.rmi.RemoteException {
|
||||||
int id;
|
int id;
|
||||||
UserWrapper winner;
|
UserWrapper winner;
|
||||||
Scanner in = new Scanner(System.in);
|
Scanner in = new Scanner(System.in);
|
||||||
|
|
||||||
if (!a.getAuctions().isEmpty()) {
|
if (!a.showAllAuctions().isEmpty()) {
|
||||||
System.out.print("Enter auction number: ");
|
System.out.print("Enter auction number: ");
|
||||||
id = Integer.parseInt(in.nextLine());
|
id = Integer.parseInt(in.nextLine());
|
||||||
|
|
||||||
try {
|
a.closeAuction(id, currentUser);
|
||||||
winner = a.removeAuction(id, currentUser);
|
|
||||||
System.out.println("\nAuction won by: "+winner.getName()+" <"+winner.getEmail()+">\n");
|
|
||||||
} catch(NullPointerException e) {
|
|
||||||
System.out.println(a.getStatusofLast());
|
System.out.println(a.getStatusofLast());
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("\nNo auctions available\n");
|
System.out.println("\nNo auctions available\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void displayAuctions(Auction a) throws java.rmi.RemoteException {
|
/*
|
||||||
if (!a.getAuctions().isEmpty()) {
|
* Displays the program intro preamble.
|
||||||
|
*/
|
||||||
|
private static void displayIntro() {
|
||||||
|
ArrayList<String> lines = new ArrayList<String>();
|
||||||
|
lines.add("");
|
||||||
|
lines.add("AuctionProg 1.0");
|
||||||
|
lines.add("Copyright \u00a9 2016 Ben Goldsworthy (rumps)");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("A program to facilitate a networked auction system");
|
||||||
|
lines.add("This file is part of AuctionProg.");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("AuctionProg is free software: you can redistribute it and/or modify");
|
||||||
|
lines.add("it under the terms of the GNU General Public License as published by");
|
||||||
|
lines.add("the Free Software Foundation, either version 3 of the License, or");
|
||||||
|
lines.add("(at your option) any later version.");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("AuctionProg is distributed in the hope that it will be useful,");
|
||||||
|
lines.add("but WITHOUT ANY WARRANTY; without even the implied warranty of");
|
||||||
|
lines.add("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
|
||||||
|
lines.add("GNU General Public License for more details.");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("You should have received a copy of the GNU General Public License");
|
||||||
|
lines.add("along with AuctionProg. If not, see <http://www.gnu.org/licenses/>.");
|
||||||
|
lines.add("");
|
||||||
|
|
||||||
|
for(String line: lines){
|
||||||
|
System.out.println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Displays all the available auctions.
|
||||||
|
*/
|
||||||
|
private static void displayAuctions() throws java.rmi.RemoteException {
|
||||||
|
if (!a.showAllAuctions().isEmpty()) {
|
||||||
|
System.out.println();
|
||||||
System.out.println("#\tOwner\tPrice\tDesc");
|
System.out.println("#\tOwner\tPrice\tDesc");
|
||||||
for (int i = 0; i < 80; i++) System.out.print("-");
|
for (int i = 0; i < 80; i++) System.out.print("-");
|
||||||
for(AuctionWrapper auction: a.getAuctions()){
|
System.out.println();
|
||||||
|
for(AuctionWrapper auction: a.showAllAuctions()){
|
||||||
System.out.println(auction.getID()+"\t"+auction.getOwner().getUsername()+"\t\u00A3"+String.format("%.2f", auction.getPrice())+"\t"+auction.getDesc());
|
System.out.println(auction.getID()+"\t"+auction.getOwner().getUsername()+"\t\u00A3"+String.format("%.2f", auction.getPrice())+"\t"+auction.getDesc());
|
||||||
}
|
}
|
||||||
System.out.println("");
|
System.out.println("");
|
||||||
|
@ -260,10 +355,13 @@ public class AuctionClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void placeBid(Auction a, UserWrapper currentUser) throws java.rmi.RemoteException {
|
/*
|
||||||
|
* Takes bid details and sends the bid off.
|
||||||
|
*/
|
||||||
|
private static void placeBid(UserWrapper currentUser) throws java.rmi.RemoteException {
|
||||||
Scanner in = new Scanner(System.in);
|
Scanner in = new Scanner(System.in);
|
||||||
|
|
||||||
if (!a.getAuctions().isEmpty()) {
|
if (!a.showAllAuctions().isEmpty()) {
|
||||||
try{
|
try{
|
||||||
int id;
|
int id;
|
||||||
float price;
|
float price;
|
||||||
|
@ -284,9 +382,12 @@ public class AuctionClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads a user's private key from a file.
|
||||||
|
*/
|
||||||
private static PrivateKey readKey(String username) {
|
private static PrivateKey readKey(String username) {
|
||||||
try {
|
try {
|
||||||
FileInputStream keyfis = new FileInputStream(username + "priv.key");
|
FileInputStream keyfis = new FileInputStream("../key/client/"+username + "priv.key");
|
||||||
byte[] encKey = new byte[keyfis.available()];
|
byte[] encKey = new byte[keyfis.available()];
|
||||||
keyfis.read(encKey);
|
keyfis.read(encKey);
|
||||||
keyfis.close();
|
keyfis.close();
|
||||||
|
@ -302,9 +403,12 @@ public class AuctionClient {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Reads the server's public key from a file.
|
||||||
|
*/
|
||||||
private static PublicKey readKey() {
|
private static PublicKey readKey() {
|
||||||
try {
|
try {
|
||||||
FileInputStream keyfis = new FileInputStream("serverpub.key");
|
FileInputStream keyfis = new FileInputStream("../key/client/serverpub.key");
|
||||||
byte[] encKey = new byte[keyfis.available()];
|
byte[] encKey = new byte[keyfis.available()];
|
||||||
keyfis.read(encKey);
|
keyfis.read(encKey);
|
||||||
keyfis.close();
|
keyfis.close();
|
||||||
|
@ -321,16 +425,25 @@ public class AuctionClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a private key to a file.
|
||||||
|
*/
|
||||||
private static void writeKey(PrivateKey pKey, String username) {
|
private static void writeKey(PrivateKey pKey, String username) {
|
||||||
wK(pKey, username, "priv");
|
wK(pKey, username, "priv");
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Writes a public key to a file.
|
||||||
|
*/
|
||||||
private static void writeKey(PublicKey pKey, String username) {
|
private static void writeKey(PublicKey pKey, String username) {
|
||||||
wK(pKey, username, "pub");
|
wK(pKey, username, "pub");
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Actually writes a key to a file.
|
||||||
|
*/
|
||||||
private static void wK(Key pKey, String username, String type) {
|
private static void wK(Key pKey, String username, String type) {
|
||||||
try {
|
try {
|
||||||
byte[] key = pKey.getEncoded();
|
byte[] key = pKey.getEncoded();
|
||||||
FileOutputStream keyfos = new FileOutputStream(username+type+".key");
|
FileOutputStream keyfos = new FileOutputStream("../key/client/"+username+type+".key");
|
||||||
keyfos.write(key);
|
keyfos.write(key);
|
||||||
keyfos.close();
|
keyfos.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* AuctionProg 1.0
|
* AuctionProg 2.0
|
||||||
* Copyright © 2016 Ben Goldsworthy (rumps)
|
* Copyright © 2016 Ben Goldsworthy (rumps)
|
||||||
*
|
*
|
||||||
* A program to facilitate a networked auction system.
|
* A program to facilitate a networked auction system.
|
||||||
|
@ -29,20 +29,31 @@ import java.util.*;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import org.jgroups.JChannel;
|
||||||
|
import org.jgroups.blocks.RpcDispatcher;
|
||||||
|
import org.jgroups.blocks.RequestOptions;
|
||||||
|
import org.jgroups.blocks.ResponseMode;
|
||||||
|
import org.jgroups.View;
|
||||||
|
import org.jgroups.util.*;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
||||||
** @version 1.0
|
** @version 2.0
|
||||||
**/
|
**/
|
||||||
public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements Auction {
|
public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements Auction {
|
||||||
private ArrayList<AuctionWrapper> auctions;
|
private ArrayList<AuctionWrapper> auctions;
|
||||||
private ArrayList<UserWrapper> users;
|
private ArrayList<UserWrapper> users;
|
||||||
String status;
|
String status;
|
||||||
byte[] challenge = new byte[1024];
|
byte[] challenge = new byte[1024];
|
||||||
|
static JChannel channel;
|
||||||
|
static RpcDispatcher disp;
|
||||||
|
static RequestOptions opts = new RequestOptions(ResponseMode.GET_ALL, 5000);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Constructor Method. Required to declare the `RemoteException`
|
** Constructor Method. Required to declare the `RemoteException`
|
||||||
** instance.
|
** instance. Also sets up three replicas and creates a test suite of
|
||||||
|
** three auctions.
|
||||||
**/
|
**/
|
||||||
public AuctionImpl() throws java.rmi.RemoteException {
|
public AuctionImpl() throws java.rmi.RemoteException {
|
||||||
super();
|
super();
|
||||||
|
@ -54,9 +65,32 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
status = "";
|
status = "";
|
||||||
generateKeys();
|
generateKeys();
|
||||||
|
|
||||||
System.out.println("Server start successful.");
|
System.out.println("Server initiliasation successful.");
|
||||||
|
|
||||||
|
try {
|
||||||
|
channel=new JChannel();
|
||||||
|
disp = new RpcDispatcher(channel, this);
|
||||||
|
channel.connect("AuctionProg");
|
||||||
|
|
||||||
|
System.out.println("Creating replicas...");
|
||||||
|
new Replica().start();
|
||||||
|
new Replica().start();
|
||||||
|
new Replica().start();
|
||||||
|
System.out.println("Replicas created.");
|
||||||
|
|
||||||
|
UserWrapper testUser = new UserWrapper("Test", "test@test.com", "test");
|
||||||
|
this.openNewAuction(new AuctionWrapper(1, "test1", testUser, 12.0f, 14.0f));
|
||||||
|
this.openNewAuction(new AuctionWrapper(2, "test2", testUser, 12.0f, 14.0f));
|
||||||
|
this.openNewAuction(new AuctionWrapper(3, "test3", testUser, 12.0f, 14.0f));
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generates the pair of keys for the server's authentication and
|
||||||
|
* writes them to files.
|
||||||
|
*/
|
||||||
private void generateKeys() {
|
private void generateKeys() {
|
||||||
try {
|
try {
|
||||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
|
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
|
||||||
|
@ -73,108 +107,226 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods to validate operations and then remotely invoke methods
|
||||||
|
* using JGroups.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Creates an auction with the given details, generating a new ID for
|
** Invokes the creation of a new auction.
|
||||||
** it.
|
|
||||||
**
|
**
|
||||||
** @param desc The auction description.
|
** @param newAuction The new auction to create.
|
||||||
** @param owner The auction owner/creator.
|
|
||||||
** @param startingPrice The auction starting price.
|
|
||||||
** @param reserve The auction reserve price.
|
|
||||||
**/
|
**/
|
||||||
public void createAuction(String desc, UserWrapper owner, float startingPrice, float reserve) throws java.rmi.RemoteException {
|
public void openNewAuction(AuctionWrapper newAuction) throws java.rmi.RemoteException {
|
||||||
int id = 0;
|
System.out.println("Opening new auction...");
|
||||||
String preamble = "Create new auction: ";
|
try {
|
||||||
|
disp.callRemoteMethods(null, "createAuction", new Object[]{newAuction}, new Class[]{AuctionWrapper.class}, opts);
|
||||||
lines();
|
status = "Auction successfully opened.";
|
||||||
System.out.println(preamble + "begin.");
|
System.out.println("Auction successfully opened.");
|
||||||
|
return;
|
||||||
// Gives the new auction the lowest unclaimed ID.
|
} catch (Exception e) {
|
||||||
for(AuctionWrapper item: auctions){
|
System.out.println(e);
|
||||||
if (id <= item.getID()) {
|
|
||||||
id = item.getID();
|
|
||||||
}
|
}
|
||||||
}
|
status = "Auction could not be opened.";
|
||||||
|
System.out.println("Auction unsuccessfully opened.");
|
||||||
auctions.add(new AuctionWrapper(++id, desc, owner, startingPrice, reserve));
|
|
||||||
System.out.println(preamble + "auction "+id+" successfully created.");
|
|
||||||
status = "Auction no. "+id+" successfully created.";
|
|
||||||
|
|
||||||
System.out.println(preamble + "end.");
|
|
||||||
lines();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Removes an auction, provided the user calling the method owns it.
|
** Validates that the calling user owns the auction in question, and
|
||||||
** If the reserve price was met, also returns the winning bidder.
|
** if invokes the closing of the auction, returning the winning
|
||||||
|
** bidder (if applicaable).
|
||||||
**
|
**
|
||||||
** @param id The ID of the auction to remove.
|
** @param id The ID of the auction to bid on.
|
||||||
** @param currentUser The user calling the method.
|
** @param currentUser The user placing the bid.
|
||||||
** @return The `UserWrapper` of the highest bidder, if applicable.
|
** @return The highest bidder, or `null`.
|
||||||
**/
|
**/
|
||||||
public UserWrapper removeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException {
|
public void closeAuction(int id, UserWrapper currentUser) throws java.rmi.RemoteException {
|
||||||
|
System.out.println("Closing auction #"+id+"...");
|
||||||
AuctionWrapper auction = this.getAuction(id);
|
AuctionWrapper auction = this.getAuction(id);
|
||||||
UserWrapper response = null;
|
UserWrapper response = null;
|
||||||
String preamble = "Close auction "+id+": ";
|
|
||||||
|
|
||||||
lines();
|
|
||||||
System.out.println(preamble + "begin.");
|
|
||||||
|
|
||||||
if (auction.getOwner().getUsername().equals(currentUser.getUsername())) {
|
if (auction.getOwner().getUsername().equals(currentUser.getUsername())) {
|
||||||
System.out.println(preamble + "ownership rights confirmed.");
|
System.out.println("Ownership rights confirmed.");
|
||||||
auctions.remove(auction);
|
try {
|
||||||
System.out.println(preamble + "auction successfully closed.");
|
RspList rsp_list = disp.callRemoteMethods(null, "removeAuction", new Object[]{auction}, new Class[]{AuctionWrapper.class}, opts);
|
||||||
status = "Auction no. "+id+" successfully removed";
|
System.out.println("Auction successfully closed.");
|
||||||
if (auction.getPrice() >= auction.getReserve()) {
|
|
||||||
System.out.println(preamble + "auction closed with winner.");
|
|
||||||
status = "Auction closed - winner";
|
|
||||||
response = auction.getHighestBidder();
|
|
||||||
} else {
|
|
||||||
System.out.println(preamble + "auction closed with no winner.");
|
|
||||||
status = "Auction closed - no winner";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.println(preamble + "invalid ownership rights.");
|
|
||||||
status = "Auction no. "+id+" could not be removed - you do not own this auction";
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(preamble + "end.");
|
response = (UserWrapper)rsp_list.getFirst();
|
||||||
lines();
|
if (response.getUsername().equals("server")) {
|
||||||
return response;
|
status = "Auction closed with no winner";
|
||||||
|
} else {
|
||||||
|
status = "Auction won by: "+response.getName()+" <"+response.getEmail()+">";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = "You do not own this auction.";
|
||||||
|
System.out.println("Auction closing unsuccessful.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Bids on a given auction, provided the bid is more than the
|
** Validates a bid is higher than the given auctions current price,
|
||||||
** current highest price.
|
** and if so invokes the setting the a new bid and bidder.
|
||||||
**
|
**
|
||||||
** @param id The ID of the auction in question.
|
** @param id The ID of the auction in question.
|
||||||
** @param bidder The user bidding on the auction.
|
** @param bidder The user bidding on the auction.
|
||||||
** @param price The amount bid.
|
** @param price The amount bid.
|
||||||
**/
|
**/
|
||||||
public void bidOnAuction(int id, UserWrapper bidder, float price)
|
public void bidOnAuction(int id, UserWrapper bidder, float price) throws java.rmi.RemoteException {
|
||||||
throws java.rmi.RemoteException {
|
|
||||||
AuctionWrapper auction;
|
AuctionWrapper auction;
|
||||||
String preamble = "Bid on auction "+id+": ";
|
System.out.println("Placing bid on auction #"+id+"...");
|
||||||
|
|
||||||
lines();
|
|
||||||
System.out.println(preamble + "begin.");
|
|
||||||
|
|
||||||
|
try {
|
||||||
if ((auction = this.getAuction(id)) != null) {
|
if ((auction = this.getAuction(id)) != null) {
|
||||||
if (price > auction.getPrice()) {
|
if (price > auction.getPrice()) {
|
||||||
this.getAuction(id).setBid(bidder, price);
|
disp.callRemoteMethods(null, "setBid", new Object[]{auction, bidder, price}, new Class[]{AuctionWrapper.class, UserWrapper.class, float.class}, opts);
|
||||||
System.out.println(preamble + "bid successful.");
|
System.out.println("Bid successful.");
|
||||||
status = "Bid successful";
|
status = "Bid successful";
|
||||||
} else {
|
} else {
|
||||||
System.out.println(preamble + "bid less than current highest bid.");
|
System.out.println("Bid unsuccessful.");
|
||||||
status = "Price less than highest bid";
|
status = "Price less than highest bid";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.out.println(preamble + "auction ID not found.");
|
System.out.println("Bid unsuccessful.");
|
||||||
status = "Invalid auction ID";
|
status = "Invalid auction ID";
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println(preamble + "end.");
|
/**
|
||||||
lines();
|
** Invokes the returning of a list of all the current auctions.
|
||||||
|
**
|
||||||
|
** @return An `ArrayList` of `AuctionWrapper`s.
|
||||||
|
**/
|
||||||
|
public ArrayList<AuctionWrapper> showAllAuctions() throws java.rmi.RemoteException {
|
||||||
|
try {
|
||||||
|
RspList rsp_list=disp.callRemoteMethods(null, "getAllAuctions", null, null, opts);
|
||||||
|
return (ArrayList<AuctionWrapper>)rsp_list.getFirst();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Accessor Method. Invokes the retrieval of a preexisting user,
|
||||||
|
** if it exists.
|
||||||
|
**
|
||||||
|
** @param username The user's username.
|
||||||
|
** @return The relevant `UserWrapper`.
|
||||||
|
**/
|
||||||
|
public UserWrapper getUser(String username) throws java.rmi.RemoteException {
|
||||||
|
try {
|
||||||
|
RspList rsp_list=disp.callRemoteMethods(null, "getAllUsers", null, null, opts);
|
||||||
|
for(UserWrapper user: (ArrayList<UserWrapper>)rsp_list.getFirst()) {
|
||||||
|
if (user.getUsername().equals(username)) {
|
||||||
|
status = "Welcome back, "+user.getName()+".";
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
status = "No such user.";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Tests that the username entered is not already taken, and
|
||||||
|
** invokes the creation of a new user with the given details if not.
|
||||||
|
**
|
||||||
|
** @param newUser The new user to validate and create.
|
||||||
|
** @return The newly-created user.
|
||||||
|
**/
|
||||||
|
public UserWrapper registerUser(UserWrapper newUser) throws java.rmi.RemoteException {
|
||||||
|
try {
|
||||||
|
RspList rsp_list=disp.callRemoteMethods(null, "getAllUsers", null, null, opts);
|
||||||
|
|
||||||
|
if (!rsp_list.isEmpty()) {
|
||||||
|
for(UserWrapper user: (ArrayList<UserWrapper>)rsp_list.getFirst()){
|
||||||
|
if (user.getUsername().equals(newUser.getUsername())) {
|
||||||
|
status = "Username taken. Either choose a new username or, if trying to login to an existing account, rerun the program as 'AuctionClient <username>'.";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disp.callRemoteMethods(null, "createUser", new Object[]{newUser}, new Class[]{UserWrapper.class}, opts);
|
||||||
|
status = "New user created. Hello "+newUser.getName()+".";
|
||||||
|
return newUser;
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
status = "Something went wrong";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods that are remotely invoked via RPC on both this and the
|
||||||
|
* `Replica`s due to multicasting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Creates an auction with the given details.
|
||||||
|
**
|
||||||
|
** @param newAuction An `AuctionWrapper` of the new auction.
|
||||||
|
**/
|
||||||
|
private void createAuction(AuctionWrapper newAuction) throws java.rmi.RemoteException {
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
// Gives the new auction the lowest unclaimed ID.
|
||||||
|
for(AuctionWrapper auction: auctions){
|
||||||
|
if (id <= auction.getID()) {
|
||||||
|
id = auction.getID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newAuction.setID(++id);
|
||||||
|
auctions.add(newAuction);
|
||||||
|
status = "Auction no. "+id+" successfully created.";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Removes an auction. If the reserve price was met, also returns
|
||||||
|
** the winning bidder, otherwise an indicative `UserWrapper` with
|
||||||
|
** username of "server".
|
||||||
|
**
|
||||||
|
** @param auction The `AuctionWrapper` of the auction to remove.
|
||||||
|
** @return The `UserWrapper` of the highest bidder, or `null`.
|
||||||
|
**/
|
||||||
|
private UserWrapper removeAuction(AuctionWrapper auction) throws java.rmi.RemoteException {
|
||||||
|
auctions.remove(auction);
|
||||||
|
|
||||||
|
if (auction.getPrice() >= auction.getReserve()) {
|
||||||
|
return auction.getHighestBidder();
|
||||||
|
} else {
|
||||||
|
return new UserWrapper("err", "err", "server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Mutator Method. Sets the bid on an auction.
|
||||||
|
**
|
||||||
|
** @param auction The `AuctionWrapper` of the auction to bid on.
|
||||||
|
** @param user The user bidding on the auction.
|
||||||
|
** @param price The amount the user has bid.
|
||||||
|
**/
|
||||||
|
private void setBid(AuctionWrapper auction, UserWrapper user, float price) {
|
||||||
|
this.getAuction(auction.getID()).setBid(user, price);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Accessor Method. Retrieves a list of all the auctions.
|
||||||
|
**
|
||||||
|
** @return An `ArrayList` of `AuctionWrapper`s.
|
||||||
|
**/
|
||||||
|
private ArrayList<AuctionWrapper> getAllAuctions() {
|
||||||
|
return this.auctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,55 +336,41 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
** @return The `AuctionWrapper` indicated.
|
** @return The `AuctionWrapper` indicated.
|
||||||
**/
|
**/
|
||||||
private AuctionWrapper getAuction(int id) {
|
private AuctionWrapper getAuction(int id) {
|
||||||
for(AuctionWrapper auction: auctions){
|
try {
|
||||||
|
RspList rsp_list=disp.callRemoteMethods(null, "getAllAuctions", null, null, opts);
|
||||||
|
for(AuctionWrapper auction: (ArrayList<AuctionWrapper>)rsp_list.getFirst()) {
|
||||||
if (auction.getID() == id) {
|
if (auction.getID() == id) {
|
||||||
return auction;
|
return auction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Retrieves a list of all the auctions.
|
** Creates a new user.
|
||||||
**
|
**
|
||||||
** @return An `ArrayList` of `AuctionWrapper`s.
|
** @param newUser The new user to create.
|
||||||
**/
|
**/
|
||||||
public ArrayList<AuctionWrapper> getAuctions() throws java.rmi.RemoteException {
|
private void createUser(UserWrapper newUser) {
|
||||||
return auctions;
|
System.out.println("doing it");
|
||||||
|
this.users.add(newUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Gets a user, or creates a new one if non
|
** Gets the list of all users.
|
||||||
** exists with the given details.
|
|
||||||
**
|
**
|
||||||
** @param name The user's name.
|
** @return An `ArrayList` of users.
|
||||||
** @param email The user's email address.
|
|
||||||
** @return The relevant `UserWrapper`.
|
|
||||||
**/
|
**/
|
||||||
public UserWrapper getUser(String username) throws java.rmi.RemoteException {
|
private ArrayList<UserWrapper> getAllUsers() {
|
||||||
for(UserWrapper user: users){
|
return this.users;
|
||||||
if (user.getUsername().equals(username)) {
|
|
||||||
status = "Welcome back, "+user.getName()+".";
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
status = "No such user.";
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserWrapper registerUser(String name, String email, String username) throws java.rmi.RemoteException {
|
/*
|
||||||
for(UserWrapper user: users){
|
* Methods that are called by the `AuctionClient` program via RMI.
|
||||||
if (user.getUsername().equals(username)) {
|
*/
|
||||||
status = "Username taken. Either choose a new username or, if trying to login to an existing account, rerun the program as 'AuctionClient <username>'.";
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UserWrapper user = new UserWrapper(name, email, username);
|
|
||||||
users.add(user);
|
|
||||||
status = "New user created. Hello "+name+".";
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Gets the status resulting from the last action
|
** Accessor Method. Gets the status resulting from the last action
|
||||||
|
@ -244,18 +382,34 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
return "\n"+status+"\n";
|
return "\n"+status+"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Accessor Method. Gets the server's public key.
|
||||||
|
**
|
||||||
|
** @return The public key.
|
||||||
|
**/
|
||||||
public PublicKey getPublicKey() throws java.rmi.RemoteException {
|
public PublicKey getPublicKey() throws java.rmi.RemoteException {
|
||||||
return this.readKey("server");
|
return this.readKey("server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Retrieves a user's public key and writes it to a file.
|
||||||
|
**
|
||||||
|
** @param key The user's public key.
|
||||||
|
** @param usernam The user's username.
|
||||||
|
**/
|
||||||
public void sendPublicKey(PublicKey key, String username) throws java.rmi.RemoteException {
|
public void sendPublicKey(PublicKey key, String username) throws java.rmi.RemoteException {
|
||||||
this.writeKey(key, username);
|
this.writeKey(key, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes the server's private key to a file.
|
||||||
|
*
|
||||||
|
* @param The private key.
|
||||||
|
*/
|
||||||
private static void writeKey(PrivateKey pKey) throws java.rmi.RemoteException {
|
private static void writeKey(PrivateKey pKey) throws java.rmi.RemoteException {
|
||||||
try {
|
try {
|
||||||
byte[] key = pKey.getEncoded();
|
byte[] key = pKey.getEncoded();
|
||||||
FileOutputStream keyfos = new FileOutputStream("../key/serverpriv.key");
|
FileOutputStream keyfos = new FileOutputStream("../key/server/serverpriv.key");
|
||||||
keyfos.write(key);
|
keyfos.write(key);
|
||||||
keyfos.close();
|
keyfos.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -265,10 +419,15 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes the server's public key to a file.
|
||||||
|
*
|
||||||
|
* @param The public key.
|
||||||
|
*/
|
||||||
private static void writeKey(PublicKey pKey) throws java.rmi.RemoteException {
|
private static void writeKey(PublicKey pKey) throws java.rmi.RemoteException {
|
||||||
try {
|
try {
|
||||||
byte[] key = pKey.getEncoded();
|
byte[] key = pKey.getEncoded();
|
||||||
FileOutputStream keyfos = new FileOutputStream("../key/serverpub.key");
|
FileOutputStream keyfos = new FileOutputStream("../key/server/serverpub.key");
|
||||||
keyfos.write(key);
|
keyfos.write(key);
|
||||||
keyfos.close();
|
keyfos.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -278,10 +437,15 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a user's public key to a file.
|
||||||
|
*
|
||||||
|
* @param The public key.
|
||||||
|
*/
|
||||||
private static void writeKey(PublicKey pKey, String username) throws java.rmi.RemoteException {
|
private static void writeKey(PublicKey pKey, String username) throws java.rmi.RemoteException {
|
||||||
try {
|
try {
|
||||||
byte[] key = pKey.getEncoded();
|
byte[] key = pKey.getEncoded();
|
||||||
FileOutputStream keyfos = new FileOutputStream("../key/"+username+"pub.key");
|
FileOutputStream keyfos = new FileOutputStream("../key/server/"+username+"pub.key");
|
||||||
keyfos.write(key);
|
keyfos.write(key);
|
||||||
keyfos.close();
|
keyfos.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -291,9 +455,14 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads the server's private key from a file.
|
||||||
|
*
|
||||||
|
* @return The private key.
|
||||||
|
*/
|
||||||
private static PrivateKey readKey() throws java.rmi.RemoteException {
|
private static PrivateKey readKey() throws java.rmi.RemoteException {
|
||||||
try {
|
try {
|
||||||
FileInputStream keyfis = new FileInputStream("../key/serverpriv.key");
|
FileInputStream keyfis = new FileInputStream("../key/server/serverpriv.key");
|
||||||
byte[] encKey = new byte[keyfis.available()];
|
byte[] encKey = new byte[keyfis.available()];
|
||||||
keyfis.read(encKey);
|
keyfis.read(encKey);
|
||||||
keyfis.close();
|
keyfis.close();
|
||||||
|
@ -310,9 +479,15 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads a user's public key from a file.
|
||||||
|
*
|
||||||
|
* @param username The user's username.
|
||||||
|
* @return The public key.
|
||||||
|
*/
|
||||||
private static PublicKey readKey(String username) throws java.rmi.RemoteException {
|
private static PublicKey readKey(String username) throws java.rmi.RemoteException {
|
||||||
try {
|
try {
|
||||||
FileInputStream keyfis = new FileInputStream("../key/"+username+"pub.key");
|
FileInputStream keyfis = new FileInputStream("../key/server/"+username+"pub.key");
|
||||||
byte[] encKey = new byte[keyfis.available()];
|
byte[] encKey = new byte[keyfis.available()];
|
||||||
keyfis.read(encKey);
|
keyfis.read(encKey);
|
||||||
|
|
||||||
|
@ -330,7 +505,13 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Sends back a user's challenge, signed with the server's private
|
||||||
|
** key.
|
||||||
|
**
|
||||||
|
** @param challenge The user's challenge.
|
||||||
|
** @return The signature.
|
||||||
|
**/
|
||||||
public byte[] challengeServer(byte[] challenge) throws java.rmi.RemoteException {
|
public byte[] challengeServer(byte[] challenge) throws java.rmi.RemoteException {
|
||||||
try {
|
try {
|
||||||
Signature dsa = Signature.getInstance("SHA1withDSA");
|
Signature dsa = Signature.getInstance("SHA1withDSA");
|
||||||
|
@ -347,17 +528,32 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Sends a user's a challenge.
|
||||||
|
**
|
||||||
|
** @return The challenge.
|
||||||
|
**/
|
||||||
public byte[] getChallenge() throws java.rmi.RemoteException {
|
public byte[] getChallenge() throws java.rmi.RemoteException {
|
||||||
challenge = new byte[1024];
|
challenge = new byte[1024];
|
||||||
new Random().nextBytes(this.challenge);
|
new Random().nextBytes(this.challenge);
|
||||||
return this.challenge;
|
return this.challenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Takes a returned challenge from the user and verifies the
|
||||||
|
** signature.
|
||||||
|
**
|
||||||
|
** @param retChal The returned signature from the user.
|
||||||
|
** @param username The user's username.
|
||||||
|
** @return Whether the user has been verified or not.
|
||||||
|
**/
|
||||||
public boolean returnChallenge(byte[] retChal, String username) throws java.rmi.RemoteException {
|
public boolean returnChallenge(byte[] retChal, String username) throws java.rmi.RemoteException {
|
||||||
System.out.println("Authenticating user '"+username+"'...");
|
System.out.println("Authenticating user '"+username+"'...");
|
||||||
for(UserWrapper user: users){
|
System.out.println(users);
|
||||||
if (user.getUsername().equals(username)) {
|
|
||||||
try {
|
try {
|
||||||
|
RspList rsp_list=disp.callRemoteMethods(null, "getAllUsers", null, null, opts);
|
||||||
|
for(UserWrapper user: (ArrayList<UserWrapper>)rsp_list.getFirst()) {
|
||||||
|
if (user.getUsername().equals(username)) {
|
||||||
Signature sig = Signature.getInstance("SHA1withDSA");
|
Signature sig = Signature.getInstance("SHA1withDSA");
|
||||||
sig.initVerify(this.readKey(username));
|
sig.initVerify(this.readKey(username));
|
||||||
|
|
||||||
|
@ -366,24 +562,41 @@ public class AuctionImpl extends java.rmi.server.UnicastRemoteObject implements
|
||||||
boolean verifies = sig.verify(retChal);
|
boolean verifies = sig.verify(retChal);
|
||||||
System.out.println(username+" signature verifies: " + verifies);
|
System.out.println(username+" signature verifies: " + verifies);
|
||||||
return verifies;
|
return verifies;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println();
|
|
||||||
System.out.println("Exception");
|
|
||||||
System.out.println(e);
|
System.out.println(e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("User '"+username+"' not found.");
|
System.out.println("User '"+username+"' not found.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Creates a new replica of the server.
|
||||||
|
**/
|
||||||
|
public void replicate() throws java.rmi.RemoteException {
|
||||||
|
try {
|
||||||
|
new Replica().start();
|
||||||
|
status = "Server replication successful.";
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
status = "Server replication failed.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Closes the server and replicas.
|
||||||
|
**/
|
||||||
public void close() throws java.rmi.RemoteException {
|
public void close() throws java.rmi.RemoteException {
|
||||||
|
System.out.println("Stopping replicas");
|
||||||
|
try {
|
||||||
|
disp.callRemoteMethods(null, "stop", null, null, opts);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
channel.close();
|
||||||
|
disp.stop();
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lines() {
|
|
||||||
for (int i = 0; i < 80; i++) System.out.print("-");
|
|
||||||
System.out.print("\n");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* AuctionProg 1.0
|
* AuctionProg 2.0
|
||||||
* Copyright © 2016 Ben Goldsworthy (rumps)
|
* Copyright © 2016 Ben Goldsworthy (rumps)
|
||||||
*
|
*
|
||||||
* A program to facilitate a networked auction system.
|
* A program to facilitate a networked auction system.
|
||||||
|
@ -25,16 +25,18 @@
|
||||||
**/
|
**/
|
||||||
|
|
||||||
import java.rmi.Naming;
|
import java.rmi.Naming;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
||||||
** @version 1.0
|
** @version 2.0
|
||||||
**/
|
**/
|
||||||
public class AuctionServer {
|
public class AuctionServer {
|
||||||
/**
|
/**
|
||||||
** Constructor Method.
|
** Constructor Method.
|
||||||
**/
|
**/
|
||||||
public AuctionServer() {
|
public AuctionServer() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Auction a = new AuctionImpl();
|
Auction a = new AuctionImpl();
|
||||||
Naming.rebind("rmi://localhost/AuctionService", a);
|
Naming.rebind("rmi://localhost/AuctionService", a);
|
||||||
|
@ -49,6 +51,39 @@ public class AuctionServer {
|
||||||
** @param args Command-line arguments.
|
** @param args Command-line arguments.
|
||||||
**/
|
**/
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
|
displayIntro();
|
||||||
|
|
||||||
new AuctionServer();
|
new AuctionServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Displays the intro preamble to the user.
|
||||||
|
*/
|
||||||
|
private static void displayIntro() {
|
||||||
|
ArrayList<String> lines = new ArrayList<String>();
|
||||||
|
lines.add("");
|
||||||
|
lines.add("AuctionProg 1.0");
|
||||||
|
lines.add("Copyright \u00a9 2016 Ben Goldsworthy (rumps)");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("A program to facilitate a networked auction system");
|
||||||
|
lines.add("This file is part of AuctionProg.");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("AuctionProg is free software: you can redistribute it and/or modify");
|
||||||
|
lines.add("it under the terms of the GNU General Public License as published by");
|
||||||
|
lines.add("the Free Software Foundation, either version 3 of the License, or");
|
||||||
|
lines.add("(at your option) any later version.");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("AuctionProg is distributed in the hope that it will be useful,");
|
||||||
|
lines.add("but WITHOUT ANY WARRANTY; without even the implied warranty of");
|
||||||
|
lines.add("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
|
||||||
|
lines.add("GNU General Public License for more details.");
|
||||||
|
lines.add("");
|
||||||
|
lines.add("You should have received a copy of the GNU General Public License");
|
||||||
|
lines.add("along with AuctionProg. If not, see <http://www.gnu.org/licenses/>.");
|
||||||
|
lines.add("");
|
||||||
|
|
||||||
|
for(String line: lines){
|
||||||
|
System.out.println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* AuctionProg 1.0
|
* AuctionProg 2.0
|
||||||
* Copyright © 2016 Ben Goldsworthy (rumps)
|
* Copyright © 2016 Ben Goldsworthy (rumps)
|
||||||
*
|
*
|
||||||
* A program to facilitate a networked auction system.
|
* A program to facilitate a networked auction system.
|
||||||
|
@ -28,7 +28,7 @@ import java.io.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
||||||
** @version 1.0
|
** @version 2.0
|
||||||
**/
|
**/
|
||||||
public class AuctionWrapper implements Serializable {
|
public class AuctionWrapper implements Serializable {
|
||||||
private int id;
|
private int id;
|
||||||
|
@ -120,4 +120,13 @@ public class AuctionWrapper implements Serializable {
|
||||||
public float getReserve() {
|
public float getReserve() {
|
||||||
return this.reserve;
|
return this.reserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Mutator Method. Sets the auction ID.
|
||||||
|
** @param id The new auction ID.
|
||||||
|
**/
|
||||||
|
public void setID(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
import java.io.*;
|
|
||||||
import java.security.*;
|
|
||||||
|
|
||||||
class GenSig {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
/* Generate a DSA signature */
|
|
||||||
|
|
||||||
if (args.length != 1) {
|
|
||||||
System.out.println("Usage: GenSig nameOfFileToSign");
|
|
||||||
} else try {
|
|
||||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
|
|
||||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
|
|
||||||
keyGen.initialize(1024, random);
|
|
||||||
|
|
||||||
KeyPair pair = keyGen.generateKeyPair();
|
|
||||||
PrivateKey priv = pair.getPrivate();
|
|
||||||
PublicKey pub = pair.getPublic();
|
|
||||||
|
|
||||||
Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");
|
|
||||||
dsa.initSign(priv);
|
|
||||||
|
|
||||||
FileInputStream fis = new FileInputStream(args[0]);
|
|
||||||
BufferedInputStream bufin = new BufferedInputStream(fis);
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int len;
|
|
||||||
while ((len = bufin.read(buffer)) >= 0) {
|
|
||||||
dsa.update(buffer, 0, len);
|
|
||||||
};
|
|
||||||
bufin.close();
|
|
||||||
|
|
||||||
byte[] realSig = dsa.sign();
|
|
||||||
|
|
||||||
/* save the signature in a file */
|
|
||||||
FileOutputStream sigfos = new FileOutputStream("sig");
|
|
||||||
sigfos.write(realSig);
|
|
||||||
sigfos.close();
|
|
||||||
|
|
||||||
/* save the public key in a file */
|
|
||||||
byte[] key = pub.getEncoded();
|
|
||||||
FileOutputStream keyfos = new FileOutputStream("suepk");
|
|
||||||
keyfos.write(key);
|
|
||||||
keyfos.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("Caught exception " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
158
src/Replica.java
Executable file
158
src/Replica.java
Executable file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* AuctionProg 2.0
|
||||||
|
* Copyright © 2016 Ben Goldsworthy (rumps)
|
||||||
|
*
|
||||||
|
* A program to facilitate a networked auction system.
|
||||||
|
*
|
||||||
|
* This file is part of AuctionProg.
|
||||||
|
*
|
||||||
|
* AuctionProg is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* AuctionProg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with AuctionProg. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
** This class represents a User.
|
||||||
|
**/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import org.jgroups.JChannel;
|
||||||
|
import org.jgroups.blocks.RpcDispatcher;
|
||||||
|
import org.jgroups.blocks.RequestOptions;
|
||||||
|
import org.jgroups.blocks.ResponseMode;
|
||||||
|
import org.jgroups.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
||||||
|
** @version 2.0
|
||||||
|
**/
|
||||||
|
public class Replica {
|
||||||
|
JChannel channel;
|
||||||
|
RpcDispatcher disp;
|
||||||
|
RequestOptions opts=new RequestOptions(ResponseMode.GET_ALL, 5000);
|
||||||
|
|
||||||
|
private ArrayList<AuctionWrapper> auctions;
|
||||||
|
private ArrayList<UserWrapper> users;
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Connects to the channel and sets itself up.
|
||||||
|
**/
|
||||||
|
public void start() {
|
||||||
|
try {
|
||||||
|
channel = new JChannel();
|
||||||
|
disp = new RpcDispatcher(channel, this);
|
||||||
|
channel.connect("AuctionProg");
|
||||||
|
|
||||||
|
auctions = new ArrayList<AuctionWrapper>();
|
||||||
|
users = new ArrayList<UserWrapper>();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Shuts down the replica.
|
||||||
|
**/
|
||||||
|
public void stop() {
|
||||||
|
channel.close();
|
||||||
|
disp.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Creates a new auction.
|
||||||
|
**
|
||||||
|
** @param newAuction The new auction to create.
|
||||||
|
**/
|
||||||
|
public void createAuction(AuctionWrapper newAuction) {
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
// Gives the new auction the lowest unclaimed ID.
|
||||||
|
for(AuctionWrapper auction: auctions){
|
||||||
|
if (id <= auction.getID()) {
|
||||||
|
id = auction.getID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newAuction.setID(++id);
|
||||||
|
auctions.add(newAuction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Removes an auction from the list.
|
||||||
|
**
|
||||||
|
** @param auction The auction to remove.
|
||||||
|
** @return The highest-bidding user (if applicable).
|
||||||
|
**/
|
||||||
|
public UserWrapper removeAuction(AuctionWrapper auction) {
|
||||||
|
auctions.remove(auction);
|
||||||
|
|
||||||
|
if (auction.getPrice() >= auction.getReserve()) {
|
||||||
|
return auction.getHighestBidder();
|
||||||
|
} else {
|
||||||
|
return new UserWrapper("err", "err", "server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Mutator Method. Sets a new bid on an auction.
|
||||||
|
**
|
||||||
|
** @param auction The auction to bid on.
|
||||||
|
** @param user The user bidding.
|
||||||
|
** @param price The user's bid.
|
||||||
|
**/
|
||||||
|
public void setBid(AuctionWrapper auction, UserWrapper user, float price) {
|
||||||
|
this.getAuction(auction.getID()).setBid(user, price);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Accessor Method. Gets all the auctions.
|
||||||
|
**
|
||||||
|
** @return The list of auctions.
|
||||||
|
**/
|
||||||
|
public ArrayList<AuctionWrapper> getAllAuctions() {
|
||||||
|
return this.auctions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Gets an auction by ID.
|
||||||
|
**
|
||||||
|
** @param id The auction ID.
|
||||||
|
** @return The auction requested, or `null`.
|
||||||
|
**/
|
||||||
|
private AuctionWrapper getAuction(int id) {
|
||||||
|
for(AuctionWrapper auction: auctions) {
|
||||||
|
if (auction.getID() == id) {
|
||||||
|
return auction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Accessor Method. Gets the list of all users.
|
||||||
|
**
|
||||||
|
** @return The list of users.
|
||||||
|
**/
|
||||||
|
public ArrayList<UserWrapper> getAllUsers() {
|
||||||
|
return this.users;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Creates a new user.
|
||||||
|
**
|
||||||
|
** @param The new user to create.
|
||||||
|
**/
|
||||||
|
public void createUser(UserWrapper newUser) {
|
||||||
|
this.users.add(newUser);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* AuctionProg 1.0
|
* AuctionProg 2.0
|
||||||
* Copyright © 2016 Ben Goldsworthy (rumps)
|
* Copyright © 2016 Ben Goldsworthy (rumps)
|
||||||
*
|
*
|
||||||
* A program to facilitate a networked auction system.
|
* A program to facilitate a networked auction system.
|
||||||
|
@ -28,7 +28,7 @@ import java.io.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
** @author Ben Goldsworthy (rumps) <me+auctionprog@bengoldsworthy.net>
|
||||||
** @version 1.0
|
** @version 2.0
|
||||||
**/
|
**/
|
||||||
public class UserWrapper implements Serializable {
|
public class UserWrapper implements Serializable {
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -49,19 +49,23 @@ public class UserWrapper implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Returns the user's name.
|
** Accessor Method. Returns the user's name.
|
||||||
** @param The user's name.
|
** @return The user's name.
|
||||||
**/
|
**/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Accessor Method. Returns the user's username.
|
||||||
|
** @return The user's username.
|
||||||
|
**/
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return this.username;
|
return this.username;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Accessor Method. Returns the user's email address.
|
** Accessor Method. Returns the user's email address.
|
||||||
** @param The user's email address.
|
** @return The user's email address.
|
||||||
**/
|
**/
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return this.email;
|
return this.email;
|
||||||
|
|
Reference in a new issue