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 */ 019 package org.apache.wiki.ui.admin; 020 021 import java.lang.management.ManagementFactory; 022 import java.util.ArrayList; 023 import java.util.Collection; 024 import java.util.Iterator; 025 import java.util.List; 026 027 import javax.management.DynamicMBean; 028 import javax.management.InstanceAlreadyExistsException; 029 import javax.management.InstanceNotFoundException; 030 import javax.management.MBeanRegistrationException; 031 import javax.management.MBeanServer; 032 import javax.management.MalformedObjectNameException; 033 import javax.management.NotCompliantMBeanException; 034 import javax.management.ObjectName; 035 036 import org.apache.log4j.Logger; 037 import org.apache.wiki.Release; 038 import org.apache.wiki.WikiEngine; 039 import org.apache.wiki.api.engine.AdminBeanManager; 040 import org.apache.wiki.api.engine.PluginManager; 041 import org.apache.wiki.event.WikiEngineEvent; 042 import org.apache.wiki.event.WikiEvent; 043 import org.apache.wiki.event.WikiEventListener; 044 import org.apache.wiki.modules.WikiModuleInfo; 045 import org.apache.wiki.ui.admin.beans.CoreBean; 046 import org.apache.wiki.ui.admin.beans.PluginBean; 047 import org.apache.wiki.ui.admin.beans.SearchManagerBean; 048 import 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 */ 057 public 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 c ) { 151 for( Iterator i = c.iterator(); i.hasNext(); ) { 152 String abname = ((WikiModuleInfo)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 } catch( NotCompliantMBeanException e ) { 181 log.error( e.getMessage(), e ); 182 } 183 registerBeans( m_engine.getEditorManager().modules() ); 184 PluginManager pm = m_engine.getPluginManager(); 185 registerBeans( pm.modules() ); 186 } 187 188 /* (non-Javadoc) 189 * @see org.apache.wiki.ui.admin.AdminBeanManager#getAllBeans() 190 */ 191 @Override 192 public List< AdminBean > getAllBeans() { 193 if( m_allBeans == null ) { 194 reload(); 195 } 196 197 return m_allBeans; 198 } 199 200 /* (non-Javadoc) 201 * @see org.apache.wiki.ui.admin.AdminBeanManager#findBean(java.lang.String) 202 */ 203 @Override 204 public AdminBean findBean( String id ) { 205 for( Iterator< AdminBean > i = m_allBeans.iterator(); i.hasNext(); ) { 206 AdminBean ab = i.next(); 207 208 if( ab.getId().equals(id) ) { 209 return ab; 210 } 211 } 212 213 return null; 214 } 215 216 /** 217 * Provides a JDK 1.5-compliant version of the MBeanServerFactory. This will simply bind to the 218 * platform MBeanServer. 219 */ 220 private static final class MBeanServerFactory15 { 221 private MBeanServerFactory15() 222 {} 223 224 public static MBeanServer getServer() { 225 return ManagementFactory.getPlatformMBeanServer(); 226 } 227 } 228 229 /** 230 * Returns the type identifier for a string type. 231 * 232 * @param type A type string. 233 * @return A type value. 234 */ 235 @Override 236 public int getTypeFromString( String type ) { 237 if( "core".equals( type ) ) { 238 return AdminBean.CORE; 239 } else if( "editors".equals( type ) ) { 240 return AdminBean.EDITOR; 241 } 242 243 return AdminBean.UNKNOWN; 244 } 245 246 /* (non-Javadoc) 247 * @see org.apache.wiki.ui.admin.AdminBeanManager#actionPerformed(org.apache.wiki.event.WikiEvent) 248 */ 249 @Override 250 public void actionPerformed(WikiEvent event) { 251 if( event instanceof WikiEngineEvent ) { 252 if( ( ( WikiEngineEvent )event ).getType() == WikiEngineEvent.SHUTDOWN ) { 253 for( Iterator< AdminBean > i = m_allBeans.iterator(); i.hasNext(); ) { 254 try { 255 AdminBean ab = i.next(); 256 ObjectName on = getObjectName( ab ); 257 if( m_mbeanServer.isRegistered( on ) ) { 258 m_mbeanServer.unregisterMBean(on); 259 log.info("Unregistered AdminBean "+ab.getTitle()); 260 } 261 } catch( MalformedObjectNameException e ) { 262 log.error("Malformed object name when unregistering",e); 263 } catch (InstanceNotFoundException e) { 264 log.error("Object was registered; yet claims that it's not there",e); 265 } catch (MBeanRegistrationException e) { 266 log.error("Registration exception while unregistering",e); 267 } 268 } 269 } 270 } 271 } 272 273 }