001/*
002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Stephane Lacoin at Nuxeo (aka matic)
016 */
017package org.nuxeo.connect.tools.report.management;
018
019import java.io.IOException;
020import java.io.OutputStream;
021import java.io.OutputStreamWriter;
022import java.util.Arrays;
023import java.util.HashMap;
024import java.util.Map;
025
026import javax.management.JMException;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.jolokia.backend.BackendManager;
031import org.jolokia.config.ConfigKey;
032import org.jolokia.config.Configuration;
033import org.jolokia.request.JmxRequest;
034import org.jolokia.request.JmxRequestFactory;
035import org.jolokia.util.LogHandler;
036import org.jolokia.util.RequestType;
037import org.json.simple.JSONObject;
038import org.nuxeo.runtime.model.DefaultComponent;
039
040/**
041 * Platform mbean server invoker which output results in json based on jolokia.
042 *
043 * @since 8.3
044 */
045public class MXComponent extends DefaultComponent {
046
047    static MXComponent instance;
048
049    public MXComponent() {
050        instance = this;
051    }
052
053    // jolokia configuration
054    final Configuration config = new Configuration(ConfigKey.AGENT_ID, "false", ConfigKey.IGNORE_ERRORS, "true");
055
056    final BackendManager manager = new BackendManager(config, new LogHandler() {
057
058        final Log log = LogFactory.getLog(MXComponent.class);
059
060        @Override
061        public void info(String message) {
062            log.info(message);
063        }
064
065        @Override
066        public void error(String message, Throwable t) {
067            log.error(message, t);
068        }
069
070        @Override
071        public void debug(String message) {
072            log.debug(message);
073        }
074    });
075
076    /**
077     * Jolokia request builder
078     *
079     *
080     */
081    class RequestBuilder {
082
083        RequestBuilder(RequestType oftype) {
084            pRequestMap.put("type", oftype.getName());
085        }
086
087        @SuppressWarnings("unchecked")
088        final Map<String, Object> pRequestMap = new JSONObject();
089
090        RequestBuilder withMbean(String value) {
091            pRequestMap.put("mbean", value);
092            return this;
093        }
094
095        RequestBuilder withOperation(String value, Object... arguments) {
096            pRequestMap.put("operation", value);
097            pRequestMap.put("arguments", Arrays.asList(arguments));
098            return this;
099        }
100
101        final Map<String, String> pParams = new HashMap<>();
102
103        void run(OutputStream sink) {
104            try {
105                JmxRequest request = JmxRequestFactory.createPostRequest(pRequestMap, config.getProcessingParameters(pParams));
106                JSONObject json = manager.handleRequest(request);
107                OutputStreamWriter writer = new OutputStreamWriter(sink);
108                json.writeJSONString(writer);
109                writer.flush();
110            } catch (JMException | IOException cause) {
111                throw new AssertionError("Cannot invoke jolokia", cause);
112            }
113        }
114
115    }
116
117    RequestBuilder list() {
118        return new RequestBuilder(RequestType.LIST);
119    }
120
121    RequestBuilder search(String pattern) {
122        return new RequestBuilder(RequestType.SEARCH)
123                .withMbean(pattern);
124    }
125
126    RequestBuilder read(String pattern) {
127        return new RequestBuilder(RequestType.READ)
128                .withMbean(pattern);
129    }
130
131    RequestBuilder exec(String pattern, String operation, Object... arguments) {
132        return new RequestBuilder(RequestType.EXEC)
133                .withMbean(pattern)
134                .withOperation(operation, arguments);
135    }
136
137}