/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/Slide.java,v 1.11 2004/08/05 15:42:32 unico Exp $
 * $Revision: 1.11 $
 * $Date: 2004/08/05 15:42:32 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */ 

package org.apache.slide.common;

import java.io.FileInputStream;

import javax.management.AttributeChangeNotification;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.slide.authenticate.SecurityToken;
import org.apache.slide.util.conf.Configuration;
import org.apache.slide.util.conf.ConfigurationElement;
import org.apache.slide.util.conf.Populate;
import org.xml.sax.InputSource;

/**
 * Implementation of the Slide JMX MBean.
 * 
 * @version $Revision: 1.11 $
 */
public final class Slide
    extends NotificationBroadcasterSupport
    implements SlideMBean, MBeanRegistration {
    
    
    // ----------------------------------------------------- Instance Variables
    
    
    /**
     * Status of the Slide domain.
     */
    private int state = STOPPED;
    
    
    /**
     * Config file name.
     */
    private String configFile = null;
    
    
    /**
     * Notification sequence number.
     */
    private long sequenceNumber = 0;
    
    
    // ---------------------------------------------- MBeanRegistration Methods
    
    
    public ObjectName preRegister(MBeanServer server, ObjectName name)
        throws Exception {
        return new ObjectName(OBJECT_NAME);
    }
    
    
    public void postRegister(Boolean registrationDone) {
        if (!registrationDone.booleanValue())
            destroy();
    }
    
    
    public void preDeregister()
        throws Exception {
    }
    
    
    public void postDeregister() {
        destroy();
    }
    
    
    // ----------------------------------------------------- SlideMBean Methods
    
    
    /**
     * Retruns the Slide component name.
     */
    public String getName() {
        return NAME;
    }
    
    
    /**
     * Returns the state of the Slide domain.
     */
    public int getState() {
        return state;
    }
    
    
    /**
     * Returns a String representation of the domain's state.
     */
    public String getStateString() {
        return states[state];
    }
    
    
    /**
     * Auto initializes domain.
     */
    public void init()
        throws Exception {
        
    }
    
    
    /**
     * Initializes domain, and specify a configuration file to use.
     */
    public void init(String configFile)
        throws Exception {
        
        this.configFile = configFile;
        
    }
    
    
    /**
     * Start the domain.
     */
    public void start()
        throws Exception {
        
        Notification notification = null;
        
        if (state != STOPPED)
            return;
        
        state = STARTING;
        
        // Notifying the MBEan server that we're starting
        
        notification = new AttributeChangeNotification
            (this, sequenceNumber++, System.currentTimeMillis(), 
             "Starting " + NAME, "State", "java.lang.Integer", 
             new Integer(STOPPED), new Integer(STARTING));
        sendNotification(notification);
        
        try {
            
            if (configFile == null) {
                
                Domain.selfInit();
                
            } else {
                
                SAXParserFactory factory = SAXParserFactory.newInstance();
                factory.setNamespaceAware(false);
                factory.setValidating(false);
                SAXParser parser = factory.newSAXParser();
                
                FileInputStream is = new FileInputStream(configFile);
                //init(reader);
                Populate pop = new Populate();
                Configuration slideConfiguration = 
                    new ConfigurationElement(pop.load(new InputSource(is), 
                                                      parser.getXMLReader()));
                
                Domain.init(slideConfiguration);
                
                Domain.start();
                
            }
            
        } catch (Throwable t) {
            state = STOPPED;
            notification = new AttributeChangeNotification
                (this, sequenceNumber++, System.currentTimeMillis(), 
                 "Stopped " + NAME, "State", "java.lang.Integer", 
                 new Integer(STARTING), new Integer(STOPPED));
            sendNotification(notification);
        }
        
        state = STARTED;
        notification = new AttributeChangeNotification
            (this, sequenceNumber++, System.currentTimeMillis(), 
             "Started " + NAME, "State", "java.lang.Integer", 
             new Integer(STARTING), new Integer(STARTED));
        sendNotification(notification);
        
    }
    
    
    /**
     * Close all access tokens to the domain.
     */
    public void stop() {
        
        Notification notification = null;
        
        if (state != STARTED)
            return;
        
        state = STOPPING;
        
        notification = new AttributeChangeNotification
            (this, sequenceNumber++, System.currentTimeMillis(), 
             "Stopping " + NAME, "State", "java.lang.Integer", 
             new Integer(STARTED), new Integer(STOPPING));
        sendNotification(notification);
        
        try {
            
            Domain.stop();
            
        } catch (Throwable t) {
            
            // FIXME
            t.printStackTrace();
            
        }
        
        state = STOPPED;
        
        notification = new AttributeChangeNotification
            (this, sequenceNumber++, System.currentTimeMillis(), 
             "Stopped " + NAME, "State", "java.lang.Integer", 
             new Integer(STOPPING), new Integer(STOPPED));
        sendNotification(notification);
        
    }
    
    
    /**
     * Destroy domain.
     */
    public void destroy() {
        
        if (getState() != STOPPED)
            stop();
        
    }
    
    
    /**
     * Access a Namespace.
     * 
     * @param token Entity which wants access
     * @param namespaceName Name of the namespace on which access is requested
     * @return NamespaceAccessToken Access token to the namespace
     */
    public NamespaceAccessToken accessNamespace(SecurityToken token, 
                                                String namespaceName) {
        return Domain.accessNamespace(token, namespaceName);
    }
    
    
    /**
     * Close a namespace.
     * 
     * @param token Namespace access token
     */
    public void closeNamespace(NamespaceAccessToken token) {
        Domain.closeNamespace(token);
    }
    
    
    /**
     * Clsose a namespace.
     * 
     * @param token Entity which wants to close the namespace
     * @param namespaceName Name of the namespace
     */
    public void closeNamespace(SecurityToken token, String namespaceName) {
        Domain.closeNamespace(token, namespaceName);
    }
    
    
    /**
     * Access a Domain.
     * 
     * @param token Service who wants access
     * @return DomainAccessToken Access token to the domain
     */
    public DomainAccessToken accessDomain(SecurityToken token) {
        return Domain.accessDomain(token);
    }
    
    
}
