001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.invocation.local;
023:
024: import java.net.InetAddress;
025: import java.security.AccessController;
026: import java.security.PrivilegedAction;
027: import java.security.PrivilegedExceptionAction;
028: import java.security.PrivilegedActionException;
029: import javax.management.ObjectName;
030: import javax.naming.InitialContext;
031: import javax.transaction.TransactionManager;
032:
033: import org.jboss.invocation.Invocation;
034: import org.jboss.invocation.Invoker;
035: import org.jboss.invocation.InvokerInterceptor;
036: import org.jboss.mx.util.JMXExceptionDecoder;
037: import org.jboss.proxy.TransactionInterceptor;
038: import org.jboss.system.Registry;
039: import org.jboss.system.ServiceMBeanSupport;
040:
041: /**
042: * The Invoker is a local gate in the JMX system.
043: *
044: * @author <a href="mailto:marc.fleury@jboss.org>Marc Fleury</a>
045: * @author Scott.Stark@jboss.org
046: * @version $Revision: 57209 $
047: * @jmx:mbean extends="org.jboss.system.ServiceMBean"
048: */
049: public class LocalInvoker extends ServiceMBeanSupport implements
050: Invoker, LocalInvokerMBean {
051: private MBeanServerAction serverAction = new MBeanServerAction();
052:
053: protected void createService() throws Exception {
054: // note on design: We need to call it ourselves as opposed to
055: // letting the client InvokerInterceptor look it
056: // up through the use of Registry, the reason being including
057: // the classes in the client.
058: // If we move to a JNDI format (with local calls) for the
059: // registry we could remove the call below
060: InvokerInterceptor.setLocal(this );
061:
062: Registry.bind(serviceName, this );
063: }
064:
065: protected void startService() throws Exception {
066: InitialContext ctx = new InitialContext();
067: try {
068:
069: /**
070: * FIXME marcf: what is this doing here?
071: */
072: TransactionManager tm = (TransactionManager) ctx
073: .lookup("java:/TransactionManager");
074: TransactionInterceptor.setTransactionManager(tm);
075: } finally {
076: ctx.close();
077: }
078:
079: log.debug("Local invoker for JMX node started");
080: }
081:
082: protected void destroyService() {
083: Registry.unbind(serviceName);
084: }
085:
086: // Invoker implementation --------------------------------
087:
088: public String getServerHostName() {
089: try {
090: return InetAddress.getLocalHost().getHostName();
091: } catch (Exception ignored) {
092: return null;
093: }
094: }
095:
096: /**
097: * Invoke a method.
098: */
099: public Object invoke(Invocation invocation) throws Exception {
100: ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader();
101:
102: ObjectName mbean = (ObjectName) Registry
103: .lookup((Integer) invocation.getObjectName());
104: try {
105: Object[] args = { invocation };
106: Object rtnValue = serverAction.invoke(mbean, "invoke",
107: args, Invocation.INVOKE_SIGNATURE);
108: return rtnValue;
109: } catch (Exception e) {
110: e = (Exception) JMXExceptionDecoder.decode(e);
111: if (log.isTraceEnabled())
112: log.trace("Failed to invoke on mbean: " + mbean, e);
113: throw e;
114: } finally {
115: TCLAction.UTIL.setContextClassLoader(oldCl);
116: }
117: }
118:
119: /** Perform the MBeanServer.invoke op in a PrivilegedExceptionAction if
120: * running with a security manager.
121: */
122: class MBeanServerAction implements PrivilegedExceptionAction {
123: private ObjectName target;
124: String method;
125: Object[] args;
126: String[] sig;
127:
128: MBeanServerAction() {
129: }
130:
131: MBeanServerAction(ObjectName target, String method,
132: Object[] args, String[] sig) {
133: this .target = target;
134: this .method = method;
135: this .args = args;
136: this .sig = sig;
137: }
138:
139: public Object run() throws Exception {
140: Object rtnValue = server.invoke(target, method, args, sig);
141: return rtnValue;
142: }
143:
144: Object invoke(ObjectName target, String method, Object[] args,
145: String[] sig) throws Exception {
146: SecurityManager sm = System.getSecurityManager();
147: Object rtnValue = null;
148: if (sm == null) {
149: // Direct invocation on MBeanServer
150: rtnValue = server.invoke(target, method, args, sig);
151: } else {
152: try {
153: // Encapsulate the invocation in a PrivilegedExceptionAction
154: MBeanServerAction action = new MBeanServerAction(
155: target, method, args, sig);
156: rtnValue = AccessController.doPrivileged(action);
157: } catch (PrivilegedActionException e) {
158: Exception ex = e.getException();
159: throw ex;
160: }
161: }
162: return rtnValue;
163: }
164: }
165:
166: interface TCLAction {
167: class UTIL {
168: static TCLAction getTCLAction() {
169: return System.getSecurityManager() == null ? NON_PRIVILEGED
170: : PRIVILEGED;
171: }
172:
173: static ClassLoader getContextClassLoader() {
174: return getTCLAction().getContextClassLoader();
175: }
176:
177: static ClassLoader getContextClassLoader(Thread thread) {
178: return getTCLAction().getContextClassLoader(thread);
179: }
180:
181: static void setContextClassLoader(ClassLoader cl) {
182: getTCLAction().setContextClassLoader(cl);
183: }
184:
185: static void setContextClassLoader(Thread thread,
186: ClassLoader cl) {
187: getTCLAction().setContextClassLoader(thread, cl);
188: }
189: }
190:
191: TCLAction NON_PRIVILEGED = new TCLAction() {
192: public ClassLoader getContextClassLoader() {
193: return Thread.currentThread().getContextClassLoader();
194: }
195:
196: public ClassLoader getContextClassLoader(Thread thread) {
197: return thread.getContextClassLoader();
198: }
199:
200: public void setContextClassLoader(ClassLoader cl) {
201: Thread.currentThread().setContextClassLoader(cl);
202: }
203:
204: public void setContextClassLoader(Thread thread,
205: ClassLoader cl) {
206: thread.setContextClassLoader(cl);
207: }
208: };
209:
210: TCLAction PRIVILEGED = new TCLAction() {
211: private final PrivilegedAction getTCLPrivilegedAction = new PrivilegedAction() {
212: public Object run() {
213: return Thread.currentThread()
214: .getContextClassLoader();
215: }
216: };
217:
218: public ClassLoader getContextClassLoader() {
219: return (ClassLoader) AccessController
220: .doPrivileged(getTCLPrivilegedAction);
221: }
222:
223: public ClassLoader getContextClassLoader(final Thread thread) {
224: return (ClassLoader) AccessController
225: .doPrivileged(new PrivilegedAction() {
226: public Object run() {
227: return thread.getContextClassLoader();
228: }
229: });
230: }
231:
232: public void setContextClassLoader(final ClassLoader cl) {
233: AccessController.doPrivileged(new PrivilegedAction() {
234: public Object run() {
235: Thread.currentThread()
236: .setContextClassLoader(cl);
237: return null;
238: }
239: });
240: }
241:
242: public void setContextClassLoader(final Thread thread,
243: final ClassLoader cl) {
244: AccessController.doPrivileged(new PrivilegedAction() {
245: public Object run() {
246: thread.setContextClassLoader(cl);
247: return null;
248: }
249: });
250: }
251: };
252:
253: ClassLoader getContextClassLoader();
254:
255: ClassLoader getContextClassLoader(Thread thread);
256:
257: void setContextClassLoader(ClassLoader cl);
258:
259: void setContextClassLoader(Thread thread, ClassLoader cl);
260: }
261: }
|