001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.ui.admin; 020 021import java.lang.management.ManagementFactory; 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.Iterator; 025import java.util.List; 026 027import javax.management.DynamicMBean; 028import javax.management.InstanceAlreadyExistsException; 029import javax.management.InstanceNotFoundException; 030import javax.management.MBeanRegistrationException; 031import javax.management.MBeanServer; 032import javax.management.MalformedObjectNameException; 033import javax.management.NotCompliantMBeanException; 034import javax.management.ObjectName; 035 036import org.apache.log4j.Logger; 037import org.apache.wiki.Release; 038import org.apache.wiki.WikiEngine; 039import org.apache.wiki.api.engine.AdminBeanManager; 040import org.apache.wiki.event.WikiEngineEvent; 041import org.apache.wiki.event.WikiEvent; 042import org.apache.wiki.event.WikiEventListener; 043import org.apache.wiki.modules.WikiModuleInfo; 044import org.apache.wiki.ui.admin.beans.CoreBean; 045import org.apache.wiki.ui.admin.beans.FilterBean; 046import org.apache.wiki.ui.admin.beans.PluginBean; 047import org.apache.wiki.ui.admin.beans.SearchManagerBean; 048import org.apache.wiki.ui.admin.beans.UserBean; 049 050 051/** 052 * Provides a manager class for all AdminBeans within JSPWiki. This class also manages registration for any 053 * AdminBean which is also a JMX bean. 054 * 055 * @since 2.5.52 056 */ 057public class DefaultAdminBeanManager implements WikiEventListener, AdminBeanManager { 058 059 private WikiEngine m_engine; 060 private ArrayList< AdminBean > m_allBeans; 061 062 private MBeanServer m_mbeanServer = null; 063 064 private static Logger log = Logger.getLogger(DefaultAdminBeanManager.class); 065 066 public DefaultAdminBeanManager( WikiEngine engine ) { 067 log.info("Using JDK 1.5 Platform MBeanServer"); 068 m_mbeanServer = MBeanServerFactory15.getServer(); 069 070 m_engine = engine; 071 072 if( m_mbeanServer != null ) { 073 log.info( m_mbeanServer.getClass().getName() ); 074 log.info( m_mbeanServer.getDefaultDomain() ); 075 } 076 077 m_engine.addWikiEventListener( this ); 078 initialize(); 079 } 080 081 /* (non-Javadoc) 082 * @see org.apache.wiki.ui.admin.AdminBeanManager#initialize() 083 */ 084 @Override 085 public void initialize() { 086 reload(); 087 } 088 089 private String getJMXTitleString( int title ) { 090 switch( title ) { 091 case AdminBean.CORE: 092 return "Core"; 093 094 case AdminBean.EDITOR: 095 return "Editors"; 096 097 case AdminBean.UNKNOWN: 098 default: 099 return "Unknown"; 100 } 101 } 102 103 104 /** 105 * Register an AdminBean. If the AdminBean is also a JMX MBean, it also gets registered to the MBeanServer 106 * we've found. 107 * 108 * @param ab AdminBean to register. 109 */ 110 private void registerAdminBean( AdminBean ab ) { 111 try { 112 if( ab instanceof DynamicMBean && m_mbeanServer != null ) { 113 ObjectName name = getObjectName( ab ); 114 115 if( !m_mbeanServer.isRegistered( name ) ) { 116 m_mbeanServer.registerMBean( ab, name ); 117 } 118 } 119 120 m_allBeans.add( ab ); 121 122 log.info("Registered new admin bean "+ab.getTitle()); 123 } catch( InstanceAlreadyExistsException e ) { 124 log.error("Admin bean already registered to JMX",e); 125 } catch( MBeanRegistrationException e ) { 126 log.error("Admin bean cannot be registered to JMX",e); 127 } catch( NotCompliantMBeanException e ) { 128 log.error("Your admin bean is not very good",e); 129 } catch( MalformedObjectNameException e ) { 130 log.error("Your admin bean name is not very good",e); 131 } catch( NullPointerException e ) { 132 log.error("Evil NPE occurred",e); 133 } 134 } 135 136 private ObjectName getObjectName(AdminBean ab) throws MalformedObjectNameException { 137 String component = getJMXTitleString( ab.getType() ); 138 String title = ab.getTitle(); 139 140 ObjectName name = new ObjectName( Release.APPNAME + ":component="+component+",name="+title ); 141 return name; 142 } 143 144 /** 145 * Registers all the beans from a collection of WikiModuleInfos. If some of the beans 146 * fail, logs the message and keeps going to the next bean. 147 * 148 * @param c Collection of WikiModuleInfo instances 149 */ 150 private void registerBeans( Collection< WikiModuleInfo > c ) { 151 for( Iterator< WikiModuleInfo > i = c.iterator(); i.hasNext(); ) { 152 String abname = i.next().getAdminBeanClass(); 153 154 try { 155 if( abname != null && abname.length() > 0 ) { 156 Class< ? > abclass = Class.forName( abname ); 157 AdminBean ab = ( AdminBean ) abclass.newInstance(); 158 registerAdminBean( ab ); 159 } 160 } catch (ClassNotFoundException e) { 161 log.error( e.getMessage(), e ); 162 } catch (InstantiationException e) { 163 log.error( e.getMessage(), e ); 164 } catch (IllegalAccessException e) { 165 log.error( e.getMessage(), e ); 166 } 167 } 168 169 } 170 171 // FIXME: Should unload the beans first. 172 private void reload() { 173 m_allBeans = new ArrayList<AdminBean>(); 174 175 try { 176 registerAdminBean( new CoreBean( m_engine ) ); 177 registerAdminBean( new UserBean( m_engine ) ); 178 registerAdminBean( new SearchManagerBean( m_engine ) ); 179 registerAdminBean( new PluginBean( m_engine ) ); 180 registerAdminBean( new FilterBean( m_engine ) ); 181 } catch( NotCompliantMBeanException e ) { 182 log.error( e.getMessage(), e ); 183 } 184 registerBeans( m_engine.getEditorManager().modules() ); 185 registerBeans( m_engine.getPluginManager().modules() ); 186 registerBeans( m_engine.getFilterManager().modules() ); 187 } 188 189 /* (non-Javadoc) 190 * @see org.apache.wiki.ui.admin.AdminBeanManager#getAllBeans() 191 */ 192 @Override 193 public List< AdminBean > getAllBeans() { 194 if( m_allBeans == null ) { 195 reload(); 196 } 197 198 return m_allBeans; 199 } 200 201 /* (non-Javadoc) 202 * @see org.apache.wiki.ui.admin.AdminBeanManager#findBean(java.lang.String) 203 */ 204 @Override 205 public AdminBean findBean( String id ) { 206 for( Iterator< AdminBean > i = m_allBeans.iterator(); i.hasNext(); ) { 207 AdminBean ab = i.next(); 208 209 if( ab.getId().equals(id) ) { 210 return ab; 211 } 212 } 213 214 return null; 215 } 216 217 /** 218 * Provides a JDK 1.5-compliant version of the MBeanServerFactory. This will simply bind to the 219 * platform MBeanServer. 220 */ 221 private static final class MBeanServerFactory15 { 222 private MBeanServerFactory15() 223 {} 224 225 public static MBeanServer getServer() { 226 return ManagementFactory.getPlatformMBeanServer(); 227 } 228 } 229 230 /** 231 * Returns the type identifier for a string type. 232 * 233 * @param type A type string. 234 * @return A type value. 235 */ 236 @Override 237 public int getTypeFromString( String type ) { 238 if( "core".equals( type ) ) { 239 return AdminBean.CORE; 240 } else if( "editors".equals( type ) ) { 241 return AdminBean.EDITOR; 242 } 243 244 return AdminBean.UNKNOWN; 245 } 246 247 /* (non-Javadoc) 248 * @see org.apache.wiki.ui.admin.AdminBeanManager#actionPerformed(org.apache.wiki.event.WikiEvent) 249 */ 250 @Override 251 public void actionPerformed(WikiEvent event) { 252 if( event instanceof WikiEngineEvent ) { 253 if( ( ( WikiEngineEvent )event ).getType() == WikiEngineEvent.SHUTDOWN ) { 254 for( Iterator< AdminBean > i = m_allBeans.iterator(); i.hasNext(); ) { 255 try { 256 AdminBean ab = i.next(); 257 ObjectName on = getObjectName( ab ); 258 if( m_mbeanServer.isRegistered( on ) ) { 259 m_mbeanServer.unregisterMBean(on); 260 log.info("Unregistered AdminBean "+ab.getTitle()); 261 } 262 } catch( MalformedObjectNameException e ) { 263 log.error("Malformed object name when unregistering",e); 264 } catch (InstanceNotFoundException e) { 265 log.error("Object was registered; yet claims that it's not there",e); 266 } catch (MBeanRegistrationException e) { 267 log.error("Registration exception while unregistering",e); 268 } 269 } 270 } 271 } 272 } 273 274}