001: /*
002: * JOSSO: Java Open Single Sign-On
003: *
004: * Copyright 2004-2008, Atricore, Inc.
005: *
006: * This is free software; you can redistribute it and/or modify it
007: * under the terms of the GNU Lesser General Public License as
008: * published by the Free Software Foundation; either version 2.1 of
009: * the License, or (at your option) any later version.
010: *
011: * This software is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this software; if not, write to the Free
018: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
020: */
021: package org.josso;
022:
023: import org.apache.commons.configuration.Configuration;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.apache.commons.modeler.Registry;
027: import org.josso.agent.SSOAgent;
028: import org.josso.agent.SSOAgentConfigurationEventHandler;
029: import org.josso.agent.SSOAgentInfo;
030: import org.josso.auth.Authenticator;
031: import org.josso.auth.CredentialStore;
032: import org.josso.auth.scheme.AuthenticationScheme;
033: import org.josso.gateway.GatewayServiceLocator;
034: import org.josso.gateway.SSOGatewayInfo;
035: import org.josso.gateway.audit.SSOAuditManager;
036: import org.josso.gateway.audit.service.handler.SSOAuditTrailHandler;
037: import org.josso.gateway.event.SSOEventListener;
038: import org.josso.gateway.event.SSOEventManager;
039: import org.josso.gateway.identity.service.SSOIdentityManager;
040: import org.josso.gateway.identity.service.store.IdentityStore;
041: import org.josso.gateway.session.service.SSOSessionManager;
042: import org.josso.gateway.session.service.SessionIdGenerator;
043: import org.josso.gateway.session.service.store.SessionStore;
044: import org.josso.util.config.SSOConfigurationEventHandler;
045:
046: import javax.management.*;
047: import java.lang.reflect.Method;
048: import java.util.ArrayList;
049: import java.util.List;
050:
051: /**
052: * This ComponentKeeper will register a Model MBean for using JOSSO components as managed resources.
053: * It can also keep JOSSO configuration files synchronized with MBeans attribute changes.
054: *
055: * @author <a href="mailto:sgonzalez@josso.org">Sebastian Gonzalez Oyuela</a>
056: *
057: * @version $Id: MBeanComponentKeeper.java 508 2008-02-18 13:32:29Z sgonzalez $
058: */
059: public class MBeanComponentKeeper extends ComponentKeeperImpl implements
060: NotificationListener {
061:
062: private static final Log logger = LogFactory
063: .getLog(MBeanComponentKeeper.class);
064:
065: /**
066: * Base JOSSO JMX domain.
067: */
068: public static final String JOSSO_DOMAIN = "josso";
069:
070: /**
071: * Common Modelere MBean registry
072: */
073: private Registry _registry;
074:
075: private List _eventListeners;
076:
077: public MBeanComponentKeeper() {
078: super ();
079: _registry = Registry.getRegistry(null, null);
080: _eventListeners = new ArrayList();
081: }
082:
083: // ---------------------------------------------------------------------------------
084:
085: /**
086: * JMX NotificationListener implementation.
087: */
088: public void handleNotification(Notification notification, Object o) {
089:
090: if (logger.isDebugEnabled())
091: logger.debug("Received notification : "
092: + notification.getType());
093:
094: try {
095: String eventType = notification.getType();
096:
097: // Submit this to all the chain of listeners.
098: for (int i = 0; i < _eventListeners.size(); i++) {
099: SSOConfigurationEventListener listener = (SSOConfigurationEventListener) _eventListeners
100: .get(i);
101: if (listener.isEventEnabled(eventType, notification))
102: listener.handleEvent(eventType, notification);
103: }
104:
105: } catch (Exception e) {
106: logger.error("Can't handle notification " + notification
107: + ": \n" + e.getMessage(), e);
108: }
109:
110: }
111:
112: // ---------------------------------------------------------------------------------
113:
114: public SecurityDomain fetchSecurityDomain() throws Exception {
115: SecurityDomain domain = super .fetchSecurityDomain();
116:
117: SSOGatewayInfo info = new SSOGatewayInfo(domain);
118: ObjectName oname = buildObjectName("type=SSOGatewayInfo");
119: registerResource(oname, info);
120:
121: return domain;
122: }
123:
124: /**
125: * Registers a Model MBean using the fetched comonent as managed resource.
126: * Delegates component construction to parent class.
127: */
128: protected SSOSessionManager fetchSessionManager(Configuration config)
129: throws Exception {
130: SSOSessionManager sm = super .fetchSessionManager(config);
131: ObjectName oname = buildObjectName(sm, "SSOSessionManager");
132: registerResource(oname, sm);
133: this
134: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
135: super .getSSOGatewayConfigurationContext(),
136: "/domain/sso-session-manager",
137: "/domain/sso-session-manager/class", oname,
138: new String[0]));
139:
140: return sm;
141:
142: }
143:
144: /**
145: * Registers a Model MBean using the fetched comonent as managed resource.
146: * Delegates component construction to parent class.
147: */
148: protected SessionIdGenerator fetchSessionIdGenerator(
149: Configuration config) throws Exception {
150: SessionIdGenerator sig = super .fetchSessionIdGenerator(config);
151: ObjectName oname = buildObjectName(sig, "SessionIdGenerator");
152: registerResource(oname, sig);
153: this
154: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
155: getSSOGatewayConfigurationContext(),
156: "/domain/sso-session-manager/sso-session-id-generator",
157: "/domain/sso-session-manager/sso-session-id-generator/class",
158: oname, new String[0]));
159:
160: return sig;
161: }
162:
163: /**
164: * Registers a Model MBean using the fetched comonent as managed resource.
165: * Delegates component construction to parent class.
166: */
167: protected SessionStore fetchSessionStore(Configuration config)
168: throws Exception {
169: SessionStore ss = super .fetchSessionStore(config);
170: ObjectName oname = buildObjectName(ss, "SessionStore");
171: registerResource(oname, ss);
172:
173: this
174: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
175: getSSOGatewayConfigurationContext(),
176: "/domain/sso-session-manager/sso-session-store",
177: "/domain/sso-session-manager/sso-session-store/class",
178: oname, new String[0]));
179:
180: return ss;
181: }
182:
183: /**
184: * Registers a Model MBean using the fetched comonent as managed resource.
185: * Delegates component construction to parent class.
186: */
187: protected Authenticator fetchAuthenticator(Configuration config)
188: throws Exception {
189: Authenticator a = super .fetchAuthenticator(config);
190: ObjectName oname = buildObjectName(a, "Authenticator");
191: registerResource(oname, a);
192: this
193: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
194: getSSOGatewayConfigurationContext(),
195: "/domain/authenticator",
196: "/domain/authenticator/class", oname,
197: new String[0]));
198: return a;
199: }
200:
201: /**
202: * Registers a Model MBean using the fetched comonent as managed resource.
203: * Delegates component construction to parent class.
204: */
205: protected AuthenticationScheme fetchAuthenticationScheme(
206: Configuration config) throws Exception {
207:
208: AuthenticationScheme a = super
209: .fetchAuthenticationScheme(config);
210:
211: ObjectName oname = buildObjectName(a, "AuthenticationScheme");
212: registerResource(oname, a);
213: this
214: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
215: getSSOGatewayConfigurationContext(),
216: "/domain/authenticator/authentication-schemes/authentication-scheme[name='"
217: + a.getName() + "']",
218: "/domain/authenticator/authentication-schemes/authentication-scheme[name='"
219: + a.getName() + "']/class", oname,
220: new String[0]));
221: return a;
222: }
223:
224: /**
225: * Registers a Model MBean using the fetched comonent as managed resource.
226: * Delegates component construction to parent class.
227: */
228: protected CredentialStore fetchCredentialStore(Configuration config)
229: throws Exception {
230: CredentialStore cs = super .fetchCredentialStore(config);
231: AuthenticationScheme as = (AuthenticationScheme) _cfg.peek();
232: ObjectName oname = buildObjectName("type=CredentialStore,auth="
233: + as.getName());
234: registerResource(oname, cs);
235: this
236: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
237: getSSOGatewayConfigurationContext(),
238: "/domain/authenticator/authentication-schemes/authentication-scheme[name='"
239: + as.getName() + "']/credential-store",
240: "/domain/authenticator/authentication-schemes/authentication-scheme[name='"
241: + as.getName()
242: + "']/credential-store/class", oname,
243: new String[0]));
244: return cs;
245: }
246:
247: /**
248: * Registers a Model MBean using the fetched comonent as managed resource.
249: * Delegates component construction to parent class.
250: */
251: protected SSOIdentityManager fetchIdentityManager(
252: Configuration config) throws Exception {
253: SSOIdentityManager im = super .fetchIdentityManager(config);
254: ObjectName oname = buildObjectName(im, "SSOIdentityManager");
255: registerResource(oname, im);
256: this
257: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
258: getSSOGatewayConfigurationContext(),
259: "/domain/sso-identity-manager",
260: "/domain/sso-identity-manager/class", oname,
261: new String[0]));
262: return im;
263: }
264:
265: /**
266: * Registers a Model MBean using the fetched comonent as managed resource.
267: * Delegates component construction to parent class.
268: */
269: protected IdentityStore fetchIdentityStore(Configuration config)
270: throws Exception {
271: IdentityStore is = super .fetchIdentityStore(config);
272: ObjectName oname = buildObjectName(is, "IdentityStore");
273: registerResource(oname, is);
274: this
275: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
276: getSSOGatewayConfigurationContext(),
277: "/domain/sso-identity-manager/sso-identity-store",
278: "/domain/sso-identity-manager/sso-identity-store/class",
279: oname, new String[0]));
280: return is;
281: }
282:
283: /**
284: * Registers a Model MBean using the fetched comonent as managed resource.
285: * Delegates component construction to parent class.
286: */
287: protected SSOAuditManager fetchAuditManager(Configuration config)
288: throws Exception {
289: SSOAuditManager am = super .fetchAuditManager(config);
290: ObjectName oname = buildObjectName(am, "SSOAuditManager");
291: registerResource(oname, am);
292: this
293: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
294: getSSOGatewayConfigurationContext(),
295: "/domain/sso-audit-manager",
296: "/domain/sso-audit-manager/class", oname,
297: new String[0]));
298: return am;
299: }
300:
301: protected List fetchAuditHandlers(Configuration config)
302: throws Exception {
303: List handlers = super .fetchAuditHandlers(config);
304:
305: for (int i = 0; i < handlers.size(); i++) {
306: SSOAuditTrailHandler handler = (SSOAuditTrailHandler) handlers
307: .get(i);
308:
309: ObjectName oname = buildObjectName(handler,
310: "SSOAuditTrailHandler");
311: registerResource(oname, handler);
312: this
313: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
314: getSSOGatewayConfigurationContext(),
315: "/domain/sso-audit-manager/handlers/handler[name='"
316: + handler.getName() + "']",
317: "/domain/sso-audit-manager/handlers/handler[name='"
318: + handler.getName() + "']/class",
319: oname, new String[0]));
320:
321: }
322:
323: return handlers;
324: }
325:
326: /**
327: * Registers a Model MBean using the fetched comonent as managed resource.
328: * Delegates component construction to parent class.
329: */
330: protected SSOEventManager fetchEventManager(Configuration config)
331: throws Exception {
332: SSOEventManager em = super .fetchEventManager(config);
333: ObjectName oname = buildObjectName(em, "SSOEventManager");
334: registerResource(oname, em);
335: this
336: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
337: getSSOGatewayConfigurationContext(),
338: "/domain/sso-event-manager",
339: "/domain/sso-event-manager/class", oname,
340: new String[0]));
341: return em;
342: }
343:
344: /**
345: * Registers a Model MBean using the fetched comonent as managed resource.
346: * Delegates component construction to parent class.
347: */
348: protected List fetchEventListeners(Configuration config)
349: throws Exception {
350: List listeners = super .fetchEventListeners(config);
351:
352: for (int i = 0; i < listeners.size(); i++) {
353: SSOEventListener listener = (SSOEventListener) listeners
354: .get(i);
355:
356: ObjectName oname = buildObjectName(listener,
357: "SSOEventListener");
358: registerResource(oname, listener);
359: this
360: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
361: getSSOGatewayConfigurationContext(),
362: "/domain/sso-event-manager/listeners/listener[class='"
363: + listener.getClass().getName()
364: + "']",
365: "/domain/sso-event-manager/listeners/listener[class='"
366: + listener.getClass().getName()
367: + "']/class", oname, new String[0]));
368:
369: }
370:
371: return listeners;
372: }
373:
374: /**
375: * Registers a Model MBean using the fetched comonent as managed resource.
376: * Delegates component construction to parent class.
377: */
378: public SSOAgent fetchSSOAgent() throws Exception {
379: SSOAgent a = super .fetchSSOAgent();
380: ObjectName oname = buildObjectName(a, "SSOAgent");
381: registerResource(oname, a);
382:
383: this
384: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
385: getSSOAgentConfigurationContext(), "/agent",
386: "/agent/class", oname, new String[] { "debug" }));
387:
388: this
389: .registerSSOConfigurationEventListener(new SSOAgentConfigurationEventHandler(
390: getSSOAgentConfigurationContext(),
391: "/agent/partner-apps",
392: "/agent/partner-apps/partner-app", oname,
393: new String[] { "debug" }));
394:
395: SSOAgentInfo info = new SSOAgentInfo();
396: oname = buildObjectName("type=SSOAgentInfo");
397: registerResource(oname, info);
398:
399: return a;
400: }
401:
402: /**
403: * Registers a Model MBean using the fetched comonent as managed resource.
404: * Delegates component construction to parent class.
405: */
406: public GatewayServiceLocator fetchGatewayServiceLocator(
407: Configuration config) throws Exception {
408: GatewayServiceLocator gsl = super
409: .fetchGatewayServiceLocator(config);
410: ObjectName oname = buildObjectName(gsl, "GatewayServiceLocator");
411: registerResource(oname, gsl);
412: this
413: .registerSSOConfigurationEventListener(new SSOConfigurationEventHandler(
414: getSSOAgentConfigurationContext(),
415: "/agent/service-locator",
416: "/agent/service-locator/class", oname,
417: new String[0]));
418: return gsl;
419: }
420:
421: // -----------------------------------------------------------------------------------------------
422:
423: /**
424: * Adss a new listener to the chain.
425: */
426: protected void registerSSOConfigurationEventListener(
427: SSOConfigurationEventListener listener) {
428: if (!_eventListeners.contains(listener)) {
429: _eventListeners.add(listener);
430: }
431: }
432:
433: // -----------------------------------------------------------------------------------------------
434:
435: /**
436: * Util method to register a resource as a MBean.
437: * The M
438: *
439: * @param resource the resource instance.
440: */
441: public void registerResource(Object resource) {
442: registerResource(buildObjectName(resource), resource);
443: }
444:
445: /**
446: * Util to register any JOSSO resource as an MBean. This implementation is based on commons-modeler.
447: * Subclasses may use a different JMX implementation.
448: */
449: public void registerResource(ObjectName oname, Object resource) {
450: try {
451: logger.info("Registering MBean : " + oname);
452: _registry.registerComponent(resource, oname, null);
453:
454: MBeanServer server = getMBeanServer();
455: server.addNotificationListener(oname, this , null, null);
456:
457: } catch (Exception e) {
458: logger.error("Can't register resource as MBean : \n"
459: + e.getMessage(), e);
460: }
461: }
462:
463: public ObjectName buildObjectName(Object o) {
464: return buildObjectName(o, null);
465: }
466:
467: /**
468: * Builds a JMX Object name based on an object instance.
469: */
470: public ObjectName buildObjectName(Object o, String type) {
471:
472: // Get this MBean type
473: if (type == null) {
474: String className = o.getClass().getName();
475: int period = className.lastIndexOf('.');
476: if (period >= 0)
477: className = className.substring(period + 1);
478: type = className;
479: }
480:
481: // Check fi this MBean has a "name" ...
482: String name = null;
483: try {
484: Method m = o.getClass().getMethod("getName", new Class[0]);
485: name = (String) m.invoke(o, new Object[0]);
486: } catch (Exception e) {
487: // Object does not have a name attribute, go on ...
488: }
489:
490: String oname = "type=" + type
491: + (name != null ? ",name=" + name : "");
492: // Build the final ObjectName
493: return buildObjectName(oname);
494: }
495:
496: /**
497: * This method builds an ObjectName instance, using the JOSSO JMX domain.
498: */
499: public ObjectName buildObjectName(String oname) {
500: // Build the final ObjectName
501: try {
502: return new ObjectName(JOSSO_DOMAIN + ":" + oname);
503: } catch (MalformedObjectNameException e) {
504: logger.error("Can't build object name for [" + oname
505: + "]\n:" + e.getMessage(), e);
506: return null;
507: }
508:
509: }
510:
511: /**
512: * Finds the propper MBeanServer instance.
513: */
514: protected MBeanServer getMBeanServer() {
515: return _registry.getMBeanServer();
516: }
517:
518: }
|