/*
 * 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.sling.jmx.provider.impl;

import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeMap;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.servlet.http.HttpServletRequest;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceProvider;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.commons.osgi.PropertiesUtil;

@Component(metatype=true,
    label="Apache Sling JMX Resource Provider",
    description="This provider mounts JMX mbeans into the resource tree.")
@Service(value = ResourceProvider.class)
@Properties({
    @Property(name = ResourceProvider.ROOTS, value="/system/sling/monitoring/mbeans",
            label="Root",
            description="The mount point of the JMX beans"),
    @Property(name = ResourceProvider.USE_RESOURCE_ACCESS_SECURITY, boolValue=true, propertyPrivate=true),
    @Property(name = ResourceProvider.OWNS_ROOTS, boolValue=true, propertyPrivate=true)
})
/**
 * Brief summary of a "good" object name:
 *
 * Object names:
 * - have a domain
 * - should have a type property
 * - could have a name property
 * - additional props are not recommended
 *
 * Path to an MBean:
 * {Domain}/{type property}/{name property}{all other props}
 * where
 * {Domain} : is a path consisting of the domain (dots replaced with slashes)
 * {type property} : is the value of the type property or "{notype}" if no type property is set
 * {name property} : is the value of the name property or "{noname}" if no name property is set
 * {all other props} : name/value pairs containing all additional props
 */
public class JMXResourceProvider implements ResourceProvider {

    /** Configured root paths, ending with a slash */
    private String[] rootsWithSlash;

    /** Configured root paths, not ending with a slash */
    private String[] roots;

    /** The mbean server. */
    private MBeanServer mbeanServer;

    @Activate
    protected void activate(final Map<String, Object> props) {
        final String paths[] = PropertiesUtil.toStringArray(props.get(ResourceProvider.ROOTS));
        final List<String> rootsList = new ArrayList<String>();
        final List<String> rootsWithSlashList = new ArrayList<String>();
        if ( paths != null ) {
            for(final String p : paths) {
                if ( p.length() > 0 ) {
                    if ( p.endsWith("/") ) {
                        rootsList.add(p.substring(0,  p.length() - 1));
                        rootsWithSlashList.add(p);
                    } else {
                        rootsList.add(p);
                        rootsWithSlashList.add(p + "/");
                    }
                }
            }
        }
        this.rootsWithSlash = rootsWithSlashList.toArray(new String[rootsWithSlashList.size()]);
        this.roots = rootsList.toArray(new String[rootsList.size()]);

        this.mbeanServer = ManagementFactory.getPlatformMBeanServer();
    }

    @Deactivate
    protected void deactivate() {
        this.mbeanServer = null;
    }

    /**
     * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, javax.servlet.http.HttpServletRequest, java.lang.String)
     */
    public Resource getResource(final ResourceResolver resourceResolver,
                                final HttpServletRequest request,
                                final String path) {
        return getResource(resourceResolver, path);
    }

    /**
     * @see org.apache.sling.api.resource.ResourceProvider#getResource(org.apache.sling.api.resource.ResourceResolver, java.lang.String)
     */
    public Resource getResource(final ResourceResolver resourceResolver,
                                final String path) {
        final PathInfo info = this.parse(path);
        if ( info != null ) {
            if ( info.isRoot ) {
                return new RootResource(resourceResolver, path);
            }
            if ( info.mbeanInfo == null ) {
                final Set<ObjectName> names = this.queryObjectNames(info.pathInfo);
                if ( names.size() != 0 ) {
                    return new RootResource(resourceResolver, path);
                }
            } else {
                if (info.pathInfo == null ) {
                    return new MBeanResource(this.mbeanServer, resourceResolver, this.convertObjectNameToResourcePath(info.objectName), path, info.mbeanInfo, info.objectName);
                }
                if ( info.pathInfo.equals("mbean:attributes") ) {
                    final MBeanResource parent = (MBeanResource)this.getResource(resourceResolver, ResourceUtil.getParent(path));
                    return new AttributesResource(resourceResolver, path, parent);
                }
                if ( info.pathInfo.startsWith("mbean:attributes/") ) {
                    final Resource parentRsrc = this.getResource(resourceResolver, ResourceUtil.getParent(path));
                    final AttributesResource parentAttributesResource;
                    final MBeanResource parentMBeanResource;
                    if ( parentRsrc instanceof AttributesResource ) {
                        parentAttributesResource = (AttributesResource) parentRsrc;
                        parentMBeanResource = (MBeanResource)parentRsrc.getParent();
                    } else {
                        final AttributeResource parent;
                        if ( parentRsrc instanceof AttributeResource) {
                            parent = (AttributeResource)parentRsrc;
                        } else {
                            parent = ((MapResource)parentRsrc).getAttributeResource();
                        }
                        parentAttributesResource = (AttributesResource) parent.getParent();
                        parentMBeanResource = (MBeanResource) parentAttributesResource.getParent();
                    }
                    final AttributeList result = parentMBeanResource.getAttributes();

                    final String attrPath = info.pathInfo.substring("mbean:attributes/".length());
                    final int pos = attrPath.indexOf('/');
                    final String attrName;
                    final String subPath;
                    if ( pos == -1 ) {
                        attrName = attrPath;
                        subPath = null;
                    } else {
                        attrName = attrPath.substring(0, pos);
                        subPath = attrPath.substring(pos + 1);
                    }
                    for(final MBeanAttributeInfo mai : info.mbeanInfo.getAttributes()) {
                        if ( mai.getName().equals(attrName) ) {
                            final Iterator iter = result.iterator();
                            Object value = null;
                            while ( iter.hasNext() && value == null ) {
                                final Attribute a = (Attribute) iter.next();
                                if ( a.getName().equals(attrName) ) {
                                    value = a.getValue();
                                }
                            }
                            final AttributeResource rsrc = new AttributeResource(resourceResolver, path, mai, value, parentAttributesResource);
                            if ( subPath != null ) {
                                return rsrc.getChildResource(subPath);
                            }
                            return rsrc;
                        }
                    }
                }
            }
        }
        return null;
    }

    private Set<ObjectName> queryObjectNames(final String prefix) {
        final Set<ObjectName> allNames = this.mbeanServer.queryNames(null, null);
        Set<ObjectName> names = allNames;
        if ( prefix != null ) {
            final String pathPrefix = prefix + '/';
            names = new HashSet<ObjectName>();
            for(final ObjectName name : allNames) {
                final String path = this.convertObjectNameToResourcePath(name);
                if ( path.startsWith(pathPrefix) ) {
                    names.add(name);
                }
            }
        }
        return names;
    }
    /**
     * @see org.apache.sling.api.resource.ResourceProvider#listChildren(org.apache.sling.api.resource.Resource)
     */
    public Iterator<Resource> listChildren(final Resource parent) {
        final PathInfo info = this.parse(parent.getPath());
        if ( info != null ) {
            if ( info.isRoot || info.mbeanInfo == null ) {
                // list all MBeans
                final Set<ObjectName> names = this.queryObjectNames(info.isRoot ? null : info.pathInfo);
                final Set<String> filteredNames = new HashSet<String>();
                final String prefix = (info.isRoot ? null : info.pathInfo + "/");
                for(final ObjectName name : names) {
                    final String path = this.convertObjectNameToResourcePath(name);
                    final String testName = (info.isRoot ? path : path.substring(prefix.length()));
                    final int sep = testName.indexOf('/');
                    if ( sep == -1 ) {
                        filteredNames.add(":" + name.getCanonicalName());
                    } else {
                        filteredNames.add(testName.substring(0, sep));
                    }
                }
                final List<String> sortedNames = new ArrayList<String>(filteredNames);

                Collections.sort(sortedNames);
                final Iterator<String> iter = sortedNames.iterator();
                return new Iterator<Resource>() {

                    private Resource next;

                    {
                        seek();
                    }

                    private void seek() {
                        while ( iter.hasNext() && this.next == null ) {
                            final String name = iter.next();
                            if ( name.startsWith(":") ) {
                                try {
                                    final ObjectName on = new ObjectName(name.substring(1));
                                    final MBeanInfo info = mbeanServer.getMBeanInfo(on);
                                    final String path = convertObjectNameToResourcePath(on);
                                    final int sep = path.lastIndexOf('/');
                                    this.next = new MBeanResource(mbeanServer, parent.getResourceResolver(), path, parent.getPath() + "/" + path.substring(sep + 1), info, on);
                                } catch (final IntrospectionException e) {
                                    // ignore
                                } catch (final InstanceNotFoundException e) {
                                    // ignore
                                } catch (final ReflectionException e) {
                                    // ignore
                                } catch (final MalformedObjectNameException e) {
                                    // ignore
                                }
                            } else {
                                this.next = new RootResource(parent.getResourceResolver(), parent.getPath() + '/' + name);
                            }
                        }
                    }

                    public boolean hasNext() {
                        return next != null;
                    }

                    public Resource next() {
                        if ( next != null ) {
                            final Resource rsrc = next;
                            this.next = null;
                            seek();
                            return rsrc;
                        }
                        throw new NoSuchElementException();
                    }

                    public void remove() {
                        throw new UnsupportedOperationException("remove");
                    }
                };
            } else {
                if ( info.pathInfo == null ) {
                    final MBeanResource parentResource;
                    if ( parent instanceof MBeanResource ) {
                        parentResource = (MBeanResource)parent;
                    } else {
                        parentResource = (MBeanResource)this.getResource(parent.getResourceResolver(), parent.getPath());
                    }
                    final List<Resource> list = new ArrayList<Resource>();
                    list.add(new AttributesResource(parent.getResourceResolver(), parent.getPath() + "/mbean:attributes", parentResource));
                    return list.iterator();
                } else if ( info.pathInfo.equals("mbean:attributes") ) {
                    final AttributesResource parentResource;
                    if ( parent instanceof AttributesResource ) {
                        parentResource = (AttributesResource)parent;
                    } else {
                        parentResource = (AttributesResource) this.getResource(parent.getResourceResolver(), parent.getPath());
                    }
                    final MBeanResource parentMBeanResource = (MBeanResource)parentResource.getParent();
                    final AttributeList result = parentMBeanResource.getAttributes();

                    final MBeanAttributeInfo[] infos = info.mbeanInfo.getAttributes();
                    final Map<String, MBeanAttributeInfo> infoMap = new HashMap<String, MBeanAttributeInfo>();
                    for(final MBeanAttributeInfo i : infos) {
                        infoMap.put(i.getName(), i);
                    }
                    final Iterator iter = result.iterator();
                    return new Iterator<Resource>() {

                        public void remove() {
                            throw new UnsupportedOperationException("remove");
                        }

                        public Resource next() {
                            final Attribute attr = (Attribute)iter.next();
                            return new AttributeResource(parent.getResourceResolver(),
                                    parent.getPath() + "/" + attr.getName(),
                                    infoMap.get(attr.getName()),
                                    attr.getValue(),
                                    parentResource);
                        }

                        public boolean hasNext() {
                            return iter.hasNext();
                        }
                    };
                } else if ( info.pathInfo.startsWith("mbean:attributes/") ) {
                    Resource checkParentResource = parent;
                    if ( !(checkParentResource instanceof AttributeResource) && !(checkParentResource instanceof MapResource ) ) {
                        checkParentResource = this.getResource(parent.getResourceResolver(), parent.getPath());
                    }
                    final AttributeResource parentResource;
                    if ( checkParentResource instanceof AttributeResource ) {
                        parentResource = (AttributeResource)checkParentResource;
                    } else {
                        parentResource = ((MapResource)checkParentResource).getAttributeResource();
                    }

                    final String attrPath = info.pathInfo.substring("mbean:attributes/".length());
                    final int pos = attrPath.indexOf('/');
                    final String subPath;
                    if ( pos == -1 ) {
                        subPath = null;
                    } else {
                        subPath = attrPath.substring(pos + 1);
                    }

                    return parentResource.getChildren(parent.getPath(), subPath);

                }
            }
        }
        return null;
    }

    private static final String MARKER_NOTYPE = "{notype}";
    private static final String MARKER_NONAME = "{noname}";

    private String encode(final String value) {
        try {
            return URLEncoder.encode(value, "UTF-8");
        } catch (final UnsupportedEncodingException uee) {
            // this should never happen, UTF-8 is always supported
            return value;
        }
    }

    private String decode(final String value) {
        try {
            return URLDecoder.decode(value, "UTF-8");
        } catch (final UnsupportedEncodingException uee) {
            // this should never happen, UTF-8 is always supported
            return value;
        }
    }

    private String convertObjectNameToResourcePath(final ObjectName name) {
        final StringBuilder sb = new StringBuilder(name.getDomain().replace('.', '/'));
        sb.append('/');
        if ( name.getKeyProperty("type") != null ) {
            sb.append(encode(name.getKeyProperty("type")));
        } else {
            sb.append(MARKER_NOTYPE);
        }
        sb.append('/');
        if ( name.getKeyProperty("name") != null ) {
            sb.append(encode(name.getKeyProperty("name")));
        } else {
            sb.append(MARKER_NONAME);
        }
        final TreeMap<String, String> props = new TreeMap<String, String>(name.getKeyPropertyList());
        props.remove("name");
        props.remove("type");
        boolean first = true;
        for(final Map.Entry<String, String> entry : props.entrySet()) {
            if ( first ) {
                first = false;
                sb.append(':');
            } else {
                sb.append(',');
            }
            sb.append(encode(entry.getKey()));
            sb.append('=');
            sb.append(encode(entry.getValue()));
        }
        return sb.toString();
    }

    private ObjectName convertResourcePathToObjectName(final String path) {
        final int nameSlash = path.lastIndexOf('/');
        if ( nameSlash != -1 ) {
            final int typeSlash = path.lastIndexOf('/', nameSlash - 1);
            if ( typeSlash != -1 ) {
                final String domain = path.substring(0, typeSlash).replace('/', '.');
                final String type = decode(path.substring(typeSlash + 1, nameSlash));
                final String nameAndProps = path.substring(nameSlash + 1);
                final int colonPos = nameAndProps.indexOf(':');
                final String name;
                final String props;
                if ( colonPos == -1 ) {
                    name = decode(nameAndProps);
                    props = null;
                } else {
                    name = decode(nameAndProps.substring(0,  colonPos));
                    props = nameAndProps.substring(colonPos + 1);
                }
                final StringBuilder sb = new StringBuilder();
                sb.append(domain);
                sb.append(':');
                boolean hasProps = false;
                if ( !MARKER_NOTYPE.equals(type)) {
                    sb.append("type=");
                    sb.append(type);
                    hasProps = true;
                }
                if ( !MARKER_NONAME.equals(name) ) {
                    if ( hasProps ) {
                        sb.append(",");
                    }
                    sb.append("name=");
                    sb.append(name);
                    hasProps = true;
                }
                if ( props != null ) {
                    final String[] propArray = props.split(",");
                    for(final String keyValue : propArray) {
                        if ( hasProps ) {
                            sb.append(",");
                        }
                        final int pos = keyValue.indexOf('=');
                        if ( pos == -1 ) {
                            return null;
                        }
                        sb.append(decode(keyValue.substring(0, pos)));
                        sb.append('=');
                        sb.append(decode(keyValue.substring(pos+1)));
                    }
                }
                try {
                    return new ObjectName(sb.toString());
                } catch (final MalformedObjectNameException e) {
                    // ignore
                }
            }
        }
        return null;
    }

    public final static class PathInfo {

        public final boolean isRoot;
        public final String pathInfo;

        public ObjectName objectName;
        public MBeanInfo mbeanInfo;

        public PathInfo(final boolean isRoot) {
            this.isRoot = isRoot;
            this.pathInfo = null;
        }

        public PathInfo(final String info) {
            this.isRoot = false;
            this.pathInfo = info;
        }
    }

    /**
     * Parse the path
     */
    private PathInfo parse(final String path) {
        for(final String root : this.rootsWithSlash) {
            if ( path.startsWith(root) ) {
                final String subPath = path.substring(root.length());
                if ( subPath.length() == 0 ) {
                    return new PathInfo(true);
                }
                // MBean name / path
                String checkPath = subPath;
                String pathInfo = null;

                ObjectName objectName = null;
                MBeanInfo mbi = null;

                while ( checkPath.length() > 0 && mbi == null ) {
                    try {
                        objectName = this.convertResourcePathToObjectName(checkPath);
                        if ( objectName != null ) {
                            mbi = this.mbeanServer.getMBeanInfo(objectName);
                        }
                    } catch (final IntrospectionException e) {
                        // ignore
                    } catch (final InstanceNotFoundException e) {
                        // ignore
                    } catch (final ReflectionException e) {
                        // ignore
                    }
                    if ( mbi == null ) {
                        final int sep = checkPath.lastIndexOf('/');
                        if ( sep == -1 ) {
                            checkPath = "";
                            pathInfo = subPath;
                        } else {
                            checkPath = checkPath.substring(0, sep);
                            pathInfo = subPath.substring(sep + 1);
                        }
                    }
                }
                final PathInfo info = new PathInfo(pathInfo);
                if ( mbi != null ) {
                    info.objectName = objectName;
                    info.mbeanInfo = mbi;
                }
                return info;
            }
        }
        for(final String root : this.roots) {
            if ( path.equals(root) ) {
                return new PathInfo(true);
            }
        }
        return null;

    }
}
