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 org.apache.log4j.Logger; 022import org.apache.wiki.api.Release; 023import org.apache.wiki.api.core.Engine; 024import org.apache.wiki.event.WikiEngineEvent; 025import org.apache.wiki.event.WikiEvent; 026import org.apache.wiki.event.WikiEventListener; 027import org.apache.wiki.modules.ModuleManager; 028import org.apache.wiki.modules.WikiModuleInfo; 029import org.apache.wiki.ui.admin.beans.CoreBean; 030import org.apache.wiki.ui.admin.beans.FilterBean; 031import org.apache.wiki.ui.admin.beans.PluginBean; 032import org.apache.wiki.ui.admin.beans.SearchManagerBean; 033import org.apache.wiki.ui.admin.beans.UserBean; 034 035import javax.management.DynamicMBean; 036import javax.management.InstanceAlreadyExistsException; 037import javax.management.InstanceNotFoundException; 038import javax.management.MBeanRegistrationException; 039import javax.management.MBeanServer; 040import javax.management.MalformedObjectNameException; 041import javax.management.NotCompliantMBeanException; 042import javax.management.ObjectName; 043import java.lang.management.ManagementFactory; 044import java.util.ArrayList; 045import java.util.Collection; 046import java.util.List; 047 048 049/** 050 * Provides a manager class for all AdminBeans within JSPWiki. This class also manages registration for any 051 * AdminBean which is also a JMX bean. 052 * 053 * @since 2.5.52 054 */ 055public class DefaultAdminBeanManager implements WikiEventListener, AdminBeanManager { 056 057 private Engine m_engine; 058 private ArrayList< AdminBean > m_allBeans; 059 private MBeanServer m_mbeanServer; 060 061 private static final Logger log = Logger.getLogger( DefaultAdminBeanManager.class ); 062 063 public DefaultAdminBeanManager( final Engine engine ) { 064 log.info("Using JDK 1.5 Platform MBeanServer"); 065 m_mbeanServer = MBeanServerFactory15.getServer(); 066 067 m_engine = engine; 068 069 if( m_mbeanServer != null ) { 070 log.info( m_mbeanServer.getClass().getName() ); 071 log.info( m_mbeanServer.getDefaultDomain() ); 072 } 073 074 m_engine.addWikiEventListener( this ); 075 initialize(); 076 } 077 078 /** {@inheritDoc} */ 079 @Override 080 public void initialize() { 081 reload(); 082 } 083 084 private String getJMXTitleString( final int title ) { 085 switch( title ) { 086 case AdminBean.CORE: 087 return "Core"; 088 089 case AdminBean.EDITOR: 090 return "Editors"; 091 092 case AdminBean.UNKNOWN: 093 default: 094 return "Unknown"; 095 } 096 } 097 098 099 /** 100 * Register an AdminBean. If the AdminBean is also a JMX MBean, it also gets registered to the MBeanServer we've found. 101 * 102 * @param ab AdminBean to register. 103 */ 104 private void registerAdminBean( final AdminBean ab ) { 105 try { 106 if( ab instanceof DynamicMBean && m_mbeanServer != null ) { 107 final ObjectName name = getObjectName( ab ); 108 if( !m_mbeanServer.isRegistered( name ) ) { 109 m_mbeanServer.registerMBean( ab, name ); 110 } 111 } 112 113 m_allBeans.add( ab ); 114 115 log.info( "Registered new admin bean " + ab.getTitle() ); 116 } catch( final InstanceAlreadyExistsException e ) { 117 log.error( "Admin bean already registered to JMX", e ); 118 } catch( final MBeanRegistrationException e ) { 119 log.error( "Admin bean cannot be registered to JMX", e ); 120 } catch( final NotCompliantMBeanException e ) { 121 log.error( "Your admin bean is not very good", e ); 122 } catch( final MalformedObjectNameException e ) { 123 log.error( "Your admin bean name is not very good", e ); 124 } catch( final NullPointerException e ) { 125 log.error( "Evil NPE occurred", e ); 126 } 127 } 128 129 private ObjectName getObjectName( final AdminBean ab ) throws MalformedObjectNameException { 130 final String component = getJMXTitleString( ab.getType() ); 131 final String title = ab.getTitle(); 132 return new ObjectName( Release.APPNAME + ":component=" + component + ",name=" + title ); 133 } 134 135 /** 136 * Registers all the beans from a collection of WikiModuleInfos. If some of the beans fail, logs the message and keeps going to the 137 * next bean. 138 * 139 * @param c Collection of WikiModuleInfo instances 140 */ 141 private void registerBeans( final Collection< WikiModuleInfo > c ) { 142 for( final WikiModuleInfo wikiModuleInfo : c ) { 143 final String abname = wikiModuleInfo.getAdminBeanClass(); 144 try { 145 if( abname != null && abname.length() > 0 ) { 146 final Class< ? > abclass = Class.forName( abname ); 147 final AdminBean ab = ( AdminBean )abclass.newInstance(); 148 registerAdminBean( ab ); 149 } 150 } catch( final ClassNotFoundException | InstantiationException | IllegalAccessException e ) { 151 log.error( e.getMessage(), e ); 152 } 153 } 154 155 } 156 157 // FIXME: Should unload the beans first. 158 private void reload() { 159 m_allBeans = new ArrayList<>(); 160 161 try { 162 registerAdminBean( new CoreBean( m_engine ) ); 163 registerAdminBean( new UserBean( m_engine ) ); 164 registerAdminBean( new SearchManagerBean( m_engine ) ); 165 registerAdminBean( new PluginBean( m_engine ) ); 166 registerAdminBean( new FilterBean( m_engine ) ); 167 } catch( final NotCompliantMBeanException e ) { 168 log.error( e.getMessage(), e ); 169 } 170 for( final ModuleManager moduleManager : m_engine.getManagers( ModuleManager.class ) ) { 171 registerBeans( moduleManager.modules() ); 172 } 173 } 174 175 /* (non-Javadoc) 176 * @see org.apache.wiki.ui.admin.AdminBeanManager#getAllBeans() 177 */ 178 @Override 179 public List< AdminBean > getAllBeans() { 180 if( m_allBeans == null ) { 181 reload(); 182 } 183 184 return m_allBeans; 185 } 186 187 /* (non-Javadoc) 188 * @see org.apache.wiki.ui.admin.AdminBeanManager#findBean(java.lang.String) 189 */ 190 @Override 191 public AdminBean findBean( final String id ) { 192 for( final AdminBean ab : m_allBeans ) { 193 if( ab.getId().equals( id ) ) { 194 return ab; 195 } 196 } 197 198 return null; 199 } 200 201 /** 202 * Provides a JDK 1.5-compliant version of the MBeanServerFactory. This will simply bind to the 203 * platform MBeanServer. 204 */ 205 private static final class MBeanServerFactory15 { 206 private MBeanServerFactory15() 207 {} 208 209 public static MBeanServer getServer() { 210 return ManagementFactory.getPlatformMBeanServer(); 211 } 212 } 213 214 /** 215 * Returns the type identifier for a string type. 216 * 217 * @param type A type string. 218 * @return A type value. 219 */ 220 @Override 221 public int getTypeFromString( final String type ) { 222 if( "core".equals( type ) ) { 223 return AdminBean.CORE; 224 } else if( "editors".equals( type ) ) { 225 return AdminBean.EDITOR; 226 } 227 228 return AdminBean.UNKNOWN; 229 } 230 231 /* (non-Javadoc) 232 * @see org.apache.wiki.ui.admin.AdminBeanManager#actionPerformed(org.apache.wiki.event.WikiEvent) 233 */ 234 @Override 235 public void actionPerformed( final WikiEvent event ) { 236 if( event instanceof WikiEngineEvent ) { 237 if( event.getType() == WikiEngineEvent.SHUTDOWN ) { 238 for( final AdminBean m_allBean : m_allBeans ) { 239 try { 240 final ObjectName on = getObjectName( m_allBean ); 241 if( m_mbeanServer.isRegistered( on ) ) { 242 m_mbeanServer.unregisterMBean( on ); 243 log.info( "Unregistered AdminBean " + m_allBean.getTitle() ); 244 } 245 } catch( final MalformedObjectNameException e ) { 246 log.error( "Malformed object name when unregistering", e ); 247 } catch( final InstanceNotFoundException e ) { 248 log.error( "Object was registered; yet claims that it's not there", e ); 249 } catch( final MBeanRegistrationException e ) { 250 log.error( "Registration exception while unregistering", e ); 251 } 252 } 253 } 254 } 255 } 256 257}