/*
 *  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.jk.common;

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URLConnection;
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import javax.management.MBeanServer;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanException;
import javax.management.ReflectionException;
import javax.management.Attribute;
import javax.management.ObjectName;

import org.apache.jk.core.JkHandler;
import org.apache.commons.modeler.Registry;
import org.apache.commons.modeler.BaseModelMBean;
import org.apache.commons.modeler.ManagedBean;
import org.apache.commons.modeler.AttributeInfo;
import org.apache.commons.modeler.OperationInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A small mbean that will act as a proxy for mod_jk2.
 *
 * For efficiency, it'll get bulk results and cache them - you
 * can force an update by calling the refreshAttributes and refreshMetadata
 * operations on this mbean.
 *
 * TODO: implement the user/pass auth ( right now you must use IP based security )
 * TODO: eventually support https
 * TODO: support for metadata ( mbean-descriptors ) for description and type conversions
 * TODO: filter out trivial components ( mutexes, etc )
 *
 * @author Costin Manolache
 */
public class ModJkMX extends JkHandler
{
    private static Log log = LogFactory.getLog(ModJkMX.class);

    MBeanServer mserver;
    String webServerHost="localhost";
    int webServerPort=80;
    String statusPath="/jkstatus";
    String user;
    String pass;
    Registry reg;

    HashMap mbeans=new HashMap();
    long lastRefresh=0;
    long updateInterval=5000; // 5 sec - it's min time between updates

    public ModJkMX()
    {
    }

    /* -------------------- Public methods -------------------- */

    public String getWebServerHost() {
        return webServerHost;
    }

    public void setWebServerHost(String webServerHost) {
        this.webServerHost = webServerHost;
    }

    public int getWebServerPort() {
        return webServerPort;
    }

    public void setWebServerPort(int webServerPort) {
        this.webServerPort = webServerPort;
    }

    public long getUpdateInterval() {
        return updateInterval;
    }

    public void setUpdateInterval(long updateInterval) {
        this.updateInterval = updateInterval;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPass() {
        return pass;
    }

    public void setPass(String pass) {
        this.pass = pass;
    }

    public String getStatusPath() {
        return statusPath;
    }

    public void setStatusPath(String statusPath) {
        this.statusPath = statusPath;
    }
    /* ==================== Start/stop ==================== */

    public void destroy() {
        try {
            // We should keep track of loaded beans and call stop.
            // Modeler should do it...
            Iterator mbeansIt=mbeans.values().iterator();
            MBeanServer mbserver = Registry.getRegistry(null, null).getMBeanServer();
            while( mbeansIt.hasNext()) {
                MBeanProxy proxy=(MBeanProxy)mbeansIt.next();
                Object ooname = proxy.getObjectName();
                if( ooname != null ) {
                    ObjectName oname = null;
                    if(ooname instanceof ObjectName) {
                        oname = (ObjectName)ooname;
                    } else if(ooname instanceof String) {
                        oname = new ObjectName((String)ooname);
                    }
                    if( oname != null ) {
                        mbserver.unregisterMBean(oname);
                    }
                }
            }
        } catch( Throwable t ) {
            log.error( "Destroy error", t );
        }
    }

    public void init() throws IOException {
        try {
            //if( log.isDebugEnabled() )
            log.info("init " + webServerHost + " " + webServerPort);
            reg=Registry.getRegistry(null, null);
            refreshMetadata();
            refreshAttributes();
        } catch( Throwable t ) {
            log.error( "Init error", t );
        }
    }

    public void start() throws IOException {
        if( reg==null)
            init();
    }

    /** Refresh the proxies, if updateInterval passed
     *
     */
    public void refresh()  {
        long time=System.currentTimeMillis();
        if( time - lastRefresh < updateInterval ) {
            return;
        }
        lastRefresh=time;
        refreshMetadata();
        refreshAttributes();
    }

    public void refreshAttributes()  {
        try {
            int cnt=0;
            // connect to apache, get a list of mbeans
            BufferedReader is=getStream( "dmp=*");
            if( is==null ) return;

            String name=null;
            String att=null;
            String val=null;
            while(true) {
                String line=is.readLine();
                if( line==null ) break;
                line=line.trim();
                if( "".equals(line) || line.startsWith("#") ) continue;

                // for each mbean, create a proxy
                if(log.isDebugEnabled())
                    log.debug("Read " + line);

                if(line.startsWith( "[")) {
                    name=line.substring(1);
                    if( name.endsWith("]")) {
                        name=name.substring(0, name.length()-1);
                    }
                }
                // Name/value pair
                int idx=line.indexOf('=');
                if( idx < 0 ) continue;
                att=line.substring(0, idx );
                val=line.substring(idx+1);

                if( log.isDebugEnabled())
                    log.debug("name: " + name + " att=" + att +
                            " val=" + val);

                MBeanProxy proxy=(MBeanProxy)mbeans.get(name);
                if( proxy==null ) {
                    log.info( "Unknown object " + name);
                } else {
                    proxy.update(att, val);
                    cnt++;
                }
            }
            log.info( "Refreshing attributes " + cnt);
        } catch( Exception ex ) {
            log.info("Error ", ex);
        }
    }

    /** connect to apache, get a list of mbeans
      */
    BufferedReader getStream(String qry) throws Exception {
        try {
            String path=statusPath + "?" + qry;
            URL url=new URL( "http", webServerHost, webServerPort, path);
            URLConnection urlc=url.openConnection();
            BufferedReader is=new BufferedReader(new InputStreamReader(urlc.getInputStream()));
            return is;
        } catch (IOException e) {
            log.info( "Can't connect to jkstatus " + webServerHost + ":" + webServerPort
            + " " + e.toString());
            return null;
        }
    }

    public void refreshMetadata() {
        try {
            int cnt=0;
            int newCnt=0;
            BufferedReader is=getStream("lst=*");
            if( is==null ) return;
            String name=null;
            String type=null;
            ArrayList getters=new ArrayList();
            ArrayList setters=new ArrayList();
            ArrayList methods=new ArrayList();
            while(true) {
                String line=is.readLine();
                if( log.isDebugEnabled())
                    log.debug("Read " + line);

                // end of section
                if( line == null || line.startsWith("[") ) {
                    if( name != null ) {
                        cnt++;
                        if( mbeans.get( name ) ==null ) {
                            // New component
                            newCnt++;
                            MBeanProxy mproxy=new MBeanProxy(this);
                            mproxy.init( name, getters, setters, methods);
                            mbeans.put( name, mproxy );
                        }
                        if( log.isDebugEnabled())
                            log.debug("mbean name: " + name + " type=" + type);

                        getters.clear();
                        setters.clear();
                        methods.clear();
                    }
                }
                // end of data
                if( line==null ) break;

                line=line.trim();
                if( "".equals( line ) || line.startsWith("#"))  continue;

                // for each mbean, create a proxy

                if(line.startsWith( "[") && line.endsWith("]")) {
                    name=line.substring(1, line.length()-1);
                }
                if(line.startsWith( "T=")) {
                    type=line.substring(2);
                }
                if( line.startsWith("G=")) {
                    getters.add(line.substring(2));
                }
                if( line.startsWith("S=")) {
                    setters.add(line.substring(2));
                }
                if( line.startsWith("M=")) {
                    methods.add(line.substring(2));
                }
            }
            log.info( "Refreshing metadata " + cnt + " " +  newCnt);
        } catch( Exception ex ) {
            log.info("Error ", ex);
        }
    }

    /** Use the same metadata, except that we replace the attribute
     * get/set methods.
     */
    static class MBeanProxy extends BaseModelMBean {
        private static Log log = LogFactory.getLog(MBeanProxy.class);

        String jkName;
        List getAttNames;
        List setAttNames;
        HashMap atts=new HashMap();
        ModJkMX jkmx;

        public MBeanProxy(ModJkMX jkmx) throws Exception {
            this.jkmx=jkmx;
        }

        void init( String name, List getters, List setters, List methods )
            throws Exception
        {
            if(log.isDebugEnabled())
                log.debug("Register " + name );
            int col=name.indexOf( ':' );
            this.jkName=name;
            String type=name.substring(0, col );
            String id=name.substring(col+1);
            id=id.replace('*','%');
            id=id.replace(':', '%');
            if( id.length() == 0 ) {
                id="default";
            }
            ManagedBean mbean= new ManagedBean();

            AttributeInfo ai=new AttributeInfo();
            ai.setName( "jkName" );
            ai.setType( "java.lang.String");
            ai.setWriteable(false);
            mbean.addAttribute(ai);

            for( int i=0; i<getters.size(); i++ ) {
                String att=(String)getters.get(i);
                // Register metadata
                ai=new AttributeInfo();
                ai.setName( att );
                ai.setType( "java.lang.String");
                if( ! setters.contains(att))
                    ai.setWriteable(false);
                mbean.addAttribute(ai);
            }
            for( int i=0; i<setters.size(); i++ ) {
                String att=(String)setters.get(i);
                if( getters.contains(att))
                    continue;
                // Register metadata
                ai=new AttributeInfo();
                ai.setName( att );
                ai.setType( "java.lang.String");
                ai.setReadable(false);
                mbean.addAttribute(ai);
            }
            for( int i=0; i<methods.size(); i++ ) {
                String att=(String)methods.get(i);
                // Register metadata
                OperationInfo oi=new OperationInfo();
                oi.setName( att );
                oi.setReturnType("void");
                mbean.addOperation(oi);
            }

            this.setModelMBeanInfo(mbean.createMBeanInfo());

            MBeanServer mserver=Registry.getRegistry(null, null).getMBeanServer();
            oname=new ObjectName("apache:type=" + type + ",id=" + id);
            mserver.registerMBean(this, oname);
        }

        private void update( String name, String val ) {
            log.debug( "Updating " + jkName + " " + name + " " + val);
            atts.put( name, val);
        }

        public Object getAttribute(String name)
            throws AttributeNotFoundException, MBeanException,
                ReflectionException {
            if( "jkName".equals( name )) {
                return jkName;
            }
            jkmx.refresh();
            return atts.get(name);
        }

        public void setAttribute(Attribute attribute)
            throws AttributeNotFoundException, MBeanException,
            ReflectionException
        {
            try {
                // we support only string values
                String val=(String)attribute.getValue();
                String name=attribute.getName();
                BufferedReader is=jkmx.getStream("set=" + jkName + "|" +
                        name + "|" + val);
                if( is==null ) return;
                String res=is.readLine();
                if( log.isDebugEnabled())
                    log.debug( "Setting " + jkName + " " + name + " result " + res);

                jkmx.refreshMetadata();
                jkmx.refreshAttributes();
            } catch( Exception ex ) {
                throw new MBeanException(ex);
            }
        }

        public Object invoke(String name, Object params[], String signature[])
            throws MBeanException, ReflectionException {
            try {
                // we support only string values
                BufferedReader is=jkmx.getStream("inv=" + jkName + "|" +
                        name );
                if( is==null ) return null;
                String res=is.readLine();
                if( log.isDebugEnabled())
                    log.debug( "Invoking " + jkName + " " + name + " result " + res);

                jkmx.refreshMetadata();
                jkmx.refreshAttributes();
            } catch( Exception ex ) {
                throw new MBeanException(ex);
            }
            return null;
        }

    }


}

