/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 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
 *
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */


package org.objectweb.jonas.server;

import java.io.FileInputStream;
import java.util.Properties;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import javax.naming.NamingException;
import org.objectweb.common.Env;
import org.objectweb.common.RemoteObject;
import org.objectweb.jonas.adm.Adm;
import org.objectweb.jonas.common.JProp;
import org.objectweb.jonas.common.Log;
import org.objectweb.jonas.container.EJBService;
import org.objectweb.jonas.dbm.DataBaseService;
import org.objectweb.jonas.jms.JmsService;
import org.objectweb.jonas.jmx.JmxService;
import org.objectweb.jonas.jmx.JonasObjectName;
import org.objectweb.jonas.naming.NamingManager;
import org.objectweb.jonas.registry.RegistryManager;
import org.objectweb.jonas.service.Service;
import org.objectweb.jonas.service.ServiceManager;
import org.objectweb.jonas.service.ServiceException;
import org.objectweb.jonas_ejb.lib.Version;
import org.objectweb.util.monolog.api.HandlerFactory;
import org.objectweb.util.monolog.api.LevelFactory;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.util.monolog.api.LoggerFactory;
import org.objectweb.util.monolog.file.monolog.PropertiesConfAccess;

/**
 * This class implements an JOnAS Server.
 * @author Philippe Coq, Philippe Durieux
 * 00/06/15: Jeff Mesnil
 * 01/06/15: Regis Le Brettevillois - Libelis / JOnAS team - evidian
 *           Service as org.objectweb.jonas.service.Service
 * 02/04/25: Sebastien Chassande-Barrioz sebastien.chassande@inrialpes.fr
 *           Monolog for traces
 */
public class Server {

    static private Logger logger = null;
    static private String SERVERNAME="JOnAS";
    private String serverName = null;

    // The Server singleton value
    private static Server unique = null;

    // The associated ServiceManager for JOnAS
    ServiceManager sm = null;

    // Associated Adm object
    Adm adm = null;


    /**
     * Private constructor to force only 1 instance.
     */
    private Server() {
	sm = ServiceManager.getInstance();
    }

    /**
     * Get the unique instance.
     * Create it at first call.
     */
    public static Server getInstance() {
	if (unique == null) {
	    unique = new Server();
	}
	return unique;
    }

    /**
     * Start the server
     */
    public void start() throws Exception {

	// Print jonas version and orb
	String orbs = null;
	if (Env.isJeremie()) {
	    orbs = "Jeremie";
	} else if (Env.isSunRMI()){
	    orbs = "rmi";
	} else if (Env.isDavid()) {
	    orbs = "David RMI";
	}

	// Read the JONAS properties
	JProp props = null;
	try {
	    props = new JProp();
	} catch (Exception e) {
	    throw new Exception("JOnAS: Cannot read the JOnAS properties ("+e+")");
	}
	// get the jonas.name property value:
	serverName = props.getValue("jonas.name", "jonas"); 

        // start the framework
	this.startFramework(props);

        try {
            // start services
            sm.startServices();

        }catch(ServiceException se) {
            logger.log(BasicLevel.ERROR, SERVERNAME+" cannot start services : "+se.toString());
            throw se;
        }

	// JMX: register ejbserver and trace
	try {
	    // TODO change this class name !!! (or try to use inheritance)
	    JmxServer serverMBean = new JmxServer(this, serverName, Version.NUMBER, orbs);

	    JmxService jmx = (JmxService) ServiceManager.getJmxService();
	    jmx.getJmxServer().registerMBean(serverMBean, JonasObjectName.ejbServer());
	    jmx.getJmxServer().registerMBean(Log.getInstance(), JonasObjectName.logService());
	} catch (ServiceException se) {
	    // Jmx Service not available, do nothing
	} catch (Exception e) {
	    throw e;
	}

	// TM Server or EJB Server ?
	boolean isNotEJB = false;
	try {
	    Service ejbservice = ServiceManager.getEjbService();
	} catch (ServiceException se) {
            isNotEJB = true;
	}

	// Creates the Adm instance for remote administration
	try {
	    adm =  new Adm(props, isNotEJB);
	} catch (Exception e) {
	    throw new Exception("Cannot create Adm ("+e+")");
	}

	System.out.println("The JOnAS EJBServer '"+serverName+"' version "+Version.NUMBER+" is ready and running on "+orbs);
    }
    
    void startFramework(JProp props) throws Exception {

	// RMI Security Manager
	if (System.getSecurityManager() == null) {
	    System.setSecurityManager(new RMISecurityManager());
	}

        // Set configuration info to the Log System (monolog)
	// Default is to use trace.properties found in the classpath.
        String file = props.getValue("jonas.log.configfile", "trace.properties");
        String usecp = props.getValue("jonas.log.configfile.useclasspath", "true");
	Log.configure(file, usecp.equalsIgnoreCase("true"));

	// get a logger for server traces
        logger = Log.getLogger(Log.JONAS_SERVER_PREFIX);

	// Init the ORB
	try {
	    // Port value zero: an anonymous port is choosen
	    int portNumber = Integer.parseInt(props.getValue("jonas.orb.port", "0"));
	    RemoteObject.setPort(portNumber);
	    logger.log(BasicLevel.DEBUG, "The 'jonas.orb.port' value is "+portNumber);

	} catch (NumberFormatException e) {
	    logger.log(BasicLevel.ERROR, "JOnAS: Invalid 'jonas.orb.port' property value (default value used!)");
	}

    }

    /**
     * Stop the server without stopping the JVM
     */
    public void stop() throws Exception {
	if (adm != null) {
	    adm.stopServer();
	}
    }

    /**
     * Stop the server and stop the JVM (MBean method)
     */
    public void kill() throws Exception {
	if (adm != null) {
	    adm.killServer();
	}
    }


    /**
     * Server main routine.
     * No args.
     */
    public static void main(String args[]) {
	Server server = Server.getInstance();
	try {
	    server.start();
	} catch (Exception e) {
            // We don't use here the trace system.
            System.err.println("JOnAS error: "+e.getMessage());
            System.err.println(SERVERNAME+" halting");
	    System.exit(2);
	}
    }

}
