1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22 package org.jboss.invocation.local;
23
24 import java.net.InetAddress;
25 import java.security.AccessController;
26 import java.security.PrivilegedAction;
27 import java.security.PrivilegedExceptionAction;
28 import java.security.PrivilegedActionException;
29 import javax.management.ObjectName;
30 import javax.naming.InitialContext;
31 import javax.transaction.TransactionManager;
32
33 import org.jboss.invocation.Invocation;
34 import org.jboss.invocation.Invoker;
35 import org.jboss.invocation.InvokerInterceptor;
36 import org.jboss.mx.util.JMXExceptionDecoder;
37 import org.jboss.proxy.TransactionInterceptor;
38 import org.jboss.system.Registry;
39 import org.jboss.system.ServiceMBeanSupport;
40
41 /**
42 * The Invoker is a local gate in the JMX system.
43 *
44 * @author <a href="mailto:marc.fleury@jboss.org>Marc Fleury</a>
45 * @author Scott.Stark@jboss.org
46 * @version $Revision: 37459 $
47 * @jmx:mbean extends="org.jboss.system.ServiceMBean"
48 */
49 public class LocalInvoker
50 extends ServiceMBeanSupport
51 implements Invoker, LocalInvokerMBean
52 {
53 private MBeanServerAction serverAction = new MBeanServerAction();
54
55 protected void createService() throws Exception
56 {
57 // note on design: We need to call it ourselves as opposed to
58 // letting the client InvokerInterceptor look it
59 // up through the use of Registry, the reason being including
60 // the classes in the client.
61 // If we move to a JNDI format (with local calls) for the
62 // registry we could remove the call below
63 InvokerInterceptor.setLocal(this);
64
65 Registry.bind(serviceName, this);
66 }
67
68 protected void startService() throws Exception
69 {
70 InitialContext ctx = new InitialContext();
71 try
72 {
73
74 /**
75 * FIXME marcf: what is this doing here?
76 */
77 TransactionManager tm = (TransactionManager) ctx.lookup("java:/TransactionManager");
78 TransactionInterceptor.setTransactionManager(tm);
79 }
80 finally
81 {
82 ctx.close();
83 }
84
85 log.debug("Local invoker for JMX node started");
86 }
87
88 protected void destroyService()
89 {
90 Registry.unbind(serviceName);
91 }
92
93 // Invoker implementation --------------------------------
94
95 public String getServerHostName()
96 {
97 try
98 {
99 return InetAddress.getLocalHost().getHostName();
100 }
101 catch (Exception ignored)
102 {
103 return null;
104 }
105 }
106
107 /**
108 * Invoke a method.
109 */
110 public Object invoke(Invocation invocation) throws Exception
111 {
112 ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader();
113
114 ObjectName mbean = (ObjectName) Registry.lookup((Integer) invocation.getObjectName());
115 try
116 {
117 Object[] args = {invocation};
118 Object rtnValue = serverAction.invoke(mbean, "invoke", args,
119 Invocation.INVOKE_SIGNATURE);
120 return rtnValue;
121 }
122 catch (Exception e)
123 {
124 e = (Exception) JMXExceptionDecoder.decode(e);
125 if (log.isTraceEnabled())
126 log.trace("Failed to invoke on mbean: " + mbean, e);
127 throw e;
128 }
129 finally
130 {
131 TCLAction.UTIL.setContextClassLoader(oldCl);
132 }
133 }
134
135 /** Perform the MBeanServer.invoke op in a PrivilegedExceptionAction if
136 * running with a security manager.
137 */
138 class MBeanServerAction implements PrivilegedExceptionAction
139 {
140 private ObjectName target;
141 String method;
142 Object[] args;
143 String[] sig;
144
145 MBeanServerAction()
146 {
147 }
148 MBeanServerAction(ObjectName target, String method, Object[] args, String[] sig)
149 {
150 this.target = target;
151 this.method = method;
152 this.args = args;
153 this.sig = sig;
154 }
155
156 public Object run() throws Exception
157 {
158 Object rtnValue = server.invoke(target, method, args, sig);
159 return rtnValue;
160 }
161 Object invoke(ObjectName target, String method, Object[] args, String[] sig)
162 throws Exception
163 {
164 SecurityManager sm = System.getSecurityManager();
165 Object rtnValue = null;
166 if( sm == null )
167 {
168 // Direct invocation on MBeanServer
169 rtnValue = server.invoke(target, method, args, sig);
170 }
171 else
172 {
173 try
174 {
175 // Encapsulate the invocation in a PrivilegedExceptionAction
176 MBeanServerAction action = new MBeanServerAction(target, method, args, sig);
177 rtnValue = AccessController.doPrivileged(action);
178 }
179 catch (PrivilegedActionException e)
180 {
181 Exception ex = e.getException();
182 throw ex;
183 }
184 }
185 return rtnValue;
186 }
187 }
188
189 interface TCLAction
190 {
191 class UTIL
192 {
193 static TCLAction getTCLAction()
194 {
195 return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
196 }
197
198 static ClassLoader getContextClassLoader()
199 {
200 return getTCLAction().getContextClassLoader();
201 }
202
203 static ClassLoader getContextClassLoader(Thread thread)
204 {
205 return getTCLAction().getContextClassLoader(thread);
206 }
207
208 static void setContextClassLoader(ClassLoader cl)
209 {
210 getTCLAction().setContextClassLoader(cl);
211 }
212
213 static void setContextClassLoader(Thread thread, ClassLoader cl)
214 {
215 getTCLAction().setContextClassLoader(thread, cl);
216 }
217 }
218
219 TCLAction NON_PRIVILEGED = new TCLAction()
220 {
221 public ClassLoader getContextClassLoader()
222 {
223 return Thread.currentThread().getContextClassLoader();
224 }
225
226 public ClassLoader getContextClassLoader(Thread thread)
227 {
228 return thread.getContextClassLoader();
229 }
230
231 public void setContextClassLoader(ClassLoader cl)
232 {
233 Thread.currentThread().setContextClassLoader(cl);
234 }
235
236 public void setContextClassLoader(Thread thread, ClassLoader cl)
237 {
238 thread.setContextClassLoader(cl);
239 }
240 };
241
242 TCLAction PRIVILEGED = new TCLAction()
243 {
244 private final PrivilegedAction getTCLPrivilegedAction = new PrivilegedAction()
245 {
246 public Object run()
247 {
248 return Thread.currentThread().getContextClassLoader();
249 }
250 };
251
252 public ClassLoader getContextClassLoader()
253 {
254 return (ClassLoader)AccessController.doPrivileged(getTCLPrivilegedAction);
255 }
256
257 public ClassLoader getContextClassLoader(final Thread thread)
258 {
259 return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction()
260 {
261 public Object run()
262 {
263 return thread.getContextClassLoader();
264 }
265 });
266 }
267
268 public void setContextClassLoader(final ClassLoader cl)
269 {
270 AccessController.doPrivileged(
271 new PrivilegedAction()
272 {
273 public Object run()
274 {
275 Thread.currentThread().setContextClassLoader(cl);
276 return null;
277 }
278 }
279 );
280 }
281
282 public void setContextClassLoader(final Thread thread, final ClassLoader cl)
283 {
284 AccessController.doPrivileged(
285 new PrivilegedAction()
286 {
287 public Object run()
288 {
289 thread.setContextClassLoader(cl);
290 return null;
291 }
292 }
293 );
294 }
295 };
296
297 ClassLoader getContextClassLoader();
298
299 ClassLoader getContextClassLoader(Thread thread);
300
301 void setContextClassLoader(ClassLoader cl);
302
303 void setContextClassLoader(Thread thread, ClassLoader cl);
304 }
305 }
306