/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * This library 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 2.1 of the License, or any later version.
 *
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Initial developer(s): jonas team
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package jaasclient;

import jaasclient.beans.secusb.JAASOp;
import jaasclient.beans.secusb.JAASOpHome;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.transaction.UserTransaction;

import org.objectweb.jonas.security.auth.callback.DialogCallbackHandler;
import org.objectweb.jonas.security.auth.callback.LoginCallbackHandler;
import org.objectweb.jonas.security.auth.callback.NoInputCallbackHandler;

/**
 * Sample for Session Bean. Usage: jclient jaasclient.ClientJAASOp <text |
 * dialog | noprompt>
 * @author jonas team
 * @author Florent Benoit : use a JAAS login module configuration for the
 *         authentication
 */
public class ClientJAASOp {

    /**
     * First amount to buy
     */
    private static final int FIRST_BUY_AMOUNT = 10;

    /**
     * Second amount to buy
     */
    private static final int SECOND_BUY_AMOUNT = 20;

    /**
     * Third amount to buy (will be rollback)
     */
    private static final int THIRD_BUY_AMOUNT = 50;

    /**
     * Constructor. Hide constructor as it is an utility class
     */
    private ClientJAASOp() {

    }

    /**
     * Main method
     * @param args the arguments
     */
    public static void main(String[] args) {

        //Check if there are valid args
        if (args.length != 1) {
            System.err.println("Syntax is : jclient jaasclient.ClientJAASOp <text | dialog | noprompt>");
            System.err.println(" - text     : Prompt the user to enter login/password by command line");
            System.err.println(" - dialog   : Prompt the user to enter login/password by a window dialog");
            System.err.println(" - noprompt : No prompt is asked to the user. A default login/password is used");
            System.exit(2);
        }

        // Which handler use ?
        CallbackHandler handler = null;

        if (args[0].equalsIgnoreCase("text")) {
            handler = new LoginCallbackHandler();
        } else if (args[0].equalsIgnoreCase("dialog")) {
            handler = new DialogCallbackHandler();
        } else if (args[0].equalsIgnoreCase("noprompt")) {
            handler = new NoInputCallbackHandler("jonas", "jonas");
        } else {
            System.err.println("Invalid type '" + args[0]
                    + "', valid syntax is : jclient jaasclient.ClientJAASOp <text | dialog | noprompt>");
            System.exit(2);
        }

        Context initialContext = null;
        try {
            initialContext = new InitialContext();
        } catch (Exception e) {
            System.err.println("Cannot get initial context for JNDI: " + e);
            System.exit(2);
        }

        // Obtain a LoginContext
        LoginContext lc = null;
        try {
            lc = new LoginContext("jaasclient", handler);
        } catch (LoginException le) {
            System.err.println("Cannot create LoginContext: " + le.getMessage());
            System.exit(2);
        } catch (SecurityException se) {
            System.err.println("Cannot create LoginContext: " + se.getMessage());
            System.exit(2);
        }

        System.out
                .println("Use the l/p jonas/jonas to authenticate with the right role.\nYou can change this by editing the file JONAS_ROOT/conf/jonas-realm.xml.");

        // Login
        try {
            lc.login();
        } catch (LoginException le) {
            System.err.println("Authentication failed : " + le.getMessage());
            System.exit(2);
        }

        // Authentication is ok
        System.out.println("Authentication succeeded");

        // We want to start transactions from client: get UserTransaction
        UserTransaction utx = null;
        try {

            // Comment the following lines if you want to use a David Client:
            utx = (UserTransaction) initialContext.lookup("javax.transaction.UserTransaction");
        } catch (Exception e) {
            System.err.println("Cannot lookup UserTransaction: " + e);
            System.exit(2);
        }

        // Connecting to JAASOpHome thru JNDI
        JAASOpHome home = null;
        try {
            home = (JAASOpHome) PortableRemoteObject.narrow(initialContext.lookup("JAASOpHome"), JAASOpHome.class);
        } catch (Exception e) {
            System.err.println("Cannot lookup JAASOpHome: " + e
                    + ". Maybe you haven't do the 'jonas admin -a jaasop.jar'");
            System.exit(2);
        }

        // JAASOpBean creation
        JAASOp t1 = null;
        try {
            System.out.println("Create a bean");
            t1 = home.create("User1");
        } catch (Exception e) {
            System.err.println("Cannot create JAASOpBean: " + e);
            System.exit(2);
        }

        // First transaction (committed)
        try {
            System.out.println("Start a first transaction");
            utx.begin();
            System.out.println("First request on the new bean");
            t1.buy(FIRST_BUY_AMOUNT);
            System.out.println("Second request on the bean");
            t1.buy(SECOND_BUY_AMOUNT);
            System.out.println("Commit the transaction");
            utx.commit();
        } catch (Exception e) {
            System.err.println("exception during 1st Tx: " + e);
            System.exit(2);
        }
        // Start another transaction (rolled back)
        try {
            System.out.println("Start a second transaction");
            utx.begin();
            t1.buy(THIRD_BUY_AMOUNT);
            System.out.println("Rollback the transaction");
            utx.rollback();
        } catch (Exception e) {
            System.err.println("exception during 2nd Tx: " + e);
            System.exit(2);
        }

        // Get the total bought, outside the transaction
        int val = 0;
        try {
            System.out.println("Request outside any transaction");
            val = t1.read();
        } catch (Exception e) {
            System.err.println("Cannot read value on t1 : " + e);
            System.exit(2);
        }
        if (val != FIRST_BUY_AMOUNT + SECOND_BUY_AMOUNT) {
            System.err.println("Bad value read: " + val);
            System.exit(2);
        }

        // Remove Session bean
        try {
            t1.remove();
        } catch (Exception e) {
            System.out.println("Exception on buy: " + e);
            System.exit(2);
        }
        System.out.println("ClientJAASOp OK. Exiting.");
        System.exit(0);
    }
}