// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.monitor.integration; import static java.lang.Integer.parseInt; import static java.lang.System.getProperty; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.Socket; import java.net.URL; import java.util.Collection; import java.util.Map; import java.util.Properties; import java.util.Set; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.eclipse.jetty.client.ContentExchange; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.monitor.JMXMonitor; import org.eclipse.jetty.monitor.jmx.EventNotifier; import org.eclipse.jetty.monitor.jmx.EventState; import org.eclipse.jetty.monitor.jmx.EventState.TriggerState; import org.eclipse.jetty.monitor.jmx.EventTrigger; import org.eclipse.jetty.monitor.jmx.MonitorAction; import org.eclipse.jetty.monitor.triggers.AggregateEventTrigger; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ /** */ public class JavaMonitorAction extends MonitorAction { private static final Logger LOG = Log.getLogger(JavaMonitorAction.class); private final HttpClient _client; private final String _url; private final String _uuid; private final String _appid; private String _srvip; private String _session; /* ------------------------------------------------------------ */ /** * @param notifier * @param pollInterval * @throws Exception * @throws MalformedObjectNameException */ public JavaMonitorAction(EventNotifier notifier, String url, String uuid, String appid, long pollInterval) throws Exception { super(new AggregateEventTrigger(),notifier,pollInterval); _url = url; _uuid = uuid; _appid = appid; _client = new HttpClient(); _client.setTimeout(60000); _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); try { _client.start(); _srvip = getServerIP(); } catch (Exception ex) { LOG.debug(ex); } sendData(new Properties()); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.monitor.jmx.MonitorAction#execute(org.eclipse.jetty.monitor.jmx.EventTrigger, org.eclipse.jetty.monitor.jmx.EventState, long) */ @Override public void execute(EventTrigger trigger, EventState<?> state, long timestamp) { exec(trigger, state, timestamp); } /* ------------------------------------------------------------ */ /** * @param trigger * @param state * @param timestamp */ private <T> void exec(EventTrigger trigger, EventState<T> state, long timestamp) { Collection<TriggerState<T>> trs = state.values(); Properties data = new Properties(); for (TriggerState<T> ts : trs) { Object value = ts.getValue(); StringBuffer buffer = new StringBuffer(); buffer.append(value == null ? "" : value.toString()); buffer.append("|"); buffer.append(getClassID(value)); buffer.append("||"); buffer.append(ts.getDescription()); data.setProperty(ts.getID(), buffer.toString()); try { sendData(data); } catch (Exception ex) { LOG.debug(ex); } } } /* ------------------------------------------------------------ */ /** * @param data * @throws Exception */ private void sendData(Properties data) throws Exception { data.put("account", _uuid); data.put("appserver", "Jetty"); data.put("localIp", _srvip); if (_appid == null) data.put("lowestPort", getHttpPort()); else data.put("lowestPort", _appid); if (_session != null) data.put("session", _session); Properties response = sendRequest(data); parseResponse(response); } /* ------------------------------------------------------------ */ /** * @param request * @return * @throws Exception */ private Properties sendRequest(Properties request) throws Exception { ByteArrayOutputStream reqStream = null; ByteArrayInputStream resStream = null; Properties response = null; try { ContentExchange reqEx = new ContentExchange(); reqEx.setURL(_url); reqEx.setMethod(HttpMethods.POST); reqEx.addRequestHeader("Connection","close"); reqStream = new ByteArrayOutputStream(); request.storeToXML(reqStream,null); ByteArrayBuffer reqBuff = new ByteArrayBuffer(reqStream.toByteArray()); reqEx.setRequestContent(reqBuff); _client.send(reqEx); reqEx.waitForDone(); if (reqEx.getResponseStatus() == HttpStatus.OK_200) { response = new Properties(); resStream = new ByteArrayInputStream(reqEx.getResponseContentBytes()); response.loadFromXML(resStream); } } finally { try { if (reqStream != null) reqStream.close(); } catch (IOException ex) { LOG.ignore(ex); } try { if (resStream != null) resStream.close(); } catch (IOException ex) { LOG.ignore(ex); } } return response; } /* ------------------------------------------------------------ */ private void parseResponse(Properties response) { if (response.get("onhold") != null) throw new Error("Suspended"); if (response.get("session") != null) { _session = (String) response.remove("session"); AggregateEventTrigger trigger = (AggregateEventTrigger)getTrigger(); String queryString; ObjectName[] queryResults; for (Map.Entry<Object, Object> entry : response.entrySet()) { String[] values = ((String) entry.getValue()).split("\\|"); queryString = values[0]; if (queryString.startsWith("com.javamonitor.openfire")) continue; if (queryString.startsWith("com.javamonitor")) { queryString = "org.eclipse.jetty.monitor.integration:type=javamonitortools,id=0"; } queryResults = null; try { queryResults = queryNames(queryString); } catch (IOException e) { LOG.debug(e); } catch (MalformedObjectNameException e) { LOG.debug(e); } if (queryResults != null) { int idx = 0; for(ObjectName objName : queryResults) { String id = entry.getKey().toString()+(idx == 0 ? "" : ":"+idx); String name = queryString.equals(objName.toString()) ? "" : objName.toString(); boolean repeat = Boolean.parseBoolean(values[2]); trigger.add(new JavaMonitorTrigger(objName, values[1], id, name, repeat)); } } } } } /* ------------------------------------------------------------ */ /** * @param value * @return */ private int getClassID(final Object value) { if (value == null) return 0; if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) return 1; if (value instanceof Float || value instanceof Double) return 2; if (value instanceof Boolean) return 3; return 4; // String } /* ------------------------------------------------------------ */ /** * @return * @throws Exception */ private String getServerIP() throws Exception { Socket s = null; try { if (getProperty("http.proxyHost") != null) { s = new Socket(getProperty("http.proxyHost"), parseInt(getProperty("http.proxyPort", "80"))); } else { int port = 80; URL url = new URL(_url); if (url.getPort() != -1) { port = url.getPort(); } s = new Socket(url.getHost(), port); } return s.getLocalAddress().getHostAddress(); } finally { try { if (s != null) s.close(); } catch (IOException ex) { LOG.ignore(ex); } } } /* ------------------------------------------------------------ */ public Integer getHttpPort() { Collection<ObjectName> connectors = null; MBeanServerConnection service; try { service = JMXMonitor.getServiceConnection(); connectors = service.queryNames(new ObjectName("org.eclipse.jetty.nio:type=selectchannelconnector,*"), null); if (connectors != null && connectors.size() > 0) { Integer lowest = Integer.MAX_VALUE; for (final ObjectName connector : connectors) { lowest = (Integer)service.getAttribute(connector, "port"); } if (lowest < Integer.MAX_VALUE) return lowest; } } catch (Exception ex) { LOG.debug(ex); } return 0; } /* ------------------------------------------------------------ */ /** * @param param * @return * @throws IOException * @throws NullPointerException * @throws MalformedObjectNameException */ private ObjectName[] queryNames(ObjectName param) throws IOException, MalformedObjectNameException { ObjectName[] result = null; MBeanServerConnection connection = JMXMonitor.getServiceConnection(); Set names = connection.queryNames(param, null); if (names != null && names.size() > 0) { result = new ObjectName[names.size()]; int idx = 0; for(Object name : names) { if (name instanceof ObjectName) result[idx++] = (ObjectName)name; else result[idx++] = new ObjectName(name.toString()); } } return result; } private ObjectName[] queryNames(String param) throws IOException, MalformedObjectNameException { return queryNames(new ObjectName(param)); } }