View | Details | Raw Unified | Return to bug 44308
Collapse All | Expand All

(-)jmx/AbstractModelMBean.java (+168 lines)
Line 0 Link Here
1
package org.apache.log4j.jmx;
2
3
import javax.management.Descriptor;
4
import javax.management.MBeanException;
5
import javax.management.MBeanParameterInfo;
6
import javax.management.RuntimeOperationsException;
7
import javax.management.modelmbean.DescriptorSupport;
8
import javax.management.modelmbean.ModelMBeanAttributeInfo;
9
import javax.management.modelmbean.ModelMBeanConstructorInfo;
10
import javax.management.modelmbean.ModelMBeanInfo;
11
import javax.management.modelmbean.ModelMBeanInfoSupport;
12
import javax.management.modelmbean.ModelMBeanNotificationInfo;
13
import javax.management.modelmbean.ModelMBeanOperationInfo;
14
import javax.management.modelmbean.RequiredModelMBean;
15
16
/**
17
 * Base class for Model MBeans.
18
 * To provide a Mode MBean simply extend this class and override getModelMbeanInfo using
19
 * createModelMBeanInfo.
20
 * For registering attributes, methods, constructors, ... there exist createModelMBean*-methods.
21
 * @author Stefan Fleiter
22
 */
23
public abstract class AbstractModelMBean extends RequiredModelMBean {
24
25
    private final Object delegate;
26
27
    /**
28
     * Constructor to use an own instance of a Delegate to represent per JMX.
29
     * @param delegate Instance of LoggerManager to represent as MBean
30
     * @throws MBeanException user Exception of MBean
31
     * @throws RuntimeOperationsException Runtime Exceptions in the MBeanServer
32
     */
33
    public AbstractModelMBean(Object delegate) throws MBeanException, RuntimeOperationsException {
34
        this.delegate = delegate;
35
        setModelMBeanInfo(getModelMBeanInfo());
36
        try {
37
            setManagedResource(delegate, "ObjectReference");
38
        } catch (Exception e) {
39
            throw new RuntimeException(e);
40
        }
41
    }
42
43
    public Object getDelegate() {
44
        return delegate;
45
    }
46
47
    protected abstract ModelMBeanInfo getModelMBeanInfo() throws RuntimeOperationsException, MBeanException;
48
49
    /**
50
     * Creates the ModelMBeanNotificationInfos for this ModelMBean, extracted for easy extendability.
51
     * @return Array of ModelMBeanNotificationInfo describing the methods available per JMX
52
     */
53
    protected ModelMBeanNotificationInfo[] createModelMBeanNotificationInfos() {
54
        return new ModelMBeanNotificationInfo[] {};
55
    }
56
57
    /**
58
     * Creates the ModelMBeanConstructorInfos for this ModelMBean, extracted for easy extendability.
59
     * @return Array of ModelMBeanConstructorInfo describing the methods available per JMX
60
     */
61
    protected ModelMBeanConstructorInfo[] createModelMBeanConstructorInfos() {
62
        return new ModelMBeanConstructorInfo[] {};
63
    }
64
65
    /**
66
     * Creates the ModelMBeanOperationInfos for this ModelMBean, extracted for easy extendability.
67
     * @return Array of ModelMBeanOperationInfo describing the methods available per JMX
68
     */
69
    protected ModelMBeanOperationInfo[] createModelMBeanOperationInfos() {
70
        return new ModelMBeanOperationInfo[] {};
71
    }
72
73
    /**
74
     * Creates the ModelMBeanAttributeInfos for this ModelMBean, extracted for easy extendability.
75
     * @return Array of ModelMBeanAttributeInfo describing the methods available per JMX
76
     */
77
    protected ModelMBeanAttributeInfo[] createModelMBeanAttributeInfos() {
78
        return new ModelMBeanAttributeInfo[] {};
79
    }
80
81
    /**
82
     * Creates the ModelMBeanInfo for this ModelMBean.
83
     * @param displayName Name for this mbean to display in manager applications
84
     * @param description Description what this MBean does
85
     * @param clazz Class implementing the functionality and this MBean delegates to
86
     * @param mbeanName Name of
87
     * @return Array of ModelMBeanConstructorInfo describing the methods available per JMX
88
     */
89
    protected ModelMBeanInfo createModelMBeanInfo(String displayName, String description,
90
            Class clazz, String mbeanName) {
91
                ModelMBeanInfo result;
92
                Descriptor managerDescriptor = new DescriptorSupport(new String[] {
93
                        "name=" + mbeanName,
94
                        "descriptorType=mbean",
95
                        "displayName=" + displayName,
96
                        "type=" + clazz.getName(),
97
                });
98
99
                result = new ModelMBeanInfoSupport(
100
                        clazz.getName(),
101
                        description,
102
                        createModelMBeanAttributeInfos(),
103
                        createModelMBeanConstructorInfos(),
104
                        createModelMBeanOperationInfos(),
105
                        createModelMBeanNotificationInfos(),
106
                        managerDescriptor
107
                        );
108
                return result;
109
            }
110
111
    /**
112
     * Helper Method for registering operations.
113
     * @param name Name of operation
114
     * @param description describes what the operation does
115
     * @param parameters parameters of the operation
116
     * @param returnType class which is returned by the to be registered method
117
     * @param operationInfo INFO if non-modifying and ACTION if modifying status
118
     * @return ModelMBeanOperationInfo for the described method
119
     */
120
    protected ModelMBeanOperationInfo createOperationInfo(String name, String description,
121
            MBeanParameterInfo[] parameters, Class returnType, int operationInfo) {
122
                return new ModelMBeanOperationInfo(
123
                        name,
124
                        description,
125
                        parameters,
126
                        returnType.getName(),
127
                        operationInfo,
128
                        new DescriptorSupport(new String[] {
129
                                "name=" + name,
130
                                "displayName=" + description,
131
                                "descriptorType=operation",
132
                                "class=" + getDelegate().getClass().getName(),
133
                                "role=operation",
134
                            })
135
                        );
136
            }
137
138
    /**
139
     * Helper Method for registering attributes.
140
     * @param name Name of attribute
141
     * @param description describes what the attribute is for
142
     * @param type type of attribute (return value of get and parameter of set Operation)
143
     * @param readable true, if attribute can be read
144
     * @param writable true, if attribute can be set
145
     * @param is true if the attribute has an "is" getter, false otherwise
146
     * @param getMethod name of getter Method
147
     * @param setMethod name of setter Method
148
     * @return ModelMBeanAttributeInfo for the described method
149
     */
150
    protected ModelMBeanAttributeInfo createAttributeInfo(String name, String description,
151
            Class type, boolean readable, boolean writable, boolean is, String getMethod,
152
            String setMethod) {
153
                return new ModelMBeanAttributeInfo(
154
                        name,
155
                        type.getName(),
156
                        description,
157
                        readable, writable, is,
158
                        new DescriptorSupport(new String[] {
159
                                "name=" + name,
160
                                "descriptorType=attribute",
161
                                "displayName=" + description,
162
                                "getMethod=" + getMethod,
163
                                "setMethod=" + setMethod,
164
                            })
165
                        );
166
            }
167
168
}
0
  + Id
169
  + Id
(-)jmx/RollbackableLoggerManager.java (+70 lines)
Line 0 Link Here
1
/**
2
 *
3
 */
4
package org.apache.log4j.jmx;
5
6
import java.util.HashMap;
7
import java.util.Iterator;
8
import java.util.Map;
9
import java.util.Map.Entry;
10
11
import org.apache.log4j.Level;
12
import org.apache.log4j.Logger;
13
14
/**
15
 * LoggerManager implementation with additional rollback support to be able to undo the changes
16
 * done by this class.
17
 * @see LoggerManager
18
 * @author Stefan Fleiter
19
 */
20
public class RollbackableLoggerManager extends LoggerManager {
21
22
    /**
23
     * Thread safety guaranteed by locking on this (instance of LoggerManager) on every access.
24
     */
25
    private final Map savedLoggerConfiguration = new HashMap();
26
27
    /**
28
     * Sets the level of the specified logger.
29
     * Can be overriden to do something additional when modifying loggers.
30
     * @param logger Log4j Logger Instance
31
     * @param level New level as string
32
     * @return true, if level has changed, false if level is same as before
33
     */
34
    protected boolean doSetLogLogLevel(Logger logger, String level) {
35
        Level originalLevel = logger.getLevel();
36
        boolean modified = super.doSetLogLogLevel(logger, level);
37
        synchronized (savedLoggerConfiguration) {
38
            if (!savedLoggerConfiguration.containsKey(logger)) {
39
                savedLoggerConfiguration.put(logger, originalLevel);
40
            }
41
        }
42
        return modified;
43
    }
44
45
    /**
46
     * Rolls back all modifications which where done to the log configuration by this instance.
47
     */
48
    public synchronized void rollbackLogConfiguration() {
49
        synchronized (savedLoggerConfiguration) {
50
            for (Iterator it = savedLoggerConfiguration.entrySet().iterator(); it.hasNext(); ) {
51
                Map.Entry entry = (Entry) it.next();
52
                Logger logger = (Logger) entry.getKey();
53
                Level originalLevel = (Level) entry.getValue();
54
                logger.setLevel(originalLevel);
55
            }
56
            savedLoggerConfiguration.clear();
57
        }
58
    }
59
60
    /**
61
     * Shutdown hook which clears all references, but does not call <code>resetLogConfiguration</code>
62
     * @see #resetLogConfiguration()
63
     */
64
    public void destroy() {
65
        synchronized (savedLoggerConfiguration) {
66
            savedLoggerConfiguration.clear();
67
        }
68
    }
69
70
}
0
  + Id
71
  + Id
(-)jmx/LoggerManager.java (+183 lines)
Line 0 Link Here
1
package org.apache.log4j.jmx;
2
3
import java.util.ArrayList;
4
import java.util.Enumeration;
5
import java.util.HashMap;
6
import java.util.Iterator;
7
import java.util.List;
8
import java.util.Map;
9
10
import org.apache.log4j.Level;
11
import org.apache.log4j.LogManager;
12
import org.apache.log4j.Logger;
13
import org.apache.log4j.spi.LoggerRepository;
14
15
/**
16
 * Helper for reading and modifying the logger configuration of a running log4j instance.
17
 * This class is thread safe.
18
 * @author Stefan Fleiter
19
 */
20
public class LoggerManager {
21
22
    /**
23
     * Returns a Level instance matching the given string representation.
24
     * @param levelName Name of the level of INHERITED to inherit level from the next ancestor.
25
     * @return Level matching levelName, null for INHERITED
26
     * @throws IllegalArgumentException levelName does not represent a known level
27
     */
28
    Level getLevelByName(String levelName) throws IllegalArgumentException {
29
        Level level = Level.toLevel(levelName, null);
30
        if (null == level && null != levelName) {
31
            String lowerLevelName = levelName.toLowerCase();
32
            if (!"inherit".equals(lowerLevelName) &&
33
                    !"inherited".equals(lowerLevelName) &&
34
                    !"null".equals(lowerLevelName)) {
35
                throw new IllegalArgumentException('"' + levelName + "\" is not a valid level");
36
            }
37
        }
38
        return level;
39
    }
40
41
    /**
42
     * Returns the string representation of the given Level.
43
     * @param level Level instance
44
     * @return Name of level or null if level is null
45
     */
46
    String getLogLevelString(Level level) {
47
        return null == level ? null : level.toString();
48
    }
49
50
51
    /**
52
     * Returns the explicit set level of a specified logger.
53
     * @param loggerName Name of the logger
54
     * @return Level of the logger
55
     */
56
    public String getLogLevel(String loggerName) {
57
        return getLogLevelString(LogManager.getLogger(loggerName).getLevel());
58
    }
59
60
    /**
61
     * Returns the effective level (the level set on this logger or if not set explicitly the
62
     * level of the next ancestor) of the specified logger.
63
     * @param loggerName Name of logger either existing or to be created
64
     * @return Effective level of the logger
65
     */
66
    public String getEffectiveLogLevel(String loggerName) {
67
        return getLogLevelString(LogManager.getLogger(loggerName).getEffectiveLevel());
68
    }
69
70
    /**
71
     * Compares two levels and returns whether they are equal.
72
     * @param first first level
73
     * @param second second level
74
     * @return true if levels are equal
75
     */
76
    boolean levelEquals(Level first, Level second) {
77
        if (null == first) {
78
            return null == second;
79
        } else {
80
            return first.equals(second);
81
        }
82
    }
83
84
    /**
85
     * Sets the level of the specified logger.
86
     * @param loggerName Name of logger either existing or to be created
87
     * @param level New level
88
     * @throws IllegalArgumentException levelName does not represent a known level
89
     */
90
    public void setLogLevel(String loggerName, String level) throws IllegalArgumentException {
91
        Logger logger = LogManager.getLogger(loggerName);
92
        doSetLogLogLevel(logger, level);
93
    }
94
95
    /**
96
     * Returns the level of the root logger.
97
     * @return Level of the logger
98
     */
99
    public String getRootLogLevel() {
100
        return getLogLevelString(LogManager.getRootLogger().getLevel());
101
    }
102
103
    /**
104
     * Sets the level of the specified logger.
105
     * @param level New level
106
     * @throws IllegalArgumentException levelName does not represent a known level
107
     */
108
    public void setRootLogLevel(String level) throws IllegalArgumentException {
109
        Logger logger = LogManager.getRootLogger();
110
        doSetLogLogLevel(logger, level);
111
    }
112
113
    /**
114
     * Sets the level of the specified logger.
115
     * Can be overriden to do something additional when modifying loggers.
116
     * @param logger Log4j Logger Instance
117
     * @param level New level as string
118
     * @return true, if level has changed, false if level is same as before
119
     */
120
    protected boolean doSetLogLogLevel(Logger logger, String level) {
121
        Level originalLevel = logger.getLevel();
122
        Level newLevel = getLevelByName(level);
123
        boolean modified = false;
124
        if (!levelEquals(newLevel, originalLevel)) {
125
            modified  = true;
126
            logger.setLevel(newLevel);
127
        }
128
        return modified;
129
    }
130
131
    /**
132
     * Shutdown hook.
133
     */
134
    public void destroy() {
135
        // nothing to do
136
    }
137
138
    /**
139
     * Returns a map of all explicitly configured loggers with the level as value.
140
     * @return map of logger names and level names
141
     */
142
    public Map getLogConfiguration() {
143
        Map result = new HashMap();
144
        List loggers = getConfiguredLoggersInternal();
145
        for (Iterator it = loggers.iterator(); it.hasNext(); ) {
146
            Logger logger = (Logger) it.next();
147
            result.put(logger.getName(), logger.getEffectiveLevel().toString());
148
        }
149
        return result;
150
    }
151
152
    /**
153
     * @return all explicitly configured loggers
154
     */
155
    List getConfiguredLoggersInternal() {
156
        List result = new ArrayList();
157
        LoggerRepository r = LogManager.getLoggerRepository();
158
        Enumeration loggers = r.getCurrentLoggers();
159
        while (loggers.hasMoreElements()) {
160
            Logger logger = (Logger) loggers.nextElement();
161
            if (null != logger.getLevel()) {
162
                result.add(logger);
163
            }
164
        }
165
        result.add(LogManager.getRootLogger());
166
        return result;
167
    }
168
169
    /**
170
     * Returns the names of all loggers with an explicit set level
171
     * (Logger{@link #getLogLevel(String)} is not null).
172
     * @return array of names of all explicitly configured loggers
173
     */
174
    public String[] getConfiguredLoggers() {
175
        List configuredLoggers = getConfiguredLoggersInternal();
176
        String[] result = new String[configuredLoggers.size()];
177
        for (int i = 0; i < configuredLoggers.size(); ++i) {
178
            result[i] = ((Logger) configuredLoggers.get(i)).getName();
179
        }
180
        return result;
181
    }
182
183
}
0
  + Id
184
  + Id
(-)jmx/LoggerManagerModelMBean.java (+237 lines)
Line 0 Link Here
1
package org.apache.log4j.jmx;
2
3
import java.util.ArrayList;
4
import java.util.List;
5
import java.util.Map;
6
7
import javax.management.MBeanException;
8
import javax.management.MBeanOperationInfo;
9
import javax.management.MBeanParameterInfo;
10
import javax.management.RuntimeOperationsException;
11
import javax.management.modelmbean.ModelMBeanAttributeInfo;
12
import javax.management.modelmbean.ModelMBeanInfo;
13
import javax.management.modelmbean.ModelMBeanOperationInfo;
14
15
/**
16
 * Model MBean which makes the methods of <code>LoggerManager</code> available per JMX.
17
 * @author Stefan Fleiter
18
 * @see LoggerManager
19
 */
20
public class LoggerManagerModelMBean extends AbstractModelMBean {
21
22
    /**
23
     * Constructor.
24
     * @throws MBeanException user Exception of MBean
25
     * @throws RuntimeOperationsException Runtime Exceptions in the MBeanServer
26
     */
27
    public LoggerManagerModelMBean() throws MBeanException, RuntimeOperationsException {
28
        this(new LoggerManager());
29
    }
30
31
    /**
32
     * Constructor to use an own instance of LoggerManager to represent per JMX.
33
     * @param loggerManager Instance of LoggerManager to represent as MBean
34
     * @throws MBeanException user Exception of MBean
35
     * @throws RuntimeOperationsException Runtime Exceptions in the MBeanServer
36
     */
37
    public LoggerManagerModelMBean(LoggerManager loggerManager) throws MBeanException, RuntimeOperationsException {
38
        super(loggerManager);
39
        setModelMBeanInfo(getModelMBeanInfo());
40
        try {
41
            setManagedResource(loggerManager, "ObjectReference");
42
        } catch (Exception e) {
43
            throw new RuntimeException(e);
44
        }
45
    }
46
47
    /**
48
     * Creates the ModelMBeanOperationInfos for this ModelMBean, extracted for easy extendability.
49
     * @return Array of ModelMBeanOperationInfo describing the methods available per JMX
50
     */
51
    protected ModelMBeanOperationInfo[] createModelMBeanOperationInfos() {
52
        ModelMBeanOperationInfo getLogConfiguration = createOperationInfo(
53
                "getLogConfiguration",
54
                "Return the levels of all explicitly configured loggers",
55
                new MBeanParameterInfo[0],
56
                Map.class,
57
                ModelMBeanOperationInfo.INFO
58
                );
59
        ModelMBeanOperationInfo getConfiguredLoggers = createOperationInfo(
60
                "getConfiguredLoggers",
61
                "Return the names of the explicitly configured loggers",
62
                new MBeanParameterInfo[0],
63
                String[].class,
64
                ModelMBeanOperationInfo.INFO
65
                );
66
67
68
        ModelMBeanOperationInfo getRootLogLevel = createOperationInfo(
69
                "getRootLogLevel",
70
                "Return the level of the root logger",
71
                new MBeanParameterInfo[0],
72
                String.class,
73
                MBeanOperationInfo.INFO
74
                );
75
        ModelMBeanOperationInfo setRootLogLevel = createOperationInfo(
76
                "setRootLogLevel",
77
                "Set the level of the root logger",
78
                new MBeanParameterInfo[] {
79
                        new MBeanParameterInfo(
80
                                "level",
81
                                String.class.getName(),
82
                                "New level of root logger (INHERITED to inherit level from next ancestor)"
83
                                ),
84
85
                },
86
                void.class,
87
                ModelMBeanOperationInfo.ACTION
88
                );
89
90
        ModelMBeanOperationInfo getLogLevel = createOperationInfo(
91
                "getLogLevel",
92
                "Return the level explicitly set at the specified logger, null if this logger INHERITS its level",
93
                new MBeanParameterInfo[] {
94
                        new MBeanParameterInfo(
95
                                "logger",
96
                                String.class.getName(),
97
                                "Name of logger to query level"
98
                                ),
99
                },
100
                String.class,
101
                MBeanOperationInfo.INFO
102
                );
103
        ModelMBeanOperationInfo getEffectiveLogLevel = createOperationInfo(
104
                "getEffectiveLogLevel",
105
                "Return the effective level of the specified logger " +
106
                        "(the explicitly specified level or the level of the next ancestor)",
107
                new MBeanParameterInfo[] {
108
                        new MBeanParameterInfo(
109
                                "logger",
110
                                String.class.getName(),
111
                                "Name of logger to query level"
112
                                ),
113
                },
114
                String.class,
115
                MBeanOperationInfo.INFO
116
                );
117
        ModelMBeanOperationInfo setLogLevel = createOperationInfo(
118
                "setLogLevel",
119
                "Set the level of the specified logger",
120
                new MBeanParameterInfo[] {
121
                        new MBeanParameterInfo(
122
                                "logger",
123
                                String.class.getName(),
124
                                "name of logger to modify level"
125
126
                                ),
127
                            new MBeanParameterInfo(
128
                                    "level",
129
                                    String.class.getName(),
130
                                    "new level of specified logger (INHERITED to inherit level from next ancestor)"
131
                                    ),
132
                },
133
                void.class,
134
                MBeanOperationInfo.ACTION
135
                );
136
137
        ModelMBeanOperationInfo rollbackLogConfiguration = createOperationInfo(
138
                "rollbackLogConfiguration",
139
                "Resets all loggers to its' states before calling actions in this MBean",
140
                new MBeanParameterInfo[0],
141
                void.class,
142
                MBeanOperationInfo.ACTION
143
                );
144
145
146
        ModelMBeanOperationInfo[] modelMBeanOperationInfos = new ModelMBeanOperationInfo[] {
147
                getLogConfiguration, getConfiguredLoggers,
148
                getRootLogLevel, setRootLogLevel,
149
                getLogLevel, getEffectiveLogLevel, setLogLevel,
150
                };
151
152
        // dynamically register rollbackLogConfiguration, but only if our LoggerManager has that method
153
        List modelMBeanOperations = new ArrayList();
154
        try {
155
            getDelegate().getClass().getMethod("rollbackLogConfiguration", null);
156
            modelMBeanOperations.add(rollbackLogConfiguration);
157
        } catch (NoSuchMethodException expected) {
158
            // nothing to do
159
        }
160
        for (int i = 0; i < modelMBeanOperationInfos.length; ++i) {
161
            modelMBeanOperations.add(modelMBeanOperationInfos[i]);
162
        }
163
        modelMBeanOperationInfos = (ModelMBeanOperationInfo[]) modelMBeanOperations.toArray(
164
                new ModelMBeanOperationInfo[modelMBeanOperations.size()]);
165
        return modelMBeanOperationInfos;
166
    }
167
168
    /**
169
     * {@inheritDoc}
170
     */
171
    protected ModelMBeanAttributeInfo[] createModelMBeanAttributeInfos() {
172
        ModelMBeanAttributeInfo rootLoggerAttribute = createAttributeInfo(
173
                "rootLogger",
174
                "Level of root logger",
175
                String.class,
176
                true,
177
                true,
178
                false,
179
                "getRootLogLevel",
180
                "setRootLogLevel"
181
                );
182
183
        ModelMBeanAttributeInfo configuredLoggersAttribute = createAttributeInfo(
184
                "configuredLoggers",
185
                "Names of all loggers with explicitly set log levels",
186
                String[].class,
187
                true,
188
                false,
189
                false,
190
                "getConfiguredLoggers",
191
                null
192
                );
193
194
        ModelMBeanAttributeInfo logConfigurationAttribute = createAttributeInfo(
195
                "logConfiguration",
196
                "Name of all explicitly configured loggers with their log level",
197
                Map.class,
198
                true,
199
                false,
200
                false,
201
                "getLogConfiguration",
202
                null
203
                );
204
205
        return new ModelMBeanAttributeInfo[] {
206
                rootLoggerAttribute,
207
                configuredLoggersAttribute,
208
                logConfigurationAttribute,
209
                };
210
    }
211
212
    /**
213
     * Constructs the ModelMBeanInfo for this Model MBean.
214
     * @return ModelMBeanInfo instance
215
     * @throws MBeanException user Exception of MBean
216
     * @throws RuntimeOperationsException Runtime Exceptions in the MBeanServer
217
     */
218
    protected ModelMBeanInfo getModelMBeanInfo() throws RuntimeOperationsException, MBeanException {
219
        Class clazz = getDelegate().getClass();
220
        String displayName = "Log4jManager";
221
        String description = "Model MBean for Manager Logger Configuration of Log4j";
222
        String mbeanName = "log4j:manager";
223
        return createModelMBeanInfo(displayName, description, clazz, mbeanName);
224
    }
225
226
    /**
227
     * Calls <code>LoggerManager#destroy()</code>.
228
     * @see LoggerManager#destroy()
229
     * {@inheritDoc}}
230
     */
231
    public void postDeregister() {
232
        ((LoggerManager) getDelegate()).destroy();
233
        super.postDeregister();
234
    }
235
236
237
}
0
  + Id
238
  + Id

Return to bug 44308