001: //========================================================================
002: //Copyright 2005 Mort Bay Consulting Pty. Ltd.
003: //------------------------------------------------------------------------
004: //Licensed under the Apache License, Version 2.0 (the "License");
005: //you may not use this file except in compliance with the License.
006: //You may obtain a copy of the License at
007: //http://www.apache.org/licenses/LICENSE-2.0
008: //Unless required by applicable law or agreed to in writing, software
009: //distributed under the License is distributed on an "AS IS" BASIS,
010: //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: //See the License for the specific language governing permissions and
012: //limitations under the License.
013: //========================================================================
014:
015: package org.mortbay.management;
016:
017: import java.net.URL;
018: import java.util.ArrayList;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Map;
023: import java.util.WeakHashMap;
024:
025: import javax.management.Attribute;
026: import javax.management.MBeanServer;
027: import javax.management.ObjectInstance;
028: import javax.management.ObjectName;
029: import javax.management.loading.PrivateMLet;
030:
031: import org.mortbay.component.Container;
032: import org.mortbay.component.Container.Relationship;
033: import org.mortbay.log.Log;
034: import org.mortbay.log.Logger;
035: import org.mortbay.util.MultiMap;
036: import org.mortbay.util.TypeUtil;
037:
038: public class MBeanContainer implements Container.Listener {
039: private final MBeanServer _server;
040: private volatile int _managementPort;
041: private final WeakHashMap _beans = new WeakHashMap();
042: private final HashMap _unique = new HashMap();
043: private String _domain = null;
044: private MultiMap _relations = new MultiMap();
045:
046: public synchronized ObjectName findMBean(Object object) {
047: ObjectName bean = (ObjectName) _beans.get(object);
048: return bean == null ? null : bean;
049: }
050:
051: public synchronized Object findBean(ObjectName oname) {
052: for (Iterator iter = _beans.entrySet().iterator(); iter
053: .hasNext();) {
054: Map.Entry entry = (Map.Entry) iter.next();
055: ObjectName bean = (ObjectName) entry.getValue();
056: if (bean.equals(oname))
057: return entry.getKey();
058: }
059: return null;
060: }
061:
062: public MBeanContainer(MBeanServer server) {
063: this ._server = server;
064: Logger log = Log.getLog();
065: if (log != null)
066: addBean(log);
067: }
068:
069: public MBeanServer getMBeanServer() {
070: return _server;
071: }
072:
073: public void setDomain(String domain) {
074: _domain = domain;
075: }
076:
077: public String getDomain() {
078: return _domain;
079: }
080:
081: public void setManagementPort(int port) {
082: this ._managementPort = port;
083: }
084:
085: public void start() {
086: if (_managementPort > 0) {
087: try {
088: Log.warn("HttpAdaptor for mx4j is not secure");
089:
090: PrivateMLet mlet = new PrivateMLet(new URL[0], Thread
091: .currentThread().getContextClassLoader(), false);
092: ObjectName mletName = ObjectName.getInstance("mx4j",
093: "name", "HttpAdaptorLoader");
094: _server.registerMBean(mlet, mletName);
095:
096: ObjectName adaptorName = ObjectName.getInstance("mx4j",
097: "name", "HttpAdaptor");
098: _server.createMBean(
099: "mx4j.tools.adaptor.http.HttpAdaptor",
100: adaptorName, mletName);
101: _server.setAttribute(adaptorName, new Attribute("Port",
102: new Integer(_managementPort)));
103: _server.setAttribute(adaptorName, new Attribute("Host",
104: "localhost"));
105:
106: ObjectName processorName = ObjectName.getInstance(
107: "mx4j", "name", "XSLTProcessor");
108: _server.createMBean(
109: "mx4j.tools.adaptor.http.XSLTProcessor",
110: processorName, mletName);
111: _server.setAttribute(adaptorName, new Attribute(
112: "ProcessorName", processorName));
113:
114: _server.invoke(adaptorName, "start", null, null);
115:
116: Runtime.getRuntime().addShutdownHook(
117: new ShutdownHook(mletName, adaptorName,
118: processorName));
119: } catch (Exception e) {
120: Log.warn(e);
121: }
122: }
123: }
124:
125: public synchronized void add(Relationship relationship) {
126: ObjectName parent = (ObjectName) _beans.get(relationship
127: .getParent());
128: if (parent == null) {
129: addBean(relationship.getParent());
130: parent = (ObjectName) _beans.get(relationship.getParent());
131: }
132:
133: ObjectName child = (ObjectName) _beans.get(relationship
134: .getChild());
135: if (child == null) {
136: addBean(relationship.getChild());
137: child = (ObjectName) _beans.get(relationship.getChild());
138: }
139:
140: if (parent != null && child != null)
141: _relations.add(parent, relationship);
142:
143: }
144:
145: public synchronized void remove(Relationship relationship) {
146: ObjectName parent = (ObjectName) _beans.get(relationship
147: .getParent());
148: ObjectName child = (ObjectName) _beans.get(relationship
149: .getChild());
150: if (parent != null && child != null)
151: _relations.removeValue(parent, relationship);
152: }
153:
154: public synchronized void removeBean(Object obj) {
155: ObjectName bean = (ObjectName) _beans.get(obj);
156:
157: if (bean != null) {
158: List r = _relations.getValues(bean);
159: if (r != null && r.size() > 0) {
160: Log.debug("Unregister {}", r);
161: Iterator iter = new ArrayList(r).iterator();
162: while (iter.hasNext()) {
163: Relationship rel = (Relationship) iter.next();
164: rel.getContainer().update(rel.getParent(),
165: rel.getChild(), null,
166: rel.getRelationship(), true);
167: }
168: }
169:
170: try {
171: _server.unregisterMBean(bean);
172: Log.debug("Unregistered {}", bean);
173: } catch (javax.management.InstanceNotFoundException e) {
174: Log.ignore(e);
175: } catch (Exception e) {
176: Log.warn(e);
177: }
178: }
179: }
180:
181: public synchronized void addBean(Object obj) {
182: try {
183: if (obj == null || _beans.containsKey(obj))
184: return;
185:
186: Object mbean = ObjectMBean.mbeanFor(obj);
187: if (mbean == null)
188: return;
189:
190: ObjectName oname = null;
191: if (mbean instanceof ObjectMBean) {
192: ((ObjectMBean) mbean).setMBeanContainer(this );
193: oname = ((ObjectMBean) mbean).getObjectName();
194: }
195:
196: //no override mbean object name, so make a generic one
197: if (oname == null) {
198: String name = obj.getClass().getName().toLowerCase();
199: int dot = name.lastIndexOf('.');
200: if (dot >= 0)
201: name = name.substring(dot + 1);
202: Integer count = (Integer) _unique.get(name);
203: count = TypeUtil.newInteger(count == null ? 0
204: : (1 + count.intValue()));
205: _unique.put(name, count);
206:
207: //if no explicit domain, create one
208: String domain = _domain;
209: if (domain == null)
210: domain = obj.getClass().getPackage().getName();
211:
212: oname = ObjectName.getInstance(domain + ":type=" + name
213: + ",id=" + count);
214: }
215:
216: ObjectInstance oinstance = _server.registerMBean(mbean,
217: oname);
218: Log.debug("Registered {}", oinstance.getObjectName());
219: _beans.put(obj, oinstance.getObjectName());
220:
221: } catch (Exception e) {
222: Log.warn("bean: " + obj, e);
223: }
224: }
225:
226: private class ShutdownHook extends Thread {
227: private final ObjectName mletName;
228: private final ObjectName adaptorName;
229: private final ObjectName processorName;
230:
231: public ShutdownHook(ObjectName mletName,
232: ObjectName adaptorName, ObjectName processorName) {
233: this .mletName = mletName;
234: this .adaptorName = adaptorName;
235: this .processorName = processorName;
236: }
237:
238: public void run() {
239: halt();
240: unregister(processorName);
241: unregister(adaptorName);
242: unregister(mletName);
243: }
244:
245: private void halt() {
246: try {
247: _server.invoke(adaptorName, "stop", null, null);
248: } catch (Exception e) {
249: Log.warn(e);
250: }
251: }
252:
253: private void unregister(ObjectName objectName) {
254: try {
255: _server.unregisterMBean(objectName);
256: Log.debug("Unregistered " + objectName);
257: } catch (Exception e) {
258: Log.warn(e);
259: }
260: }
261: }
262:
263: }
|