/* vim: set ts=2 et sw=2 cindent fo=qroca: */
package com.globant.google.mendoza;
import java.util.Date;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.globant.google.mendoza.malbec.OrderListener;
import com.globant.google.mendoza.malbec.Order;
import com.globant.google.mendoza.malbec.schema._2.NewOrderNotification;
import com.globant.google.mendoza.malbec.schema._2.RiskInformationNotification;
import com.globant.google.mendoza.malbec.schema._2.Money;
import com.globant.google.mendoza.malbec.schema._2.
AuthorizationAmountNotification;
import com.globant.google.mendoza.malbec.transport.Transport;
import com.globant.google.mendoza.malbec.transport.Receiver;
/** Implements an intercepting proxy for a transport delegate.
*
* This proxy intercepts the messages received by the wrapped transport and
* redirects them to another server.
*/
public final class TransportProxy implements Transport, OrderListener {
/** The class logger.
*/
private static Log log = LogFactory.getLog(TransportProxy.class);
/** The transport implementation that proxy delegates the requests to.
*/
private Transport delegate;
/** The server that will be notified when a notification
* message is received.
*/
private MendozaServer mendozaServer;
/** The merchant app URL.
*/
private String merchantURL;
/** The Checkout server post URL.
*/
private String postURL;
/** Builds a transport proxy.
*
* @param transport The object that this proxy delegates the requests
* to/from. It cannot be null.
*
* @param server The server that will be notified when a new order
* notification message is received. It cannot be null.
*
* @param theMerchantURL The merchant app URL. It cannot be null.
*
* @param thePostURL he Checkout server post URL. It cannot be null.
*/
TransportProxy(final Transport transport, final MendozaServer server,
final String theMerchantURL, final String thePostURL) {
if (transport == null) {
throw new IllegalArgumentException("The transport cannot be null");
}
if (server == null) {
throw new IllegalArgumentException("The server cannot be null");
}
if (theMerchantURL == null) {
throw new IllegalArgumentException("The merchant URL cannot be null");
}
if (thePostURL == null) {
throw new IllegalArgumentException("The Checkout URL cannot be null");
}
delegate = transport;
mendozaServer = server;
postURL = thePostURL;
merchantURL = theMerchantURL;
}
/** Sends a message to the server.
*
* This implementation throws an error.
*
* @param message The message to send to the server. It cannot be null.
*
* @return Returns the server response, usually an acknowledge or an error
* related to the validity of the message structure.
*/
public String send(final String message) {
this.setServerURL(postURL);
String serverResponse = delegate.send(message);
this.setServerURL(merchantURL);
return serverResponse;
}
/** Registers a receiver for this transport.
*
* Registers a receiver that forwards the message to another server.
*
* @param receiver The receiver that is notified of the message availability.
*/
public void registerReceiver(final Receiver receiver) {
Receiver receiverInterceptor = new Receiver() {
public String receive(final String uri, final String method, final
Properties header, final Properties params, final String message) {
log.trace("Entering receive");
String response = delegate.send(message);
log.trace("Leaving receive");
return response;
}
public void received(final String message) {
log.trace("Entering received");
if (log.isDebugEnabled()) {
log.debug("Message: " + message);
}
if (message.contains("<merchant-calculation-callback")) {
log.debug("Merchant calculation callback received.");
Date start = new Date();
String response = delegate.send(message);
Date end = new Date();
mendozaServer.setMerchantCalculation(message, response, start, end);
receiver.received(message);
} else {
delegate.send(message);
receiver.received(message);
}
log.trace("Leaving received");
}
};
delegate.registerReceiver(receiverInterceptor);
}
/** Starts listening to requests.
*
* You must have registered a receiver before calling start. The registered
* receiver is notified of new requests.
*
* This implementation simply calls start on the delegate.
*/
public void start() {
delegate.start();
}
/** Stops the server.
*
* This implementation simply calls stop on the delegate.
*/
public void stop() {
delegate.stop();
}
/** Called when a new message is received, before the acknowledge is sent to
* GBuy.
*
* @param command The command name. This is the top level xml node name.
*
* @param orderNumber The GBuy order number.
*
* @param timestamp The notification timestamp.
*/
public void receiveMessage(final String command, final String orderNumber,
final Date timestamp) {
log.trace("Entering receiveMessage('" + command + "', '" + orderNumber
+ "', ...)");
}
/** Called when a buyer places an order.
*
* @param order The order initialized to talk to GBuy.
*
* @param timestamp Time and date of message in ISO 8601 format.
*
* @param newOrderNotification The new order message included in the new
* order notification.
*/
public synchronized void newOrder(final Order order, final Date timestamp,
final NewOrderNotification newOrderNotification) {
log.trace("Entering newOrder");
mendozaServer.registerNewOrderNotification(
order.getNumber(), newOrderNotification);
mendozaServer.setCurrentOrder(order);
log.trace("Leaving newOrder");
}
/** Called when GBuy sends the risk information notification.
*
* @param order The order initialized to talk to GBuy.
*
* @param timestamp Time and date of message in ISO 8601 format.
*
* @param information The buyer's risk information.
*/
public void riskInformation(final Order order, final Date timestamp, final
RiskInformationNotification information) {
log.trace("Entering riskInformation");
mendozaServer.registerRiskInformationNotification(
order.getNumber(), information);
log.trace("Leaving riskInformation");
}
/** Called when the GBuy order changes state.
*
* @param order The order initialized to talk to GBuy.
*
* @param timestamp Time and date of message in ISO 8601 format.
*
* @param newFulfillmentState Order's current fulfillment state.
*
* @param newFinancialState Order's current financial state.
*
* @param oldFulfillmentState Fulfillment state before this state change.
*
* @param oldFinancialState Financial state before this state change.
*
* @param reason Description of state change (not always used).
*/
public void stateChanged(final Order order, final Date timestamp, final
String newFulfillmentState, final String newFinancialState, final String
oldFulfillmentState, final String oldFinancialState,
final String reason) {
log.trace("Entering stateChanged");
mendozaServer.registerOrderStateChanged(order.getNumber(),
newFulfillmentState, newFinancialState);
log.trace("Leaving stateChanged");
}
/** Called when all or part of the funds for the order are captured
* (charged).
*
* @param order The order initialized to talk to GBuy.
*
* @param timestamp Time and date of message in ISO 8601 format.
*
* @param latest Value of the most recent charge on this order.
*
* @param total Total value charged on this order.
*/
public void chargeAmount(final Order order, final Date timestamp, final Money
latest, final Money total) {
log.trace("Entering chargeAmount");
log.trace("Leaving chargeAmount");
}
/** When the buyer initiates a chargeback against the order, and GBuy
* approves the chargeback, GBuy sends you a chargeback-amount-notification.
*
* @param order The order initialized to talk to GBuy.
*
* @param timestamp Time and date of message in ISO 8601 format.
*
* @param latest Value of the most recent charge on this order.
*
* @param total Total value charged on this order.
*/
public void chargebackAmount(final Order order, final Date timestamp, final
Money latest, final Money total) {
log.trace("Entering chargebackAmount");
log.trace("Leaving chargebackAmount");
}
/** When you request a refund by sending a refund-order message, GBuy sends
* you a refund-amount-notification.
*
* @param order The order initialized to talk to GBuy.
*
* @param timestamp Time and date of message in ISO 8601 format.
*
* @param latest Value of the most recent charge on this order.
*
* @param total Total value charged on this order.
*/
public void refundAmount(final Order order, final Date timestamp, final Money
latest, final Money total) {
log.trace("Entering refundAmount");
log.trace("Leaving refundAmount");
}
/** Authorization Amount Notification.
*
* @param order The order initialized to talk to GBuy.
*
* @param timestamp Time and date of message in ISO 8601 format.
*
* @param authorizationAmountNotification The authorization amount
* notification.
*/
public void authorizationAmount(final Order order, final Date timestamp,
final AuthorizationAmountNotification authorizationAmountNotification) {
log.trace("Entering authorizationAmount");
log.trace("Leaving authorizationAmount");
}
/** Called when an unrecognized message is received.
*
* @param message The complete received message.
*/
public void unknown(final String message) {
log.error("Unknown message type: \n" + message);
}
/** Sets the url to use to send messages to GBuy.
*
* @param url The url. Cannot be null.
*/
public void setServerURL(final String url) {
delegate.setServerURL(url);
}
}