/* * JBoss, Home of Professional Open Source * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mobicents.seam.actions; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.ejb.Remove; import javax.ejb.Stateful; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContextType; import javax.servlet.sip.Address; import javax.servlet.sip.SipApplicationSession; import javax.servlet.sip.SipFactory; import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipURI; import javax.servlet.sip.URI; import org.jboss.mobicents.seam.listeners.MediaConnectionListener; import org.jboss.mobicents.seam.model.Customer; import org.jboss.mobicents.seam.model.Inventory; import org.jboss.mobicents.seam.model.Order; import org.jboss.mobicents.seam.model.OrderLine; import org.jboss.mobicents.seam.model.Product; import org.jboss.mobicents.seam.util.TTSUtils; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Begin; import org.jboss.seam.annotations.End; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.bpm.CreateProcess; import org.jboss.seam.annotations.security.Restrict; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.faces.FacesMessages; import org.jboss.seam.log.Log; import org.mobicents.mscontrol.MsConnection; import org.mobicents.mscontrol.MsPeer; import org.mobicents.mscontrol.MsPeerFactory; import org.mobicents.mscontrol.MsProvider; import org.mobicents.mscontrol.MsSession; @Stateful @Name("checkout") public class CheckoutAction implements Checkout, Serializable { @Logger private Log log; private static final long serialVersionUID = -4651884454184474207L; @PersistenceContext(type = PersistenceContextType.EXTENDED) EntityManager em; @In(value = "currentUser", required = false) Customer customer; @In(create = true) ShoppingCart cart; @Out(scope = ScopeType.CONVERSATION, required = false) Order currentOrder; @Out(scope = ScopeType.CONVERSATION, required = false) Order completedOrder; @Out(scope = ScopeType.BUSINESS_PROCESS, required = false) long orderId; @Out(scope = ScopeType.BUSINESS_PROCESS, required = false) BigDecimal amount = BigDecimal.ZERO; @Out(value = "customer", scope = ScopeType.BUSINESS_PROCESS, required = false) String customerName; @Out(value = "customerfullname", scope = ScopeType.BUSINESS_PROCESS, required = false) String customerFullName; @Out(value = "cutomerphone", scope = ScopeType.BUSINESS_PROCESS, required = false) String customerPhone; //jboss 5, compliant with sip spec 1.1 //@Resource(mappedName="java:comp/env/sip/shopping-demo/SipFactory") SipFactory sipFactory; //jboss 4 @Resource(mappedName="java:/sip/shopping-demo/SipFactory") SipFactory sipFactory; @Begin(nested = true, pageflow = "checkout") public void createOrder() { currentOrder = new Order(); for (OrderLine line : cart.getCart()) { currentOrder.addProduct(em.find(Product.class, line.getProduct() .getProductId()), line.getQuantity()); } currentOrder.calculateTotals(); cart.resetCart(); } @End @CreateProcess(definition = "OrderManagement", processKey = "#{completedOrder.orderId}") @Restrict("#{identity.loggedIn}") public void submitOrder() { try { completedOrder = purchase(customer, currentOrder); orderId = completedOrder.getOrderId(); amount = completedOrder.getNetAmount(); customerName = completedOrder.getCustomer().getUserName(); customerFullName = completedOrder.getCustomer().getFirstName() + " " + completedOrder.getCustomer().getLastName(); customerPhone = completedOrder.getCustomer().getPhone(); fireEvent(orderId, amount, customerFullName, customerPhone); } catch (InsufficientQuantityException e) { for (Product product : e.getProducts()) { Contexts.getEventContext().set("prod", product); FacesMessages.instance().addFromResourceBundle( "checkoutInsufficientQuantity"); } } } private Order purchase(Customer customer, Order order) throws InsufficientQuantityException { order.setCustomer(customer); order.setOrderDate(new Date()); List<Product> errorProducts = new ArrayList<Product>(); for (OrderLine line : order.getOrderLines()) { Inventory inv = line.getProduct().getInventory(); if (!inv.order(line.getQuantity())) { errorProducts.add(line.getProduct()); } } if (errorProducts.size() > 0) { throw new InsufficientQuantityException(errorProducts); } order.calculateTotals(); em.persist(order); return order; } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) private void fireEvent(long orderId, BigDecimal ammount, String customerName, String customerPhone) { try { SipApplicationSession sipApplicationSession = sipFactory.createApplicationSession(); String callerAddress = (String)Contexts.getApplicationContext().get("caller.sip"); String callerDomain = (String)Contexts.getApplicationContext().get("caller.domain"); SipURI fromURI = sipFactory.createSipURI(callerAddress, callerDomain); Address fromAddress = sipFactory.createAddress(fromURI); Address toAddress = sipFactory.createAddress(customerPhone); SipServletRequest sipServletRequest = sipFactory.createRequest(sipApplicationSession, "INVITE", fromAddress, toAddress); // getting the contact address for the registered customer sip address String userContact= ((Map<String, String>)Contexts.getApplicationContext().get("registeredUsersMap")).get(customerPhone); if(userContact != null && userContact.length() > 0) { // for customers using the registrar URI requestURI = sipFactory.createURI(userContact); sipServletRequest.setRequestURI(requestURI); } else { // for customers not using the registrar and registered directly their contact location URI requestURI = sipFactory.createURI(customerPhone); sipServletRequest.setRequestURI(requestURI); } //TTS file creation StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("Welcome "); stringBuffer.append(customerName); stringBuffer.append(". You have placed an order of $"); stringBuffer.append(ammount); stringBuffer.append(". Press 1 to confirm and 2 to decline."); TTSUtils.buildAudio(stringBuffer.toString(), "speech.wav"); Thread.sleep(300); //Media Server Control Creation MsPeer peer = MsPeerFactory.getPeer("org.mobicents.mscontrol.impl.MsPeerImpl"); MsProvider provider = peer.getProvider(); MsSession session = provider.createSession(); MsConnection connection = session.createNetworkConnection(MediaConnectionListener.PR_JNDI_NAME); MediaConnectionListener listener = new MediaConnectionListener(); listener.setInviteRequest(sipServletRequest); // provider.addConnectionListener(listener); connection.addConnectionListener(listener); log.info("waiting to get the SDP from Media Server before sending the INVITE to " + callerAddress + "@" + callerDomain); connection.modify("$", null); sipServletRequest.getSession().setAttribute("customerName", customerName); sipServletRequest.getSession().setAttribute("customerPhone", customerPhone); sipServletRequest.getSession().setAttribute("amountOrder", amount); sipServletRequest.getSession().setAttribute("orderId", orderId); sipServletRequest.getSession().setAttribute("connection", connection); sipServletRequest.getSession().setAttribute("orderApproval", true); sipServletRequest.getSession().setAttribute("caller", (String)Contexts.getApplicationContext().get("caller.sip")); sipServletRequest.getSession().setAttribute("callerDomain", (String)Contexts.getApplicationContext().get("caller.domain")); sipServletRequest.getSession().setAttribute("callerPassword", (String)Contexts.getApplicationContext().get("caller.password")); } catch (UnsupportedOperationException uoe) { log.error("An unexpected exception occurred while trying to create the request for checkout confirmation", uoe); } catch (Exception e) { log.error("An unexpected exception occurred while trying to create the request for checkout confirmation", e); } } @Remove public void destroy() { } }