1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.monitor.integration;
15
16 import static java.lang.Integer.parseInt;
17 import static java.lang.System.getProperty;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.net.Socket;
23 import java.net.URL;
24 import java.util.Collection;
25 import java.util.Map;
26 import java.util.Properties;
27 import java.util.Set;
28
29 import javax.management.MBeanServerConnection;
30 import javax.management.MalformedObjectNameException;
31 import javax.management.ObjectName;
32
33 import org.eclipse.jetty.client.ContentExchange;
34 import org.eclipse.jetty.client.HttpClient;
35 import org.eclipse.jetty.http.HttpMethods;
36 import org.eclipse.jetty.http.HttpStatus;
37 import org.eclipse.jetty.io.ByteArrayBuffer;
38 import org.eclipse.jetty.monitor.JMXMonitor;
39 import org.eclipse.jetty.monitor.jmx.EventNotifier;
40 import org.eclipse.jetty.monitor.jmx.EventState;
41 import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
42 import org.eclipse.jetty.monitor.jmx.EventTrigger;
43 import org.eclipse.jetty.monitor.jmx.MonitorAction;
44 import org.eclipse.jetty.monitor.triggers.AggregateEventTrigger;
45 import org.eclipse.jetty.util.log.Log;
46 import org.eclipse.jetty.util.log.Logger;
47
48
49
50
51
52 public class JavaMonitorAction extends MonitorAction
53 {
54 private static final Logger LOG = Log.getLogger(JavaMonitorAction.class);
55
56 private final HttpClient _client;
57
58 private final String _url;
59 private final String _uuid;
60 private final String _appid;
61
62 private String _srvip;
63 private String _session;
64
65
66
67
68
69
70
71
72 public JavaMonitorAction(EventNotifier notifier, String url, String uuid, String appid, long pollInterval)
73 throws Exception
74 {
75 super(new AggregateEventTrigger(),notifier,pollInterval);
76
77 _url = url;
78 _uuid = uuid;
79 _appid = appid;
80
81 _client = new HttpClient();
82 _client.setTimeout(60000);
83 _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
84
85 try
86 {
87 _client.start();
88 _srvip = getServerIP();
89 }
90 catch (Exception ex)
91 {
92 LOG.debug(ex);
93 }
94
95 sendData(new Properties());
96 }
97
98
99
100
101
102 @Override
103 public void execute(EventTrigger trigger, EventState<?> state, long timestamp)
104 {
105 exec(trigger, state, timestamp);
106 }
107
108
109
110
111
112
113
114 private <T> void exec(EventTrigger trigger, EventState<T> state, long timestamp)
115 {
116 Collection<TriggerState<T>> trs = state.values();
117
118 Properties data = new Properties();
119 for (TriggerState<T> ts : trs)
120 {
121 Object value = ts.getValue();
122
123 StringBuffer buffer = new StringBuffer();
124 buffer.append(value == null ? "" : value.toString());
125 buffer.append("|");
126 buffer.append(getClassID(value));
127 buffer.append("||");
128 buffer.append(ts.getDescription());
129
130 data.setProperty(ts.getID(), buffer.toString());
131
132 try
133 {
134 sendData(data);
135 }
136 catch (Exception ex)
137 {
138 LOG.debug(ex);
139 }
140 }
141 }
142
143
144
145
146
147
148 private void sendData(Properties data)
149 throws Exception
150 {
151 data.put("account", _uuid);
152 data.put("appserver", "Jetty");
153 data.put("localIp", _srvip);
154 if (_appid == null)
155 data.put("lowestPort", getHttpPort());
156 else
157 data.put("lowestPort", _appid);
158 if (_session != null)
159 data.put("session", _session);
160
161 Properties response = sendRequest(data);
162
163 parseResponse(response);
164 }
165
166
167
168
169
170
171
172 private Properties sendRequest(Properties request)
173 throws Exception
174 {
175 ByteArrayOutputStream reqStream = null;
176 ByteArrayInputStream resStream = null;
177 Properties response = null;
178
179 try {
180 ContentExchange reqEx = new ContentExchange();
181 reqEx.setURL(_url);
182 reqEx.setMethod(HttpMethods.POST);
183 reqEx.addRequestHeader("Connection","close");
184
185 reqStream = new ByteArrayOutputStream();
186 request.storeToXML(reqStream,null);
187 ByteArrayBuffer reqBuff = new ByteArrayBuffer(reqStream.toByteArray());
188
189 reqEx.setRequestContent(reqBuff);
190 _client.send(reqEx);
191
192 reqEx.waitForDone();
193
194 if (reqEx.getResponseStatus() == HttpStatus.OK_200)
195 {
196 response = new Properties();
197 resStream = new ByteArrayInputStream(reqEx.getResponseContentBytes());
198 response.loadFromXML(resStream);
199 }
200 }
201 finally
202 {
203 try
204 {
205 if (reqStream != null)
206 reqStream.close();
207 }
208 catch (IOException ex)
209 {
210 LOG.ignore(ex);
211 }
212
213 try
214 {
215 if (resStream != null)
216 resStream.close();
217 }
218 catch (IOException ex)
219 {
220 LOG.ignore(ex);
221 }
222 }
223
224 return response;
225 }
226
227
228 private void parseResponse(Properties response)
229 {
230 if (response.get("onhold") != null)
231 throw new Error("Suspended");
232
233
234 if (response.get("session") != null)
235 {
236 _session = (String) response.remove("session");
237
238 AggregateEventTrigger trigger = (AggregateEventTrigger)getTrigger();
239
240 String queryString;
241 ObjectName[] queryResults;
242 for (Map.Entry<Object, Object> entry : response.entrySet())
243 {
244 String[] values = ((String) entry.getValue()).split("\\|");
245
246 queryString = values[0];
247 if (queryString.startsWith("com.javamonitor.openfire"))
248 continue;
249
250 if (queryString.startsWith("com.javamonitor"))
251 {
252 queryString = "org.eclipse.jetty.monitor.integration:type=javamonitortools,id=0";
253 }
254
255 queryResults = null;
256 try
257 {
258 queryResults = queryNames(queryString);
259 }
260 catch (IOException e)
261 {
262 LOG.debug(e);
263 }
264 catch (MalformedObjectNameException e)
265 {
266 LOG.debug(e);
267 }
268
269 if (queryResults != null)
270 {
271 int idx = 0;
272 for(ObjectName objName : queryResults)
273 {
274 String id = entry.getKey().toString()+(idx == 0 ? "" : ":"+idx);
275 String name = queryString.equals(objName.toString()) ? "" : objName.toString();
276 boolean repeat = Boolean.parseBoolean(values[2]);
277 trigger.add(new JavaMonitorTrigger(objName, values[1], id, name, repeat));
278 }
279 }
280 }
281 }
282 }
283
284
285
286
287
288
289 private int getClassID(final Object value)
290 {
291 if (value == null)
292 return 0;
293
294 if (value instanceof Byte ||
295 value instanceof Short ||
296 value instanceof Integer ||
297 value instanceof Long)
298 return 1;
299
300 if (value instanceof Float ||
301 value instanceof Double)
302 return 2;
303
304 if (value instanceof Boolean)
305 return 3;
306
307 return 4;
308 }
309
310
311
312
313
314
315 private String getServerIP()
316 throws Exception
317 {
318 Socket s = null;
319 try {
320 if (getProperty("http.proxyHost") != null)
321 {
322 s = new Socket(getProperty("http.proxyHost"),
323 parseInt(getProperty("http.proxyPort", "80")));
324 }
325 else
326 {
327 int port = 80;
328
329 URL url = new URL(_url);
330 if (url.getPort() != -1) {
331 port = url.getPort();
332 }
333 s = new Socket(url.getHost(), port);
334 }
335 return s.getLocalAddress().getHostAddress();
336 }
337 finally
338 {
339 try
340 {
341 if (s != null)
342 s.close();
343 }
344 catch (IOException ex)
345 {
346 LOG.ignore(ex);
347 }
348 }
349 }
350
351
352 public Integer getHttpPort()
353 {
354 Collection<ObjectName> connectors = null;
355 MBeanServerConnection service;
356 try
357 {
358 service = JMXMonitor.getServiceConnection();
359
360 connectors = service.queryNames(new ObjectName("org.eclipse.jetty.nio:type=selectchannelconnector,*"), null);
361 if (connectors != null && connectors.size() > 0)
362 {
363 Integer lowest = Integer.MAX_VALUE;
364 for (final ObjectName connector : connectors) {
365 lowest = (Integer)service.getAttribute(connector, "port");
366 }
367
368 if (lowest < Integer.MAX_VALUE)
369 return lowest;
370 }
371 }
372 catch (Exception ex)
373 {
374 LOG.debug(ex);
375 }
376
377 return 0;
378 }
379
380
381
382
383
384
385
386
387
388 private ObjectName[] queryNames(ObjectName param)
389 throws IOException, MalformedObjectNameException
390 {
391 ObjectName[] result = null;
392
393 MBeanServerConnection connection = JMXMonitor.getServiceConnection();
394 Set names = connection.queryNames(param, null);
395 if (names != null && names.size() > 0)
396 {
397 result = new ObjectName[names.size()];
398
399 int idx = 0;
400 for(Object name : names)
401 {
402 if (name instanceof ObjectName)
403 result[idx++] = (ObjectName)name;
404 else
405 result[idx++] = new ObjectName(name.toString());
406 }
407 }
408
409 return result;
410 }
411
412 private ObjectName[] queryNames(String param)
413 throws IOException, MalformedObjectNameException
414 {
415 return queryNames(new ObjectName(param));
416 }
417
418 }