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 }