/*
 * 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.catalina.manager;


import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Set;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.MBeanInfo;
import javax.management.MBeanAttributeInfo;
import javax.management.Attribute;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.modeler.Registry;

/**
 * This servlet will dump JMX attributes in a simple format
 * and implement proxy services for modeler.
 *
 * @author Costin Manolache
 */
public class JMXProxyServlet extends HttpServlet  {
    // ----------------------------------------------------- Instance Variables

    /**
     * MBean server.
     */
    protected MBeanServer mBeanServer = null;
    protected Registry registry;
    // --------------------------------------------------------- Public Methods


    /**
     * Initialize this servlet.
     */
    public void init() throws ServletException {
        // Retrieve the MBean server
        registry = Registry.getRegistry(null, null);
        mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
    }


    /**
     * Process a GET request for the specified resource.
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet-specified error occurs
     */
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {

        response.setContentType("text/plain");

        PrintWriter writer = response.getWriter();

        if( mBeanServer==null ) {
            writer.println("Error - No mbean server");
            return;
        }

        String qry=request.getParameter("set");
        if( qry!= null ) {
            String name=request.getParameter("att");
            String val=request.getParameter("val");

            setAttribute( writer, qry, name, val );
            return;
        }
        qry=request.getParameter("get");
        if( qry!= null ) {
            String name=request.getParameter("att");
            getAttribute( writer, qry, name );
            return;
        }        
        qry=request.getParameter("qry");
        if( qry == null ) {
            qry = "*:*";
        }

        listBeans( writer, qry );

    }

    public void getAttribute(PrintWriter writer, String onameStr, String att) {
        try {
            ObjectName oname = new ObjectName(onameStr);
            Object value = mBeanServer.getAttribute(oname, att);
            writer.println("OK - Attribute get '" + onameStr + "' - " + att
                    + "= " + escape(value.toString()));
        } catch (Exception ex) {
            writer.println("Error - " + ex.toString());
        }
    }

    public void setAttribute( PrintWriter writer,
                              String onameStr, String att, String val )
    {
        try {
            ObjectName oname=new ObjectName( onameStr );
            String type=registry.getType(oname, att);
            Object valueObj=registry.convertValue(type, val );
            mBeanServer.setAttribute( oname, new Attribute(att, valueObj));
            writer.println("OK - Attribute set");
        } catch( Exception ex ) {
            writer.println("Error - " + ex.toString());
        }
    }

    public void listBeans( PrintWriter writer, String qry )
    {

        Set names = null;
        try {
            names=mBeanServer.queryNames(new ObjectName(qry), null);
            writer.println("OK - Number of results: " + names.size());
            writer.println();
        } catch (Exception e) {
            writer.println("Error - " + e.toString());
            return;
        }

        Iterator it=names.iterator();
        while( it.hasNext()) {
            ObjectName oname=(ObjectName)it.next();
            writer.println( "Name: " + oname.toString());

            try {
                MBeanInfo minfo=mBeanServer.getMBeanInfo(oname);
                // can't be null - I thinl
                String code=minfo.getClassName();
                if ("org.apache.commons.modeler.BaseModelMBean".equals(code)) {
                    code=(String)mBeanServer.getAttribute(oname, "modelerType");
                }
                writer.println("modelerType: " + code);

                MBeanAttributeInfo attrs[]=minfo.getAttributes();
                Object value=null;

                for( int i=0; i< attrs.length; i++ ) {
                    if( ! attrs[i].isReadable() ) continue;
                    if( ! isSupported( attrs[i].getType() )) continue;
                    String attName=attrs[i].getName();
                    if( attName.indexOf( "=") >=0 ||
                            attName.indexOf( ":") >=0 ||
                            attName.indexOf( " ") >=0 ) {
                        continue;
                    }
            
                    try {
                        value=mBeanServer.getAttribute(oname, attName);
                    } catch( Throwable t) {
                        System.out.println("Error getting attribute " + oname +
                                " " + attName + " " + t.toString());
                        continue;
                    }
                    if( value==null ) continue;
                    if( "modelerType".equals( attName)) continue;
                    String valueString=value.toString();
                    writer.println( attName + ": " + escape(valueString));
                }
            } catch (Exception e) {
                // Ignore
            }
            writer.println();
        }

    }

    public String escape(String value) {
        // The only invalid char is \n
        // We also need to keep the string short and split it with \nSPACE
        // XXX TODO
        int idx=value.indexOf( "\n" );
        if( idx < 0 ) return value;

        int prev=0;
        StringBuffer sb=new StringBuffer();
        while( idx >= 0 ) {
            appendHead(sb, value, prev, idx);

            sb.append( "\\n\n ");
            prev=idx+1;
            if( idx==value.length() -1 ) break;
            idx=value.indexOf('\n', idx+1);
        }
        if( prev < value.length() )
            appendHead( sb, value, prev, value.length());
        return sb.toString();
    }

    private void appendHead( StringBuffer sb, String value, int start, int end) {
        if (end < 1) return;
        
        int pos=start;
        while( end-pos > 78 ) {
            sb.append( value.substring(pos, pos+78));
            sb.append( "\n ");
            pos=pos+78;
        }
        sb.append( value.substring(pos,end));
    }

    public boolean isSupported( String type ) {
        return true;
    }
}
