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

import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.Set;

import javax.management.JMRuntimeException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;

/**
 * General helper to dump MBean contents to the log.
 *
 */
public class MBeanDumper {

    private static final Log log = LogFactory.getLog(MBeanDumper.class);

    private static final String CRLF = "\r\n";

    /**
     * The following code to dump MBeans has been copied from JMXProxyServlet.
     * @param mbeanServer the MBean server
     * @param names a set of object names for which to dump the info
     * @return a string representation of the MBeans
     */
    public static String dumpBeans(MBeanServer mbeanServer, Set<ObjectName> names)
    {
        StringBuilder buf = new StringBuilder();
        Iterator<ObjectName> it=names.iterator();
        while( it.hasNext()) {
            ObjectName oname=it.next();
            buf.append("Name: ");
            buf.append(oname.toString());
            buf.append(CRLF);

            try {
                MBeanInfo minfo=mbeanServer.getMBeanInfo(oname);
                // can't be null - I think
                String code=minfo.getClassName();
                if ("org.apache.commons.modeler.BaseModelMBean".equals(code)) {
                    code=(String)mbeanServer.getAttribute(oname, "modelerType");
                }
                buf.append("modelerType: ");
                buf.append(code);
                buf.append(CRLF);

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

                for (int i=0; i< attrs.length; i++) {
                    if (! attrs[i].isReadable()) continue;
                    String attName=attrs[i].getName();
                    if ("modelerType".equals(attName)) continue;
                    if (attName.indexOf('=') >=0 ||
                            attName.indexOf(':') >=0 ||
                            attName.indexOf(' ') >=0 ) {
                        continue;
                    }

                    try {
                        value=mbeanServer.getAttribute(oname, attName);
                    } catch (JMRuntimeException rme) {
                        Throwable cause = rme.getCause();
                        if (cause instanceof UnsupportedOperationException) {
                            if (log.isDebugEnabled()) {
                                log.debug("Error getting attribute " + oname
                                        + " " + attName, rme);
                            }
                        } else if (cause instanceof NullPointerException) {
                            if (log.isDebugEnabled()) {
                                log.debug("Error getting attribute " + oname
                                        + " " + attName, rme);
                            }
                        } else {
                            log.error("Error getting attribute " + oname +
                                    " " + attName, rme);
                        }
                        continue;
                    } catch (Throwable t) {
                        ExceptionUtils.handleThrowable(t);
                        log.error("Error getting attribute " + oname +
                                " " + attName, t);
                        continue;
                    }
                    if (value==null) continue;
                    String valueString;
                    try {
                        Class<?> c = value.getClass();
                        if (c.isArray()) {
                            int len = Array.getLength(value);
                            StringBuilder sb = new StringBuilder("Array[" +
                                    c.getComponentType().getName() + "] of length " + len);
                            if (len > 0) {
                                sb.append(CRLF);
                            }
                            for (int j = 0; j < len; j++) {
                                sb.append("\t");
                                Object item = Array.get(value, j);
                                if (item == null) {
                                    sb.append("NULL VALUE");
                                } else {
                                    try {
                                        sb.append(escape(item.toString()));
                                    }
                                    catch (Throwable t) {
                                        ExceptionUtils.handleThrowable(t);
                                        sb.append("NON-STRINGABLE VALUE");
                                    }
                                }
                                if (j < len - 1) {
                                    sb.append(CRLF);
                                }
                            }
                            valueString = sb.toString();
                        }
                        else {
                            valueString = escape(value.toString());
                        }
                        buf.append(attName);
                        buf.append(": ");
                        buf.append(valueString);
                        buf.append(CRLF);
                    }
                    catch (Throwable t) {
                        ExceptionUtils.handleThrowable(t);
                    }
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
            }
            buf.append(CRLF);
        }
        return buf.toString();

    }

    public static 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;
        StringBuilder sb=new StringBuilder();
        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 static void appendHead( StringBuilder 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));
    }

}
