StoreBid.java

240 lines | 8.76 kB Blame History Raw Download
/*
 * Copyright (C) 2002-2009  OW2 Consortium
 *
 * This file is part of dcsj-rubis (below referred to as "this program").
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.rice.rubis.servlets;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * This servlet records a bid in the database and display
 * the result of the transaction.
 * It must be called this way :
 * <pre>
 * http://..../StoreBid?itemId=aa&userId=bb&minBid=cc&maxQty=dd&bid=ee&maxBid=ff&qty=gg
 *   where: aa is the item id
 *          bb is the user id
 *          cc is the minimum acceptable bid for this item
 *          dd is the maximum quantity available for this item
 *          ee is the user bid
 *          ff is the maximum bid the user wants
 *          gg is the quantity asked by the user
 * </pre>
 *
 * @author <a href="mailto:cecchet@rice.edu">Emmanuel Cecchet</a>
 * @author <a href="mailto:julie.marguerite@inrialpes.fr">Julie Marguerite</a>
 * @author <a href="mailto:marco.guazzone@gmail.com">Marco Guazzone</a>
 */

public class StoreBid extends RubisHttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        this.doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        int userId; // item id
        int itemId; // user id
        float minBid; // minimum acceptable bid for this item
        float bid; // user bid
        float maxBid; // maximum bid the user wants
        int maxQty; // maximum quantity available for this item
        int qty; // quantity asked by the user
        ServletPrinter sp = null;
        PreparedStatement stmt = null;
        Connection conn = null;

        sp = new ServletPrinter(response, "StoreBid");

		/* Get and check all parameters */

        String value = request.getParameter("userId");
        if ((value == null) || (value.equals(""))) {
            this.printError("You must provide a user identifier!", sp);
            return;
        }
        userId = Integer.parseInt(value);

        value = request.getParameter("itemId");
        if ((value == null) || (value.equals(""))) {
            this.printError("You must provide an item identifier!", sp);
            return;
        }
        itemId = Integer.parseInt(value);

        value = request.getParameter("minBid");
        if ((value == null) || (value.equals(""))) {
            this.printError("You must provide a minimum bid!", sp);
            return;
        }
        minBid = Float.parseFloat(value);

        value = request.getParameter("bid");
        if ((value == null) || (value.equals(""))) {
            this.printError("You must provide a bid!", sp);
            return;
        }
        bid = Float.parseFloat(value);

        value = request.getParameter("maxBid");
        if ((value == null) || (value.equals(""))) {
            this.printError("You must provide a maximum bid!", sp);
            return;
        }
        maxBid = Float.parseFloat(value);

        value = request.getParameter("maxQty");
        if ((value == null) || (value.equals(""))) {
            this.printError("You must provide a maximum quantity!", sp);
            return;
        }
        maxQty = Integer.parseInt(value);

        value = request.getParameter("qty");
        if ((value == null) || (value.equals(""))) {
            this.printError("You must provide a quantity!", sp);
            return;
        }
        qty = Integer.parseInt(value);

		/* Check for invalid values */

        if (maxQty <= 0 || qty > maxQty) {
            this.printError("You cannot request " + qty + " items because only " + maxQty + " are proposed!", sp);
            return;
        }
        if (bid < minBid) {
            this.printError("Your bid of $" + bid + " is not acceptable because it is below the $" + minBid + " minimum bid!", sp);
            return;
        }
        if (maxBid < minBid) {
            this.printError("Your maximum bid of $" + maxBid + " is not acceptable because it is below the $" + minBid + " minimum bid!", sp);
            return;
        }
        if (maxBid < bid) {
            this.printError("Your maximum bid of $" + maxBid + " is not acceptable because it is below your current bid of $" + bid + "!", sp);
            return;
        }
        try {
            conn = this.getConnection();
            conn.setAutoCommit(false);
            String now = TimeManagement.currentDateToString();
            stmt = conn.prepareStatement("INSERT INTO bids VALUES (NULL,?,?,?,?,?,?)");
            stmt.setInt(1, userId);
            stmt.setInt(2, itemId);
            stmt.setInt(3, qty);
            stmt.setFloat(4, bid);
            stmt.setFloat(5, maxBid);
            stmt.setString(6, now);
            stmt.executeUpdate();
            stmt.close();
            // update the number of bids and the max bid for the item
            PreparedStatement update = null;
            try {
                stmt = conn.prepareStatement("SELECT nb_of_bids, max_bid FROM items WHERE id=?");
                stmt.setInt(1, itemId);
                ResultSet rs = stmt.executeQuery();
                if (rs.first()) {
                    int nbOfBids = rs.getInt("nb_of_bids");
                    nbOfBids++;
                    float oldMaxBid = rs.getFloat("max_bid");
                    if (bid > oldMaxBid) {
                        oldMaxBid = bid;
                        update =
                                conn.prepareStatement("UPDATE items SET max_bid=?, nb_of_bids=? WHERE id=?");
                        update.setFloat(1, maxBid);
                        update.setInt(2, nbOfBids);
                        update.setInt(3, itemId);
                        update.executeUpdate();
                        update.close();
                    } else {
                        update = conn.prepareStatement("UPDATE items SET nb_of_bids=? WHERE id=?");
                        update.setInt(1, nbOfBids);
                        update.setInt(2, itemId);
                        update.executeUpdate();
                        update.close();
                    }
                } else {
                    conn.rollback();
                    this.printError("Couldn't find the item.", sp);
                    this.closeConnection(stmt, conn);
                    return;
                }
            } catch (Exception ex) {
                conn.rollback();
                this.printError("Failed to update nb of bids and max bid: " + ex, sp);
                if (update != null) {
                    update.close();
                }
                this.closeConnection(stmt, conn);
                return;
            }
            conn.commit();

            sp.printHTMLheader("RUBiS: Bidding result");
            sp.printHTML("<center><h2>Your bid has been successfully processed.</h2></center>\n");
            sp.printHTMLfooter();
        } catch (Exception e) {
            this.printError("Error while storing the bid: " + e, sp);
            try {
                conn.rollback();
            } catch (Exception se) {
                this.printError("Transaction rollback failed: " + e, sp);
            }
        }
        this.closeConnection(stmt, conn);
    }

    @Override
    protected int getPoolSize() {
        return Config.StoreBidPoolSize;
    }

    /**
     * Close both statement and connection.
     */
    private void closeConnection(PreparedStatement stmt, Connection conn) {
        try {
            if (stmt != null) {
                stmt.close(); // close statement
            }
            if (conn != null) {
                conn.setAutoCommit(true);
                this.releaseConnection(conn);
            }
        } catch (Exception ignore) {
        }
    }

    /**
     * Display an error message.
     *
     * @param errorMsg the error message value
     */
    private void printError(String errorMsg, ServletPrinter sp) {
        this.printError("Store Bid", errorMsg, sp);
    }
}