package com.robonobo.wang.server.controller; import static com.robonobo.common.util.TextUtil.*; import java.io.IOException; import java.util.*; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import com.robonobo.common.util.TextUtil; import com.robonobo.wang.beans.Coin; import com.robonobo.wang.beans.DenominationPrivate; import com.robonobo.wang.client.LucreFacade; import com.robonobo.wang.proto.WangProtocol.CoinListMsg; import com.robonobo.wang.proto.WangProtocol.CoinMsg; import com.robonobo.wang.proto.WangProtocol.DepositStatusMsg; import com.robonobo.wang.proto.WangProtocol.DepositStatusMsg.Status; import com.robonobo.wang.server.UserAccount; import com.robonobo.wang.server.dao.*; @Controller public class DepositCoinsController extends BaseController implements InitializingBean { @Autowired private DenominationDao denominationDao; @Autowired private DoubleSpendDao doubleSpendDao; private LucreFacade lucre; private Map<Integer, DenominationPrivate> denomPrivs; @Override public void afterPropertiesSet() throws Exception { lucre = new LucreFacade(); try { List<DenominationPrivate> denoms = denominationDao.getDenomsPrivate(); denomPrivs = new HashMap<Integer, DenominationPrivate>(); for (DenominationPrivate denom : denoms) { denomPrivs.put(denom.getDenom(), denom); } } catch (DAOException e) { throw new ServletException(e); } } @RequestMapping(value = "/depositCoins") @Transactional(rollbackFor=Exception.class) public void depositCoins(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserAccount user = getAuthUser(req, resp); if (user == null) { send401(req, resp); return; } resp.setContentType("application/data"); CoinListMsg.Builder clBldr = CoinListMsg.newBuilder(); readFromInput(clBldr, req); CoinListMsg cl = clBldr.build(); double coinValue = 0; DepositStatusMsg.Builder dBldr = DepositStatusMsg.newBuilder(); dBldr.setStatus(Status.OK); try { List<String> deposCoins = new ArrayList<String>(); for (CoinMsg coinMsg : cl.getCoinList()) { DenominationPrivate denom = denomPrivs.get(coinMsg.getDenom()); Coin coin = new Coin(coinMsg); if (denom == null) throw new IOException("Malformed coin, no denomination"); boolean lucreSaysOk = lucre.verifyCoin(denom, coin); boolean isDoubleSpend = doubleSpendDao.isDoubleSpend(coinMsg.getCoinId()); if (!lucreSaysOk || isDoubleSpend) { dBldr.setStatus(Status.Error); dBldr.addBadCoinId(coinMsg.getCoinId()); continue; } coinValue += getDenomValue(coin.getDenom()); deposCoins.add(coinMsg.getCoinId()); } if (dBldr.getStatus() == Status.OK) { for (String coinId : deposCoins) { doubleSpendDao.add(coinId); } log.info("User " + user.getEmail() + " deposited " + deposCoins.size() + " coins worth " + WANG_CHAR + coinValue); try { UserAccount lockUser = uaDao.getAndLockUserAccount(user.getEmail()); lockUser.setBalance(lockUser.getBalance() + coinValue); uaDao.putUserAccount(lockUser); } catch (DAOException e) { throw new IOException(e); } } else log.warn("User " + user.getEmail() + " got bad coin error while attempting to deposit coins"); } catch (DAOException e) { throw new IOException(e); } writeToOutput(dBldr.build(), resp); resp.setStatus(HttpServletResponse.SC_OK); } private double getDenomValue(Integer denom) { return Math.pow(2, denom); } }