001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jk.common;
019:
020: import org.apache.jk.core.JkHandler;
021:
022: import javax.management.MBeanServer;
023: import javax.management.ObjectName;
024: import javax.management.Attribute;
025: import javax.management.MBeanServerFactory;
026: import java.io.IOException;
027:
028: /**
029: * Load the HTTP or RMI adapters for MX4J and JMXRI.
030: *
031: * Add "mx.enabled=true" in jk2.properties to enable it.
032: * You could also select http and/or jrmp protocol,
033: * with mx.httpPort, mx.httpHost, mxjrmpPort and mx.jrmpPort.
034: * <p />
035: * If you run into an error message like
036: * "SystemId Unknown; Line #12; Column #81; Cannot add attribute name after
037: * child nodes or before an element is produced. Attribute will be ignored."
038: * after setting mx.enabled to true, you probably need a newer version
039: * of Xalan. See the RELEASE-NOTES document section on XML Parsers for
040: * more information.
041: *
042: */
043: public class JkMX extends JkHandler {
044: MBeanServer mserver;
045: private boolean enabled = false;
046: private boolean log4jEnabled = true;
047: private int httpport = -1;
048: private String httphost = "localhost";
049: private String authmode = "none";
050: private String authuser = null;
051: private String authpassword = null;
052: private int jrmpport = -1;
053: private String jrmphost = "localhost";
054: private boolean useXSLTProcessor = true;
055:
056: public JkMX() {
057: }
058:
059: /* -------------------- Public methods -------------------- */
060:
061: /** Enable the MX4J adapters (new way)
062: */
063: public void setEnabled(boolean b) {
064: enabled = b;
065: }
066:
067: public boolean getEnabled() {
068: return enabled;
069: }
070:
071: /** Enable the Log4j MBean)
072: */
073: public void setLog4jEnabled(boolean b) {
074: log4jEnabled = b;
075: }
076:
077: public boolean getLog4jEnabled() {
078: return log4jEnabled;
079: }
080:
081: /** Enable the MX4J adapters (old way, compatible)
082: */
083: public void setPort(int i) {
084: enabled = (i != -1);
085: }
086:
087: public int getPort() {
088: return ((httpport != -1) ? httpport : jrmpport);
089: }
090:
091: /** Enable the MX4J HTTP internal adapter
092: */
093: public void setHttpPort(int i) {
094: httpport = i;
095: }
096:
097: public int getHttpPort() {
098: return httpport;
099: }
100:
101: public void setHttpHost(String host) {
102: this .httphost = host;
103: }
104:
105: public String getHttpHost() {
106: return httphost;
107: }
108:
109: public void setAuthMode(String mode) {
110: authmode = mode;
111: }
112:
113: public String getAuthMode() {
114: return authmode;
115: }
116:
117: public void setAuthUser(String user) {
118: authuser = user;
119: }
120:
121: public String getAuthUser() {
122: return authuser;
123: }
124:
125: public void setAuthPassword(String password) {
126: authpassword = password;
127: }
128:
129: public String getAuthPassword() {
130: return authpassword;
131: }
132:
133: /** Enable the MX4J JRMP internal adapter
134: */
135: public void setJrmpPort(int i) {
136: jrmpport = i;
137: }
138:
139: public int getJrmpPort() {
140: return jrmpport;
141: }
142:
143: public void setJrmpHost(String host) {
144: this .jrmphost = host;
145: }
146:
147: public String getJrmpHost() {
148: return jrmphost;
149: }
150:
151: public boolean getUseXSLTProcessor() {
152: return useXSLTProcessor;
153: }
154:
155: public void setUseXSLTProcessor(boolean uxsltp) {
156: useXSLTProcessor = uxsltp;
157: }
158:
159: /* ==================== Start/stop ==================== */
160: ObjectName httpServerName = null;
161: ObjectName jrmpServerName = null;
162:
163: /** Initialize the worker. After this call the worker will be
164: * ready to accept new requests.
165: */
166: public void loadAdapter() throws IOException {
167: boolean httpAdapterLoaded = false;
168: boolean jrmpAdapterLoaded = false;
169:
170: if ((httpport != -1)
171: && classExists("mx4j.adaptor.http.HttpAdaptor")) {
172: try {
173: httpServerName = registerObject(
174: "mx4j.adaptor.http.HttpAdaptor",
175: "Http:name=HttpAdaptor");
176:
177: if (httphost != null)
178: mserver.setAttribute(httpServerName, new Attribute(
179: "Host", httphost));
180: mserver.setAttribute(httpServerName, new Attribute(
181: "Port", new Integer(httpport)));
182:
183: if ("none".equals(authmode) || "basic".equals(authmode)
184: || "digest".equals(authmode))
185: mserver.setAttribute(httpServerName, new Attribute(
186: "AuthenticationMethod", authmode));
187:
188: if (authuser != null && authpassword != null)
189: mserver.invoke(httpServerName, "addAuthorization",
190: new Object[] { authuser, authpassword },
191: new String[] { "java.lang.String",
192: "java.lang.String" });
193:
194: if (useXSLTProcessor) {
195: ObjectName processorName = registerObject(
196: "mx4j.adaptor.http.XSLTProcessor",
197: "Http:name=XSLTProcessor");
198: mserver.setAttribute(httpServerName, new Attribute(
199: "ProcessorName", processorName));
200: }
201:
202: // starts the server
203: mserver.invoke(httpServerName, "start", null, null);
204:
205: log.info("Started MX4J console on host " + httphost
206: + " at port " + httpport);
207:
208: httpAdapterLoaded = true;
209:
210: } catch (Throwable t) {
211: httpServerName = null;
212: log.error("Can't load the MX4J http adapter ", t);
213: }
214: }
215:
216: if ((httpport != -1) && (!httpAdapterLoaded)
217: && classExists("mx4j.tools.adaptor.http.HttpAdaptor")) {
218: try {
219: httpServerName = registerObject(
220: "mx4j.tools.adaptor.http.HttpAdaptor",
221: "Http:name=HttpAdaptor");
222:
223: if (httphost != null)
224: mserver.setAttribute(httpServerName, new Attribute(
225: "Host", httphost));
226: mserver.setAttribute(httpServerName, new Attribute(
227: "Port", new Integer(httpport)));
228:
229: if ("none".equals(authmode) || "basic".equals(authmode)
230: || "digest".equals(authmode))
231: mserver.setAttribute(httpServerName, new Attribute(
232: "AuthenticationMethod", authmode));
233:
234: if (authuser != null && authpassword != null)
235: mserver.invoke(httpServerName, "addAuthorization",
236: new Object[] { authuser, authpassword },
237: new String[] { "java.lang.String",
238: "java.lang.String" });
239:
240: if (useXSLTProcessor) {
241: ObjectName processorName = registerObject(
242: "mx4j.tools.adaptor.http.XSLTProcessor",
243: "Http:name=XSLTProcessor");
244: mserver.setAttribute(httpServerName, new Attribute(
245: "ProcessorName", processorName));
246: }
247: // starts the server
248: mserver.invoke(httpServerName, "start", null, null);
249: if (log.isInfoEnabled())
250: log.info("Started MX4J console on host " + httphost
251: + " at port " + httpport);
252:
253: httpAdapterLoaded = true;
254:
255: } catch (Throwable t) {
256: httpServerName = null;
257: log.error("Can't load the MX4J http adapter ", t);
258: }
259: }
260:
261: if ((jrmpport != -1)
262: && classExists("mx4j.tools.naming.NamingService")) {
263: try {
264: jrmpServerName = registerObject(
265: "mx4j.tools.naming.NamingService",
266: "Naming:name=rmiregistry");
267: mserver.setAttribute(jrmpServerName, new Attribute(
268: "Port", new Integer(jrmpport)));
269: mserver.invoke(jrmpServerName, "start", null, null);
270: if (log.isInfoEnabled())
271: log.info("Creating " + jrmpServerName);
272:
273: // Create the JRMP adaptor
274: ObjectName adaptor = registerObject(
275: "mx4j.adaptor.rmi.jrmp.JRMPAdaptor",
276: "Adaptor:protocol=jrmp");
277:
278: mserver.setAttribute(adaptor, new Attribute("JNDIName",
279: "jrmp"));
280:
281: mserver
282: .invoke(
283: adaptor,
284: "putNamingProperty",
285: new Object[] {
286: javax.naming.Context.INITIAL_CONTEXT_FACTORY,
287: "com.sun.jndi.rmi.registry.RegistryContextFactory" },
288: new String[] { "java.lang.Object",
289: "java.lang.Object" });
290:
291: String jrpmurl = "rmi://" + jrmphost + ":"
292: + Integer.toString(jrmpport);
293:
294: mserver.invoke(adaptor, "putNamingProperty",
295: new Object[] {
296: javax.naming.Context.PROVIDER_URL,
297: jrpmurl },
298: new String[] { "java.lang.Object",
299: "java.lang.Object" });
300:
301: // Registers the JRMP adaptor in JNDI and starts it
302: mserver.invoke(adaptor, "start", null, null);
303: if (log.isInfoEnabled())
304: log.info("Creating " + adaptor + " on host "
305: + jrmphost + " at port " + jrmpport);
306:
307: jrmpAdapterLoaded = true;
308:
309: } catch (Exception ex) {
310: jrmpServerName = null;
311: log.error("MX4j RMI adapter not loaded: "
312: + ex.toString());
313: }
314: }
315:
316: if ((httpport != -1) && (!httpAdapterLoaded)
317: && classExists("com.sun.jdmk.comm.HtmlAdaptorServer")) {
318: try {
319: httpServerName = registerObject(
320: "com.sun.jdmk.comm.HtmlAdaptorServer",
321: "Adaptor:name=html,port=" + httpport);
322: if (log.isInfoEnabled())
323: log.info("Registering the JMX_RI html adapter "
324: + httpServerName + " at port " + httpport);
325:
326: mserver.setAttribute(httpServerName, new Attribute(
327: "Port", new Integer(httpport)));
328:
329: mserver.invoke(httpServerName, "start", null, null);
330:
331: httpAdapterLoaded = true;
332: } catch (Throwable t) {
333: httpServerName = null;
334: log.error("Can't load the JMX_RI http adapter "
335: + t.toString());
336: }
337: }
338:
339: if ((!httpAdapterLoaded) && (!jrmpAdapterLoaded))
340: log
341: .warn("No adaptors were loaded but mx.enabled was defined.");
342:
343: }
344:
345: public void destroy() {
346: try {
347: if (log.isInfoEnabled())
348: log.info("Stoping JMX ");
349:
350: if (httpServerName != null) {
351: mserver.invoke(httpServerName, "stop", null, null);
352: }
353: if (jrmpServerName != null) {
354: mserver.invoke(jrmpServerName, "stop", null, null);
355: }
356: } catch (Throwable t) {
357: log.error("Destroy error" + t);
358: }
359: }
360:
361: public void init() throws IOException {
362: try {
363: mserver = getMBeanServer();
364:
365: if (enabled) {
366: loadAdapter();
367: }
368: if (log4jEnabled) {
369: try {
370: registerObject(
371: "org.apache.log4j.jmx.HierarchyDynamicMBean",
372: "log4j:hierarchy=default");
373: if (log.isInfoEnabled())
374: log
375: .info("Registering the JMX hierarchy for Log4J ");
376: } catch (Throwable t) {
377: if (log.isInfoEnabled())
378: log.info("Can't enable log4j mx: ", t);
379: }
380: }
381: } catch (Throwable t) {
382: log.error("Init error", t);
383: }
384: }
385:
386: public void addHandlerCallback(JkHandler w) {
387: }
388:
389: MBeanServer getMBeanServer() {
390: MBeanServer server;
391: if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
392: server = (MBeanServer) MBeanServerFactory.findMBeanServer(
393: null).get(0);
394: } else {
395: server = MBeanServerFactory.createMBeanServer();
396: }
397: return (server);
398: }
399:
400: private static boolean classExists(String className) {
401: try {
402: Thread.currentThread().getContextClassLoader().loadClass(
403: className);
404: return true;
405: } catch (Throwable e) {
406: if (log.isInfoEnabled())
407: log
408: .info("className [" + className
409: + "] does not exist");
410: return false;
411: }
412: }
413:
414: private ObjectName registerObject(String className, String oName)
415: throws Exception {
416: Class c = Class.forName(className);
417: Object o = c.newInstance();
418: ObjectName objN = new ObjectName(oName);
419: mserver.registerMBean(o, objN);
420: return objN;
421: }
422:
423: private static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
424: .getLog(JkMX.class);
425:
426: }
|