1 /*
2 * Copyright 2004-2005 OpenSymphony
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 *
16 */
17
18 /*
19 * Previously Copyright (c) 2001-2004 James House
20 */
21 package org.quartz.jobs.ee.jmx;
22
23
24 import java.util.LinkedList;
25 import java.util.StringTokenizer;
26
27 import javax.management.MBeanServer;
28 import javax.management.MBeanServerFactory;
29 import javax.management.ObjectName;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.quartz.Job;
34 import org.quartz.JobDataMap;
35 import org.quartz.JobExecutionContext;
36 import org.quartz.JobExecutionException;
37
38
39 /**
40 * Generic JMX invoker Job. It supports any number or type of parameters
41 * to the JMX bean.<p>
42 *
43 * The required parameters are as follows (case doesn't matter):<p>
44 * <dl>
45 * <dt><strong>JMX_OBJECTNAME</strong>
46 * <dd>This is the fully qualifed name of the object (ie in JBoss to lookup
47 * the log4j jmx bean you would specify "jboss.system:type=Log4jService,service=Logging"
48 * <dt><strong>JMX_METHOD</strong>
49 * <dd>This is the method to invoke on the specified JMX Bean. (ie in JBoss to
50 * change the log level you would specify "setLoggerLevel"
51 * <dt><strong>JMX_PARAMDEFS</strong>
52 * <dd>This is a definition of the parameters to be passed to the specified method
53 * and their corresponding java types. Each parameter definition is comma seperated
54 * and has the following parts: <type>:<name>. Type is the java type for the parameter.
55 * The following types are supported:<p>
56 * <b>i</b> - is for int<p>
57 * <b>l</b> - is for long<p>
58 * <b>f</b> - is for float<p>
59 * <b>d</b> - is for double<p>
60 * <b>s</b> - is for String<p>
61 * <b>b</b> - is for boolean<p>
62 * For ilfdb use lower for native type and upper for object wrapper. The name portion
63 * of the definition is the name of the parameter holding the string value. (ie
64 * s:fname,s:lname would require 2 parameters of the name fname and lname and
65 * would be passed in that order to the method.
66 *
67 * @author James Nelson (jmn@provident-solutions.com) -- Provident Solutions LLC
68 *
69 */
70 public class JMXInvokerJob implements Job {
71
72 private final Log log = LogFactory.getLog(getClass());
73
74 public void execute(JobExecutionContext context) throws JobExecutionException {
75 try {
76 Object[] params=null;
77 String[] types=null;
78 String objName = null;
79 String objMethod = null;
80
81 JobDataMap jobDataMap = context.getMergedJobDataMap();
82
83 String[] keys = jobDataMap.getKeys();
84 for (int i = 0; i < keys.length; i++) {
85 String value = jobDataMap.getString(keys[i]);
86 if ("JMX_OBJECTNAME".equalsIgnoreCase(keys[i])) {
87 objName = value;
88 } else if ("JMX_METHOD".equalsIgnoreCase(keys[i])) {
89 objMethod = value;
90 } else if("JMX_PARAMDEFS".equalsIgnoreCase(keys[i])) {
91 String[] paramdefs=split(value, ",");
92 params=new Object[paramdefs.length];
93 types=new String[paramdefs.length];
94 for(int k=0;k<paramdefs.length;k++) {
95 String parts[]= split(paramdefs[k], ":");
96 if (parts.length<2) {
97 throw new Exception("Invalid parameter definition: required parts missing "+paramdefs[k]);
98 }
99 switch(parts[0].charAt(0)) {
100 case 'i':
101 params[k]=new Integer(jobDataMap.getString(parts[1]));
102 types[k]=Integer.TYPE.getName();
103 break;
104 case 'I':
105 params[k]=new Integer(jobDataMap.getString(parts[1]));
106 types[k]=Integer.class.getName();
107 break;
108 case 'l':
109 params[k]=new Long(jobDataMap.getString(parts[1]));
110 types[k]=Long.TYPE.getName();
111 break;
112 case 'L':
113 params[k]=new Long(jobDataMap.getString(parts[1]));
114 types[k]=Long.class.getName();
115 break;
116 case 'f':
117 params[k]=new Float(jobDataMap.getString(parts[1]));
118 types[k]=Float.TYPE.getName();
119 break;
120 case 'F':
121 params[k]=new Float(jobDataMap.getString(parts[1]));
122 types[k]=Float.class.getName();
123 break;
124 case 'd':
125 params[k]=new Double(jobDataMap.getString(parts[1]));
126 types[k]=Double.TYPE.getName();
127 break;
128 case 'D':
129 params[k]=new Double(jobDataMap.getString(parts[1]));
130 types[k]=Double.class.getName();
131 break;
132 case 's':
133 params[k]=new String(jobDataMap.getString(parts[1]));
134 types[k]=String.class.getName();
135 break;
136 case 'b':
137 params[k]=new Boolean(jobDataMap.getString(parts[1]));
138 types[k]=Boolean.TYPE.getName();
139 break;
140 case 'B':
141 params[k]=new Boolean(jobDataMap.getString(parts[1]));
142 types[k]=Boolean.class.getName();
143 break;
144 }
145 }
146 }
147 }
148
149 if (objName==null || objMethod==null) {
150 throw new Exception("Required parameters missing");
151 }
152
153 context.setResult(invoke(objName, objMethod, params, types));
154 } catch (Exception e) {
155 String m = "Caught a " + e.getClass().getName() + " exception : " + e.getMessage();
156 getLog().error(m, e);
157 throw new JobExecutionException(m, e, false);
158 }
159 }
160
161 private String[] split(String str, String splitStr) // Same as String.split(.) in JDK 1.4
162 {
163 LinkedList l = new LinkedList();
164
165 StringTokenizer strTok = new StringTokenizer(str, splitStr);
166 while(strTok.hasMoreTokens()) {
167 String tok = strTok.nextToken();
168 l.add(tok);
169 }
170
171 return (String[])l.toArray(new String[l.size()]);
172 }
173
174 private Object invoke(String objectName, String method, Object[] params, String[] types) throws Exception {
175 MBeanServer server = (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0);
176 ObjectName mbean = new ObjectName(objectName);
177
178 if (server == null) {
179 throw new Exception("Can't find mbean server");
180 }
181
182 getLog().info("invoking " + method);
183 return server.invoke(mbean, method, params, types);
184 }
185
186 protected Log getLog() {
187 return log;
188 }
189
190 }