/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2000-2009 Sun Microsystems, Inc. All rights reserved. 
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License ("CDDL") (collectively, the "License").  You may
 * not use this file except in compliance with the License.  You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or mq/legal/LICENSE.txt.  See the License for the specific language
 * governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at mq/legal/LICENSE.txt.  Sun designates
 * this particular file as subject to the "Classpath" exception as provided by
 * Sun in the GPL Version 2 section of the License file that accompanied this
 * code.  If applicable, add the following below the License Header, with the
 * fields enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or  to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright holder. 
 */

/*
 * @(#)BrokerProcess.java	1.16 06/28/07
 */ 

package com.sun.messaging.jmq.jmsserver;

import java.util.*;
import com.sun.messaging.jmq.jmsserver.service.Service;
import com.sun.messaging.jmq.jmsserver.service.ServiceManager;
import com.sun.messaging.jmq.jmsserver.service.imq.IMQService;
import com.sun.messaging.jmq.jmsserver.service.imq.IMQDirectService;
import com.sun.messaging.jmq.jmsservice.JMSBroker;
import com.sun.messaging.jmq.jmsservice.JMSService;
import com.sun.messaging.jmq.jmsservice.BrokerEventListener;
import com.sun.messaging.jmq.jmsservice.BrokerEvent;

/**
 * Wrapper used to start the broker. It wraps a singleton class
 * (only one broker can be running in any process).<P>
 *
 * <u>Example</u><P>
 * <code><PRE>
 *      BrokerProcess bp = BrokerProcess.getBrokerProcess();
 *      try {
 *      
 *          Properties ht = bp.convertArgs(args);
 *          int exitcode = bp.start(true, ht, null);
 *          System.out.println("Broker exited with " + exitcode);
 *
 *      } catch (IllegalArgumentException ex) {
 *          System.err.println("Bad Argument " + ex.getMessage());
 *          System.out.println(BrokerProcess.usage());
 *      }
 * </PRE></code>
 */
public class BrokerProcess implements JMSBroker
{

    public static final int EMBEDDED_BROKER = 1; // old style embedded broker
    public static final int JMSRA_DIRECT_BROKER = 2; // old JMSRA direct mode broker
    public static final int DIRECT_BROKER = 3;

    Broker b = null;
    int type = 0;
    private static BrokerProcess bp = null;

    /**
     * return default broker process (DIRECT_BROKER)
     */
    public static BrokerProcess getBrokerProcess() 
        throws IllegalStateException
    {
        if (bp != null) return bp;
        return bp = BrokerProcess.getBrokerProcess(DIRECT_BROKER);
    }

    /**
     * Retrieve the singleton BrokerProcess object
     * @param brokerType is one of EMBEDDED_BROKER, JMSRA_DIRECT_BROKER, DIRECT_BROKER
     */
    public static BrokerProcess getBrokerProcess(int brokerType) 
        throws IllegalStateException
    {
        if (bp != null) {
            if (bp.type != 0 && bp.type != brokerType) {
                throw new IllegalStateException("INVALID STATE"); 
             }
             return bp;
        }
        switch (brokerType) {
            case EMBEDDED_BROKER:
                 //System.out.println("DEBUG: Oldstyle Embedded");
                 bp = new BrokerProcess();
                 break;
            case JMSRA_DIRECT_BROKER:
                 //System.out.println("DEBUG: Old JMSRA_Direct");
                 bp = new JMSRA_BrokerProcess();
                 break;
            case DIRECT_BROKER:
                 //System.out.println("DEBUG new Direct mode");
                 bp = new DirectBrokerProcess();
                 break;
             default:
                 throw new IllegalStateException("Invalid Type"); 
         }
         return bp;
     }




    /**
     * Constructor
     */
    public BrokerProcess() {
       type = EMBEDDED_BROKER;
        b = Broker.getBroker();
    }

    /**
     * Change command line args into a hashtable format
     *<P>
     * Additional arguments are:
     *    <UL>
     *       <LI> -varhome</LI>
     *       <LI> -imqhome</LI>
     *    </UL>
     *
     * @param args arguments in broker format
     */
    public Properties convertArgs(String[] args)
        throws IllegalArgumentException
    {
        Properties props = new Properties();

        // first look for var home and the like
        for (int i =0; i < args.length; i ++) {
            String arg = args[i];
            if (arg.equals("-varhome")) {
                props.setProperty("imq.varhome",
                        args[i+1]);
                i ++;
            } else if (arg.equals("-imqhome")) {
                props.setProperty("imq.home",
                        args[i+1]);
                i ++;
            } else if (arg.equals("-libhome")) {
                props.setProperty("imq.libhome",
                        args[i+1]);
                i ++;
            }
        }
        Globals.pathinit(props);
        return b.convertArgs(args);
    }

    public Properties parseArgs(String[] args)
        throws IllegalArgumentException
    {
        return (convertArgs(args));
    }

    /**
     * Usage string
     *
     */
    public static String usage()
    {
        return getBrokerProcess().b.usage();
    }

    /**
     * Checks the state of the Broker
     *
     * @return the state of the broker
     */
    public boolean isRunning() {
        return true;
    }

    /**
     * Start the broker (only one broker can be running in a given
     * vm).<p>This call returns as soon as the broker sucessfully starts.
     * @param inProcess - indicates that the broker is running inprocess
     *                    and the shutdown hook and memory management
     *                    code should not be used.
     * @param properties - configuration setttings for the broker
     *
     * @param bn - optional class to notify when a broker has completed
     *             starting or has been shutdown.
     *
     * @return the exit code what would be returned by the broker if it
     *       was running as a standalone process. (or 0 if it sucessfully
     *       started).
     *
     * @throws OutOfMemoryError - if the broker can not allocate enough 
     *          memory to continue running
     * @throws IllegalStateException - the broker is already running.  
     * @throws IllegalArgumentException - an invalid value for a property
     *                was passed on the command line
     */
    public int start(boolean inProcess, Properties properties, BrokerEventListener bel, boolean initOnly)
        throws OutOfMemoryError, IllegalStateException, IllegalArgumentException
    {
        return getBrokerProcess().b.start(inProcess, properties, bel, initOnly);
    }

    /**
     * Stop the broker (only one broker can be running in a given
     * vm).<p>
     * @param cleanup - if false, the code does not need to worry about freeing
     *                  unused resources. (broker is about to exit)
     * @throws IllegalStateException - the broker is already stopped.  
     */
    public void stop(boolean cleanup)
        throws IllegalStateException
    {

        b.destroyBroker(cleanup);
        b = null;
        bp = null;
    }


    public static void main(String args[]) {
try {

        BrokerProcess bp = getBrokerProcess();

        BrokerEventListener bn = new BrokerEventListener()
            {
                public boolean exitRequested(BrokerEvent event,
                   Throwable thr) {
System.out.println("EXIT REQUESTED " + event);
                      return false;
                }

                public void brokerEvent(BrokerEvent event) {
System.out.println("GOT EVENT" + event);
                }

            };

        String newargs[] = new String[args.length + 4];
        int i =0;
        for (i =0; i < args.length; i ++)
            newargs[i] = args[i];
        newargs[i++] = "-varhome";
        newargs[i++] = "../../../solaris/opt/var";
        newargs[i++] = "-imqhome";
        newargs[i++] = "../../../solaris/opt/";
       
        Properties p =bp.convertArgs(newargs);

System.err.println("HEY START");
        int exit = bp.start(true, p, bn, false);
System.err.println("HEY STARTED");
        Thread.currentThread().sleep(10*1000);
        System.out.println("HEY SHUTTING DOWN");
        bp.stop(true);
        System.out.println("Sleeping");
        Thread.currentThread().sleep(1000*10);
        System.out.println("Restarting");
        exit = bp.start(true, p, null, false);
        System.out.println("Sleeping");
        Thread.currentThread().sleep(10*1000);
        bp.stop(true);
        System.out.println("HEY SHUTTING DOWN");
        System.out.println("Sleeping");
        Thread.currentThread().sleep(1000*60);
        System.exit(0);
} catch (Exception ex) {
ex.printStackTrace();
}

    }
}


