1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.catalina.mbeans;
19
20
21 import java.util.Iterator;
22
23 import javax.naming.Binding;
24 import javax.naming.Context;
25 import javax.naming.InitialContext;
26 import javax.naming.NamingEnumeration;
27 import javax.naming.NamingException;
28 import javax.naming.OperationNotSupportedException;
29
30 import org.apache.catalina.Group;
31 import org.apache.catalina.Lifecycle;
32 import org.apache.catalina.LifecycleEvent;
33 import org.apache.catalina.LifecycleListener;
34 import org.apache.catalina.Role;
35 import org.apache.catalina.User;
36 import org.apache.catalina.UserDatabase;
37 import org.apache.juli.logging.Log;
38 import org.apache.juli.logging.LogFactory;
39 import org.apache.tomcat.util.res.StringManager;
40
41
42 /**
43  * Implementation of <code>LifecycleListener</code> that instantiates the
44  * set of MBeans associated with global JNDI resources that are subject to
45  * management.
46  *
47  * @author Craig R. McClanahan
48  * @since 4.1
49  */

50 public class GlobalResourcesLifecycleListener implements LifecycleListener {
51
52     private static final Log log = LogFactory.getLog(GlobalResourcesLifecycleListener.class);
53     protected static final StringManager sm = StringManager.getManager(GlobalResourcesLifecycleListener.class);
54
55
56     // ----------------------------------------------------- Instance Variables
57
58     /**
59      * The owning Catalina component that we are attached to.
60      */

61     protected Lifecycle component = null;
62
63
64     // ---------------------------------------------- LifecycleListener Methods
65
66     /**
67      * Primary entry point for startup and shutdown events.
68      *
69      * @param event The event that has occurred
70      */

71     @Override
72     public void lifecycleEvent(LifecycleEvent event) {
73
74         if (Lifecycle.START_EVENT.equals(event.getType())) {
75             component = event.getLifecycle();
76             createMBeans();
77         } else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
78             destroyMBeans();
79             component = null;
80         }
81     }
82
83
84     // ------------------------------------------------------ Protected Methods
85
86     /**
87      * Create the MBeans for the interesting global JNDI resources.
88      */

89     protected void createMBeans() {
90         // Look up our global naming context
91         Context context = null;
92         try {
93             context = (Context) (new InitialContext()).lookup("java:/");
94         } catch (NamingException e) {
95             log.error(sm.getString("globalResources.noNamingContext"));
96             return;
97         }
98
99         // Recurse through the defined global JNDI resources context
100         try {
101             createMBeans("", context);
102         } catch (NamingException e) {
103             log.error(sm.getString("globalResources.createError"), e);
104         }
105     }
106
107
108     /**
109      * Create the MBeans for the interesting global JNDI resources in
110      * the specified naming context.
111      *
112      * @param prefix Prefix for complete object name paths
113      * @param context Context to be scanned
114      *
115      * @exception NamingException if a JNDI exception occurs
116      */

117     protected void createMBeans(String prefix, Context context) throws NamingException {
118
119         if (log.isDebugEnabled()) {
120             log.debug("Creating MBeans for Global JNDI Resources in Context '" +
121                 prefix + "'");
122         }
123
124         try {
125             NamingEnumeration<Binding> bindings = context.listBindings("");
126             while (bindings.hasMore()) {
127                 Binding binding = bindings.next();
128                 String name = prefix + binding.getName();
129                 Object value = context.lookup(binding.getName());
130                 if (log.isDebugEnabled()) {
131                     log.debug("Checking resource " + name);
132                 }
133                 if (value instanceof Context) {
134                     createMBeans(name + "/", (Context) value);
135                 } else if (value instanceof UserDatabase) {
136                     try {
137                         createMBeans(name, (UserDatabase) value);
138                     } catch (Exception e) {
139                         log.error(sm.getString("globalResources.userDatabaseCreateError", name), e);
140                     }
141                 }
142             }
143         } catch (RuntimeException ex) {
144             log.error(sm.getString("globalResources.createError.runtime"), ex);
145         } catch (OperationNotSupportedException ex) {
146             log.error(sm.getString("globalResources.createError.operation"), ex);
147         }
148     }
149
150
151     /**
152      * Create the MBeans for the specified UserDatabase and its contents.
153      *
154      * @param name Complete resource name of this UserDatabase
155      * @param database The UserDatabase to be processed
156      *
157      * @exception Exception if an exception occurs while creating MBeans
158      */

159     protected void createMBeans(String name, UserDatabase database) throws Exception {
160
161         // Create the MBean for the UserDatabase itself
162         if (log.isDebugEnabled()) {
163             log.debug("Creating UserDatabase MBeans for resource " + name);
164             log.debug("Database=" + database);
165         }
166         try {
167             MBeanUtils.createMBean(database);
168         } catch(Exception e) {
169             throw new IllegalArgumentException(sm.getString("globalResources.createError.userDatabase", name), e);
170         }
171
172         // Create the MBeans for each defined Role
173         Iterator<Role> roles = database.getRoles();
174         while (roles.hasNext()) {
175             Role role = roles.next();
176             if (log.isDebugEnabled()) {
177                 log.debug("  Creating Role MBean for role " + role);
178             }
179             try {
180                 MBeanUtils.createMBean(role);
181             } catch (Exception e) {
182                 throw new IllegalArgumentException(sm.getString("globalResources.createError.userDatabase.role", role), e);
183             }
184         }
185
186         // Create the MBeans for each defined Group
187         Iterator<Group> groups = database.getGroups();
188         while (groups.hasNext()) {
189             Group group = groups.next();
190             if (log.isDebugEnabled()) {
191                 log.debug("  Creating Group MBean for group " + group);
192             }
193             try {
194                 MBeanUtils.createMBean(group);
195             } catch (Exception e) {
196                 throw new IllegalArgumentException(sm.getString("globalResources.createError.userDatabase.group", group), e);
197             }
198         }
199
200         // Create the MBeans for each defined User
201         Iterator<User> users = database.getUsers();
202         while (users.hasNext()) {
203             User user = users.next();
204             if (log.isDebugEnabled()) {
205                 log.debug("  Creating User MBean for user " + user);
206             }
207             try {
208                 MBeanUtils.createMBean(user);
209             } catch (Exception e) {
210                 throw new IllegalArgumentException(sm.getString("globalResources.createError.userDatabase.user", user), e);
211             }
212         }
213     }
214
215
216     /**
217      * Destroy the MBeans for the interesting global JNDI resources.
218      */

219     protected void destroyMBeans() {
220         if (log.isDebugEnabled()) {
221             log.debug("Destroying MBeans for Global JNDI Resources");
222         }
223     }
224 }
225