/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.tomcat.util.modeler.modules;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.loading.MLet;
import javax.xml.transform.TransformerException;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.DomUtil;
import org.apache.tomcat.util.modeler.AttributeInfo;
import org.apache.tomcat.util.modeler.BaseModelMBean;
import org.apache.tomcat.util.modeler.ManagedBean;
import org.apache.tomcat.util.modeler.Registry;
import org.w3c.dom.Document;
import org.w3c.dom.Node;


/** This will create mbeans based on a config file.
 *  The format is an extended version of MLET.
 *
 * Classloading. We don't support any explicit classloader tag. 
 * A ClassLoader is just an mbean ( it can be the standard MLetMBean or
 * a custom one ). 
 * 
 * XXX add a special attribute to reference the loader mbean,
 * XXX figure out how to deal with private loaders
 */
public class MbeansSource extends ModelerSource implements MbeansSourceMBean
{
    private static final Log log = LogFactory.getLog(MbeansSource.class);
    Registry registry;
    String type;

    // true if we are during the original loading
    boolean loading=true;
    List<ObjectName> mbeans = new ArrayList<ObjectName>();
    static boolean loaderLoaded=false;
    private Document document;
    private HashMap<ObjectName,Node> object2Node =
        new HashMap<ObjectName,Node>();

    long lastUpdate;
    long updateInterval=10000; // 10s

    public void setRegistry(Registry reg) {
        this.registry=reg;
    }          

    public void setLocation( String loc ) {
        this.location=loc;
    }

    /** Used if a single component is loaded
     *
     * @param type
     */
    public void setType( String type ) {
       this.type=type;
    }

    public void setSource( Object source ) {
        this.source=source;
    }

    public Object getSource() {
        return source;
    }

    public String getLocation() {
        return location;
    }
    
    /** Return the list of mbeans created by this source.
     *  It can be used to implement runtime services.
     */
    public List<ObjectName> getMBeans() {
        return mbeans;
    }

    @Override
    public List<ObjectName> loadDescriptors(Registry registry, String location,
            String type, Object source) throws Exception {
        setRegistry(registry);
        setLocation(location);
        setType(type);
        setSource(source);
        execute();
        return mbeans;
    }
    
    public void start() throws Exception {
        registry.invoke(mbeans, "start", false);        
    }

    public void stop() throws Exception {
        registry.invoke(mbeans, "stop", false);        
    }
    
    public void init() throws Exception {
        if( mbeans==null) execute();
        if( registry==null ) registry=Registry.getRegistry(null, null);
        
        registry.invoke(mbeans, "init", false);
    }
    
    public void destroy() throws Exception {
        registry.invoke(mbeans, "destroy", false);                
    }
    
    public void load() throws Exception {
        execute(); // backward compat
    }

    public void execute() throws Exception {
        if( registry==null ) registry=Registry.getRegistry(null, null);
        try {
            InputStream stream=getInputStream();
            long t1=System.currentTimeMillis();
            document = DomUtil.readXml(stream);

            // We don't care what the root node is.
            Node descriptorsN=document.getDocumentElement();

            if( descriptorsN == null ) {
                log.error("No descriptors found");
                return;
            }

            Node firstMbeanN=DomUtil.getChild(descriptorsN, null);

            if( firstMbeanN==null ) {
                // maybe we have a single mlet
                if( log.isDebugEnabled() )
                    log.debug("No child " + descriptorsN);
                firstMbeanN=descriptorsN;
            }

            MBeanServer server =
                Registry.getRegistry(null, null).getMBeanServer();

            // XXX Not very clean...  Just a workaround
            if( ! loaderLoaded ) {
                // Register a loader that will be find ant classes.
                ObjectName defaultLoader= new ObjectName("modeler",
                        "loader", "modeler");
                MLet mlet=new MLet( new URL[0], this.getClass().getClassLoader());
                server.registerMBean(mlet, defaultLoader);
                loaderLoaded=true;
            }
        
            // Process nodes
            for (Node mbeanN = firstMbeanN; mbeanN != null;
                 mbeanN= DomUtil.getNext(mbeanN, null, Node.ELEMENT_NODE))
            {
                String nodeName=mbeanN.getNodeName();

                // mbean is the "official" name
                if( "mbean".equals(nodeName) || "MLET".equals(nodeName) )
                {
                    String code=DomUtil.getAttribute( mbeanN, "code" );
                    String objectName=DomUtil.getAttribute( mbeanN, "objectName" );
                    if( objectName==null ) {
                        objectName=DomUtil.getAttribute( mbeanN, "name" );
                    }
                    
                    if( log.isDebugEnabled())
                        log.debug( "Processing mbean objectName=" + objectName +
                                " code=" + code);

                    // args can be grouped in constructor or direct childs
                    Node constructorN=DomUtil.getChild(mbeanN, "constructor");
                    if( constructorN == null ) constructorN=mbeanN;

                    processArg(constructorN);

                    try {
                        ObjectName oname=new ObjectName(objectName);
                        if( ! server.isRegistered( oname )) {
                            // We wrap everything in a model mbean.
                            // XXX need to support "StandardMBeanDescriptorsSource"
                            String modelMBean=BaseModelMBean.class.getName();                            
                            server.createMBean(modelMBean, oname,
                                    new Object[] { code, this},
                                    new String[] { String.class.getName(),
                                                  ModelerSource.class.getName() } 
                                    );
                            mbeans.add(oname);
                        }
                        object2Node.put( oname, mbeanN );
                        // XXX Arguments, loader !!!
                    } catch( Exception ex ) {
                        log.error( "Error creating mbean " + objectName, ex);
                    }

                    Node firstAttN=DomUtil.getChild(mbeanN, "attribute");
                    for (Node descN = firstAttN; descN != null;
                         descN = DomUtil.getNext( descN ))
                    {
                        processAttribute(server, descN, objectName);
                    }
                } else if("jmx-operation".equals(nodeName) ) {
                    String name=DomUtil.getAttribute(mbeanN, "objectName");
                    if( name==null )
                        name=DomUtil.getAttribute(mbeanN, "name");

                    String operation=DomUtil.getAttribute(mbeanN, "operation");

                    if( log.isDebugEnabled())
                        log.debug( "Processing invoke objectName=" + name +
                                " code=" + operation);
                    try {
                        ObjectName oname=new ObjectName(name);

                        processArg( mbeanN );
                        server.invoke( oname, operation, null, null);
                    } catch (Exception e) {
                        log.error( "Error in invoke " + name + " " + operation);
                    }
                }

                ManagedBean managed=new ManagedBean();
                DomUtil.setAttributes(managed, mbeanN);
                Node firstN;

                // process attribute info
                firstN=DomUtil.getChild( mbeanN, "attribute");
                for (Node descN = firstN; descN != null;
                     descN = DomUtil.getNext( descN ))
                {
                    AttributeInfo ci=new AttributeInfo();
                    DomUtil.setAttributes(ci, descN);
                    managed.addAttribute( ci );
                }

            }

            long t2=System.currentTimeMillis();
            log.info( "Reading mbeans  " + (t2-t1));
            loading=false;
        } catch( Exception ex ) {
            log.error( "Error reading mbeans ", ex);
        }
    }
    
    @Override
    public void updateField( ObjectName oname, String name, 
                             Object value )
    {
        if( loading ) return;
        // nothing by default
        //log.info( "XXX UpdateField " + oname + " " + name + " " + value);
        Node n = object2Node.get(oname);
        if( n == null ) {
            log.info( "Node not found " + oname );
            return;
        }
        Node attNode=DomUtil.findChildWithAtt(n, "attribute", "name", name);
        if( attNode == null ) {
            // found no existing attribute with this name
            attNode=n.getOwnerDocument().createElement("attribute");
            DomUtil.setAttribute(attNode, "name", name);
            n.appendChild(attNode);
        } 
        String oldValue=DomUtil.getAttribute(attNode, "value");
        if( oldValue != null ) {
            // we'll convert all values to text content
            DomUtil.removeAttribute( attNode, "value");
        }
        DomUtil.setText(attNode, value.toString());

        //store();
    }
    
    /** Store the mbeans. 
     * XXX add a background thread to store it periodically 
     */ 
    public void save() {
        // XXX customize no often than ( based on standard descriptor ), etc.
        // It doesn't work very well if we call this on each set att - 
        // the triger will work for the first att, but all others will be delayed
        long time=System.currentTimeMillis();
        if( location!=null &&
                time - lastUpdate > updateInterval ) {
            lastUpdate=time;
            try {
                FileOutputStream fos=new FileOutputStream(location);
                DomUtil.writeXml(document, fos);
            } catch (TransformerException e) {
                log.error( "Error writing");
            } catch (FileNotFoundException e) {
                log.error( "Error writing" ,e );
            }
        }
    }

    private void processAttribute(MBeanServer server,
                                  Node descN, String objectName ) {
        String attName=DomUtil.getAttribute(descN, "name");
        String value=DomUtil.getAttribute(descN, "value");
        String type=null; // DomUtil.getAttribute(descN, "type");
        if( value==null ) {
            // The value may be specified as CDATA
            value=DomUtil.getContent(descN);
        }
        try {
            if( log.isDebugEnabled())
                log.debug("Set attribute " + objectName + " " + attName +
                        " " + value);
            ObjectName oname=new ObjectName(objectName);
            // find the type
            if( type==null )
                type=registry.getType(  oname, attName );

            if( type==null ) {
                log.info("Can't find attribute " + objectName + " " + attName );

            } else {
                Object valueO=registry.convertValue( type, value);
                server.setAttribute(oname, new Attribute(attName, valueO));
            }
        } catch( Exception ex) {
            log.error("Error processing attribute " + objectName + " " +
                    attName + " " + value, ex);
        }

    }

    private void processArg(Node mbeanN) {
        Node firstArgN=DomUtil.getChild(mbeanN, "arg" );
        // process all args
        for (Node argN = firstArgN; argN != null;
             argN = DomUtil.getNext( argN ))
        {
            DomUtil.getAttribute(argN, "type");
            String value=DomUtil.getAttribute(argN, "value");
            if( value==null ) {
                // The value may be specified as CDATA
                value=DomUtil.getContent(argN);
            }
        }
    }
}
