0001: /*
0002: * JBoss, Home of Professional Open Source.
0003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
0004: * as indicated by the @author tags. See the copyright.txt file in the
0005: * distribution for a full listing of individual contributors.
0006: *
0007: * This is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU Lesser General Public License as
0009: * published by the Free Software Foundation; either version 2.1 of
0010: * the License, or (at your option) any later version.
0011: *
0012: * This software is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this software; if not, write to the Free
0019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
0021: */
0022: package org.jboss.ejb;
0023:
0024: // $Id: Container.java 61864 2007-03-29 20:01:13Z thomas.diesler@jboss.com $
0025:
0026: import java.lang.reflect.InvocationTargetException;
0027: import java.lang.reflect.Method;
0028: import java.net.URL;
0029: import java.rmi.MarshalException;
0030: import java.security.AccessController;
0031: import java.security.Policy;
0032: import java.security.PrivilegedActionException;
0033: import java.security.PrivilegedExceptionAction;
0034: import java.util.HashMap;
0035: import java.util.HashSet;
0036: import java.util.Iterator;
0037: import java.util.Map;
0038: import java.util.Set;
0039:
0040: import javax.ejb.EJBException;
0041: import javax.ejb.EJBObject;
0042: import javax.ejb.TimedObject;
0043: import javax.ejb.Timer;
0044: import javax.ejb.TimerService;
0045: import javax.ejb.spi.HandleDelegate;
0046: import javax.management.MBeanException;
0047: import javax.management.MalformedObjectNameException;
0048: import javax.management.ObjectName;
0049: import javax.naming.Context;
0050: import javax.naming.InitialContext;
0051: import javax.naming.LinkRef;
0052: import javax.naming.NamingException;
0053: import javax.naming.Reference;
0054: import javax.naming.StringRefAddr;
0055: import javax.transaction.TransactionManager;
0056: import javax.xml.soap.SOAPMessage;
0057:
0058: import org.jboss.deployment.DeploymentException;
0059: import org.jboss.deployment.DeploymentInfo;
0060: import org.jboss.ejb.plugins.local.BaseLocalProxyFactory;
0061: import org.jboss.ejb.txtimer.EJBTimerService;
0062: import org.jboss.invocation.Invocation;
0063: import org.jboss.invocation.InvocationKey;
0064: import org.jboss.invocation.InvocationStatistics;
0065: import org.jboss.invocation.InvocationType;
0066: import org.jboss.invocation.JBossLazyUnmarshallingException;
0067: import org.jboss.invocation.MarshalledInvocation;
0068: import org.jboss.logging.Logger;
0069: import org.jboss.metadata.ApplicationMetaData;
0070: import org.jboss.metadata.BeanMetaData;
0071: import org.jboss.metadata.EjbLocalRefMetaData;
0072: import org.jboss.metadata.EjbRefMetaData;
0073: import org.jboss.metadata.EnvEntryMetaData;
0074: import org.jboss.metadata.MessageDestinationMetaData;
0075: import org.jboss.metadata.MessageDestinationRefMetaData;
0076: import org.jboss.metadata.ResourceEnvRefMetaData;
0077: import org.jboss.metadata.ResourceRefMetaData;
0078: import org.jboss.metadata.serviceref.ServiceRefDelegate;
0079: import org.jboss.mx.util.ObjectNameConverter;
0080: import org.jboss.mx.util.ObjectNameFactory;
0081: import org.jboss.security.AnybodyPrincipal;
0082: import org.jboss.security.AuthenticationManager;
0083: import org.jboss.security.RealmMapping;
0084: import org.jboss.system.ServiceMBeanSupport;
0085: import org.jboss.util.NestedError;
0086: import org.jboss.util.NestedRuntimeException;
0087: import org.jboss.util.naming.ENCThreadLocalKey;
0088: import org.jboss.util.naming.NonSerializableFactory;
0089: import org.jboss.util.naming.Util;
0090: import org.jboss.ws.integration.ServiceRefMetaData;
0091: import org.jboss.ws.integration.URLLoaderAdapter;
0092: import org.jboss.ws.integration.UnifiedVirtualFile;
0093: import org.omg.CORBA.ORB;
0094:
0095: /**
0096: * This is the base class for all EJB-containers in JBoss. A Container
0097: * functions as the central hub of all metadata and plugins. Through this
0098: * the container plugins can get hold of the other plugins and any metadata
0099: * they need.
0100: *
0101: * <p>The EJBDeployer creates instances of subclasses of this class
0102: * and calls the appropriate initialization methods.
0103: *
0104: * <p>A Container does not perform any significant work, but instead delegates
0105: * to the plugins to provide for all kinds of algorithmic functionality.
0106: *
0107: * @see EJBDeployer
0108: *
0109: * @author <a href="mailto:rickard.oberg@jboss.org">Rickard �berg</a>
0110: * @author <a href="mailto:marc.fleury@jboss.org">Marc Fleury</a>
0111: * @author <a href="mailto:Scott.Stark@jboss.org">Scott Stark</a>.
0112: * @author <a href="bill@burkecentral.com">Bill Burke</a>
0113: * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
0114: * @author <a href="mailto:christoph.jung@infor.de">Christoph G. Jung</a>
0115: * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
0116: * @version $Revision: 61864 $
0117: *
0118: * @jmx.mbean extends="org.jboss.system.ServiceMBean"
0119: */
0120: public abstract class Container extends ServiceMBeanSupport implements
0121: ContainerMBean, AllowedOperationsFlags {
0122: public final static String BASE_EJB_CONTAINER_NAME = "jboss.j2ee:service=EJB";
0123:
0124: public final static ObjectName ORB_NAME = ObjectNameFactory
0125: .create("jboss:service=CorbaORB");
0126:
0127: public final static ObjectName EJB_CONTAINER_QUERY_NAME = ObjectNameFactory
0128: .create(BASE_EJB_CONTAINER_NAME + ",*");
0129:
0130: protected static final Method EJBOBJECT_REMOVE;
0131: /** A reference to {@link javax.ejb.TimedObject#ejbTimeout}. */
0132: protected static final Method EJB_TIMEOUT;
0133:
0134: /** This is the application that this container is a part of */
0135: protected EjbModule ejbModule;
0136:
0137: /**
0138: * This is the local classloader of this container. Used for loading
0139: * resources that must come from the local jar file for the container.
0140: * NOT for loading classes!
0141: */
0142: protected ClassLoader localClassLoader;
0143:
0144: /**
0145: * This is the classloader of this container. All classes and resources that
0146: * the bean uses will be loaded from here. By doing this we make the bean
0147: * re-deployable
0148: */
0149: protected ClassLoader classLoader;
0150:
0151: /** The class loader for remote dynamic classloading */
0152: protected ClassLoader webClassLoader;
0153:
0154: /**
0155: * Externally supplied configuration data
0156: */
0157: private DeploymentInfo di;
0158:
0159: /**
0160: * This is the new metadata. it includes information from both ejb-jar and
0161: * jboss.xml the metadata for the application can be accessed trough
0162: * metaData.getApplicationMetaData()
0163: */
0164: protected BeanMetaData metaData;
0165:
0166: /** This is the EnterpriseBean class */
0167: protected Class beanClass;
0168:
0169: /** This is the Home interface class */
0170: protected Class homeInterface;
0171:
0172: /** This is the Remote interface class */
0173: protected Class remoteInterface;
0174:
0175: /** The local home interface class */
0176: protected Class localHomeInterface;
0177:
0178: /** The local inteface class */
0179: protected Class localInterface;
0180:
0181: /** This is the TransactionManager */
0182: protected TransactionManager tm;
0183:
0184: /** This is the SecurityManager */
0185: protected AuthenticationManager sm;
0186:
0187: /** This is the realm mapping */
0188: protected RealmMapping rm;
0189:
0190: /** The custom security proxy used by the SecurityInterceptor */
0191: protected Object securityProxy;
0192:
0193: /** This is the bean lock manager that is to be used */
0194: protected BeanLockManager lockManager;
0195:
0196: /** ??? */
0197: protected LocalProxyFactory localProxyFactory = new BaseLocalProxyFactory();
0198:
0199: /** This is a cache for method permissions */
0200: private HashMap methodPermissionsCache = new HashMap();
0201:
0202: /** Maps for MarshalledInvocation mapping */
0203: protected Map marshalledInvocationMapping = new HashMap();
0204:
0205: /** ObjectName of Container */
0206: private ObjectName jmxName;
0207: /** HashMap<String, EJBProxyFactory> for the invoker bindings */
0208: protected HashMap proxyFactories = new HashMap();
0209: /** A priviledged actions for MBeanServer.invoke when running with sec mgr */
0210: private MBeanServerAction serverAction = new MBeanServerAction();
0211:
0212: /**
0213: * The Proxy factory is set in the Invocation. This TL is used
0214: * for methods that do not have access to the Invocation.
0215: */
0216: protected ThreadLocal proxyFactoryTL = new ThreadLocal();
0217:
0218: /** The number of create invocations that have been made */
0219: protected long createCount;
0220: /** The number of create invocations that have been made */
0221: protected long removeCount;
0222: /** Time statistics for the invoke(Invocation) methods */
0223: protected InvocationStatistics invokeStats = new InvocationStatistics();
0224:
0225: /** The JACC context id for the container */
0226: protected String jaccContextID;
0227:
0228: /**
0229: * Flag to denote whether a JACC configuration has been fitted for authorization
0230: */
0231: protected boolean isJaccEnabled = false;
0232:
0233: static {
0234: try {
0235: EJBOBJECT_REMOVE = EJBObject.class.getMethod("remove",
0236: new Class[0]);
0237: EJB_TIMEOUT = TimedObject.class.getMethod("ejbTimeout",
0238: new Class[] { Timer.class });
0239: } catch (Throwable t) {
0240: throw new NestedRuntimeException(t);
0241: }
0242: }
0243:
0244: // Public --------------------------------------------------------
0245:
0246: public Class getLocalClass() {
0247: return localInterface;
0248: }
0249:
0250: public Class getLocalHomeClass() {
0251: return localHomeInterface;
0252: }
0253:
0254: public Class getRemoteClass() {
0255: return remoteInterface;
0256: }
0257:
0258: /**
0259: * this actually should be called remotehome, but for interface compliance purposes
0260: * we keep it like that
0261: */
0262: public Class getHomeClass() {
0263: return homeInterface;
0264: }
0265:
0266: /**
0267: * Whether the bean is call by value
0268: *
0269: * @return true for call by value
0270: */
0271: public boolean isCallByValue() {
0272: if (ejbModule.isCallByValue())
0273: return true;
0274: return metaData.isCallByValue();
0275: }
0276:
0277: /**
0278: * Sets a transaction manager for this container.
0279: *
0280: * @see javax.transaction.TransactionManager
0281: *
0282: * @param tm
0283: */
0284: public void setTransactionManager(final TransactionManager tm) {
0285: this .tm = tm;
0286: }
0287:
0288: /**
0289: * Returns this container's transaction manager.
0290: *
0291: * @return A concrete instance of javax.transaction.TransactionManager
0292: */
0293: public TransactionManager getTransactionManager() {
0294: return tm;
0295: }
0296:
0297: public void setSecurityManager(AuthenticationManager sm) {
0298: this .sm = sm;
0299: }
0300:
0301: public AuthenticationManager getSecurityManager() {
0302: return sm;
0303: }
0304:
0305: public BeanLockManager getLockManager() {
0306: return lockManager;
0307: }
0308:
0309: public void setLockManager(final BeanLockManager lockManager) {
0310: this .lockManager = lockManager;
0311: lockManager.setContainer(this );
0312: }
0313:
0314: public void addProxyFactory(String invokerBinding,
0315: EJBProxyFactory factory) {
0316: proxyFactories.put(invokerBinding, factory);
0317: }
0318:
0319: public void setRealmMapping(final RealmMapping rm) {
0320: this .rm = rm;
0321: }
0322:
0323: public RealmMapping getRealmMapping() {
0324: return rm;
0325: }
0326:
0327: public void setSecurityProxy(Object proxy) {
0328: this .securityProxy = proxy;
0329: }
0330:
0331: public Object getSecurityProxy() {
0332: return securityProxy;
0333: }
0334:
0335: public EJBProxyFactory getProxyFactory() {
0336: EJBProxyFactory factory = (EJBProxyFactory) proxyFactoryTL
0337: .get();
0338: // There's no factory thread local which means this is probably
0339: // a local invocation. Just use the first (usually only)
0340: // proxy factory.
0341: // TODO: define a default factory in the meta data or
0342: // even better, let the return over the original transport
0343: // plugin the transport layer for the generated proxy
0344: if (factory == null && remoteInterface != null) {
0345: Iterator i = proxyFactories.values().iterator();
0346: if (i.hasNext())
0347: factory = (EJBProxyFactory) i.next();
0348: }
0349: return factory;
0350: }
0351:
0352: public void setProxyFactory(Object factory) {
0353: proxyFactoryTL.set(factory);
0354: }
0355:
0356: public EJBProxyFactory lookupProxyFactory(String binding) {
0357: return (EJBProxyFactory) proxyFactories.get(binding);
0358: }
0359:
0360: /**
0361: * Gets the DeploymentInfo for this Container
0362: *
0363: * @return The DeploymentInfo for this Container
0364: */
0365: public final DeploymentInfo getDeploymentInfo() {
0366: return di;
0367: }
0368:
0369: /**
0370: * Sets the DeploymentInfo of this Container
0371: *
0372: * @param di The new DeploymentInfo to be used
0373: */
0374: public final void setDeploymentInfo(DeploymentInfo di) {
0375: this .di = di;
0376: }
0377:
0378: /**
0379: * Sets the application deployment unit for this container. All the bean
0380: * containers within the same application unit share the same instance.
0381: *
0382: * @param app application for this container
0383: */
0384: public void setEjbModule(EjbModule app) {
0385: ejbModule = app;
0386: }
0387:
0388: public String getJaccContextID() {
0389: return jaccContextID;
0390: }
0391:
0392: public void setJaccContextID(String id) {
0393: jaccContextID = id;
0394: }
0395:
0396: /**
0397: * Get the flag whether JACC is enabled
0398: * @return
0399: */
0400: public boolean isJaccEnabled() {
0401: return isJaccEnabled;
0402: }
0403:
0404: /**
0405: * Set the flag that JACC is enabled
0406: *
0407: * @param isJaccEnabled
0408: */
0409: public void setJaccEnabled(boolean isJaccEnabled) {
0410: this .isJaccEnabled = isJaccEnabled;
0411: }
0412:
0413: /**
0414: * Gets the application deployment unit for this container. All the bean
0415: * containers within the same application unit share the same instance.
0416: * @jmx.managed-attribute
0417: */
0418: public EjbModule getEjbModule() {
0419: return ejbModule;
0420: }
0421:
0422: /**
0423: * Gets the number of create invocations that have been made
0424: * @jmx.managed-attribute
0425: */
0426: public long getCreateCount() {
0427: return createCount;
0428: }
0429:
0430: /**
0431: * Gets the number of remove invocations that have been made
0432: * @jmx.managed-attribute
0433: */
0434: public long getRemoveCount() {
0435: return removeCount;
0436: }
0437:
0438: /** Gets the invocation statistics collection
0439: * @jmx.managed-attribute
0440: */
0441: public InvocationStatistics getInvokeStats() {
0442: return invokeStats;
0443: }
0444:
0445: /**
0446: * Sets the local class loader for this container.
0447: * Used for loading resources from the local jar file for this container.
0448: * NOT for loading classes!
0449: *
0450: * @param cl
0451: */
0452: public void setLocalClassLoader(ClassLoader cl) {
0453: this .localClassLoader = cl;
0454: }
0455:
0456: /**
0457: * Returns the local classloader for this container.
0458: *
0459: * @return The local classloader for this container.
0460: */
0461: public ClassLoader getLocalClassLoader() {
0462: return localClassLoader;
0463: }
0464:
0465: /**
0466: * Sets the class loader for this container. All the classes and resources
0467: * used by the bean in this container will use this classloader.
0468: *
0469: * @param cl
0470: */
0471: public void setClassLoader(ClassLoader cl) {
0472: this .classLoader = cl;
0473: }
0474:
0475: /**
0476: * Returns the classloader for this container.
0477: *
0478: * @return
0479: */
0480: public ClassLoader getClassLoader() {
0481: return classLoader;
0482: }
0483:
0484: /** Get the class loader for dynamic class loading via http.
0485: */
0486: public ClassLoader getWebClassLoader() {
0487: return webClassLoader;
0488: }
0489:
0490: /** Set the class loader for dynamic class loading via http.
0491: */
0492: public void setWebClassLoader(final ClassLoader webClassLoader) {
0493: this .webClassLoader = webClassLoader;
0494: }
0495:
0496: /**
0497: * Sets the meta data for this container. The meta data consists of the
0498: * properties found in the XML descriptors.
0499: *
0500: * @param metaData
0501: */
0502: public void setBeanMetaData(final BeanMetaData metaData) {
0503: this .metaData = metaData;
0504: }
0505:
0506: /** Get the components environment context
0507: * @jmx.managed-attribute
0508: * @return Environment Context
0509: */
0510: public Context getEnvContext() throws NamingException {
0511: ClassLoader ccl = SecurityActions.getContextClassLoader();
0512: try {
0513: // The ENC is a map keyed on the class loader
0514: SecurityActions.setContextClassLoader(classLoader);
0515: return (Context) new InitialContext()
0516: .lookup("java:comp/env");
0517: } finally {
0518: SecurityActions.setContextClassLoader(ccl);
0519: }
0520: }
0521:
0522: /**
0523: * Returns the metadata of this container.
0524: *
0525: * @jmx.managed-attribute
0526: * @return metaData;
0527: */
0528: public BeanMetaData getBeanMetaData() {
0529: return metaData;
0530: }
0531:
0532: /**
0533: * Returns the permissions for a method. (a set of roles)
0534: *
0535: * @return assemblyDescriptor;
0536: */
0537: public Set getMethodPermissions(Method m, InvocationType iface) {
0538: Set permissions;
0539:
0540: if (methodPermissionsCache.containsKey(m)) {
0541: permissions = (Set) methodPermissionsCache.get(m);
0542: } else if (m.equals(EJB_TIMEOUT)) {
0543: // No role is required to access the ejbTimeout as this is
0544: permissions = new HashSet();
0545: permissions.add(AnybodyPrincipal.ANYBODY_PRINCIPAL);
0546: methodPermissionsCache.put(m, permissions);
0547: } else {
0548: String name = m.getName();
0549: Class[] sig = m.getParameterTypes();
0550: permissions = getBeanMetaData().getMethodPermissions(name,
0551: sig, iface);
0552: methodPermissionsCache.put(m, permissions);
0553: }
0554:
0555: return permissions;
0556: }
0557:
0558: /**
0559: * Returns the bean class instance of this container.
0560: *
0561: * @return instance of the Enterprise bean class.
0562: */
0563: public Class getBeanClass() {
0564: return beanClass;
0565: }
0566:
0567: /**
0568: * Returns a new instance of the bean class or a subclass of the bean class.
0569: * This factory style method is speciffically used by a container to supply
0570: * an implementation of the abstract accessors in EJB2.0, but could be
0571: * usefull in other situations. This method should ALWAYS be used instead
0572: * of getBeanClass().newInstance();
0573: *
0574: * @return the new instance
0575: *
0576: * @see java.lang.Class#newInstance
0577: */
0578: public Object createBeanClassInstance() throws Exception {
0579: return getBeanClass().newInstance();
0580: }
0581:
0582: /**
0583: * Sets the codebase of this container.
0584: *
0585: * @param codebase a possibly empty, but non null String with
0586: * a sequence of URLs separated by spaces
0587: * /
0588: public void setCodebase(final String codebase)
0589: {
0590: if (codebase != null)
0591: this.codebase = codebase;
0592: }
0593: */
0594: /**
0595: * Gets the codebase of this container.
0596: *
0597: * @return this container's codebase String, a sequence of URLs
0598: * separated by spaces
0599: * /
0600: public String getCodebase()
0601: {
0602: return codebase;
0603: }
0604: */
0605: /** Build a JMX name using the pattern jboss.j2ee:service=EJB,jndiName=[jndiName]
0606: where the [jndiName] is either the bean remote home JNDI binding, or
0607: the local home JNDI binding if the bean has no remote interfaces.
0608: */
0609: public ObjectName getJmxName() {
0610: if (jmxName == null) {
0611: BeanMetaData beanMetaData = getBeanMetaData();
0612: if (beanMetaData == null) {
0613: throw new IllegalStateException(
0614: "Container metaData is null");
0615: }
0616:
0617: String jndiName = beanMetaData
0618: .getContainerObjectNameJndiName();
0619: if (jndiName == null) {
0620: throw new IllegalStateException(
0621: "Container jndiName is null");
0622: }
0623:
0624: // The name must be escaped since the jndiName may be arbitrary
0625: String name = BASE_EJB_CONTAINER_NAME + ",jndiName="
0626: + jndiName;
0627: try {
0628: jmxName = ObjectNameConverter.convert(name);
0629: } catch (MalformedObjectNameException e) {
0630: throw new RuntimeException(
0631: "Failed to create ObjectName, msg="
0632: + e.getMessage());
0633: }
0634: }
0635: return jmxName;
0636: }
0637:
0638: /**
0639: * Creates the single Timer Service for this container if not already created
0640: *
0641: * @param pKey Bean id
0642: * @return Container Timer Service
0643: * @throws IllegalStateException If the type of EJB is not allowed to use the
0644: * timer service, or the bean class does not implement javax.ejb.TimedObject
0645: *
0646: * @see javax.ejb.EJBContext#getTimerService
0647: *
0648: * @jmx.managed-operation
0649: **/
0650: public TimerService getTimerService(Object pKey)
0651: throws IllegalStateException {
0652: if (this instanceof StatefulSessionContainer)
0653: throw new IllegalStateException(
0654: "Statefull Session Beans are not allowed to access the TimerService");
0655:
0656: // Validate that the bean implements the TimedObject interface
0657: Class beanClass = this .getBeanClass();
0658: if (TimedObject.class.isAssignableFrom(beanClass) == false) {
0659: String msg = this .getBeanMetaData().getEjbName()
0660: + " requested getTimerService but " + beanClass
0661: + " does not implement javax.ejb.TimedObject";
0662: throw new IllegalStateException(msg);
0663: }
0664:
0665: TimerService timerService = null;
0666: try {
0667: EJBTimerService service = (EJBTimerService) SecurityActions
0668: .getMBeanProxy(EJBTimerService.class,
0669: EJBTimerService.OBJECT_NAME, server);
0670: timerService = service.createTimerService(getJmxName(),
0671: pKey, this );
0672: } catch (Exception e) {
0673: throw new EJBException("Could not create timer service", e);
0674: }
0675: return timerService;
0676: }
0677:
0678: /**
0679: * Removes Timer Service for this container
0680: *
0681: * @param pKey Bean id
0682: * @throws IllegalStateException If the type of EJB is not allowed to use the timer service
0683: *
0684: * @jmx.managed-operation
0685: **/
0686: public void removeTimerService(Object pKey)
0687: throws IllegalStateException {
0688: try {
0689: EJBTimerService service = (EJBTimerService) SecurityActions
0690: .getMBeanProxy(EJBTimerService.class,
0691: EJBTimerService.OBJECT_NAME, server);
0692: if (pKey != null) {
0693: // entity bean->remove()
0694: service.removeTimerService(getJmxName(), pKey);
0695: } else {
0696: // container stop, we choose whether active timers
0697: // should be persisted (default), or not (legacy)
0698: service.removeTimerService(getJmxName(),
0699: getBeanMetaData().getTimerPersistence());
0700: }
0701: } catch (Exception e) {
0702: log.error("Could not remove timer service", e);
0703: }
0704: }
0705:
0706: /**
0707: * Restore any timers previously persisted for this container
0708: */
0709: protected void restoreTimers() {
0710: try {
0711: // pass to the ejb timer service the container ObjectName
0712: server
0713: .invoke(EJBTimerService.OBJECT_NAME,
0714: "restoreTimers",
0715: new Object[] { getServiceName(),
0716: getClassLoader() }, new String[] {
0717: "javax.management.ObjectName",
0718: "java.lang.ClassLoader" });
0719: } catch (Exception e) {
0720: log.warn("Could not restore ejb timers", e);
0721: }
0722: }
0723:
0724: /**
0725: * The EJBDeployer calls this method. The EJBDeployer has set
0726: * all the plugins and interceptors that this bean requires and now proceeds
0727: * to initialize the chain. The method looks for the standard classes in
0728: * the URL, sets up the naming environment of the bean. The concrete
0729: * container classes should override this method to introduce
0730: * implementation specific initialization behaviour.
0731: *
0732: * @throws Exception if loading the bean class failed
0733: * (ClassNotFoundException) or setting up "java:"
0734: * naming environment failed (DeploymentException)
0735: */
0736: protected void createService() throws Exception {
0737: // Acquire classes from CL
0738: beanClass = classLoader.loadClass(metaData.getEjbClass());
0739:
0740: if (metaData.getLocalHome() != null)
0741: localHomeInterface = classLoader.loadClass(metaData
0742: .getLocalHome());
0743: if (metaData.getLocal() != null)
0744: localInterface = classLoader.loadClass(metaData.getLocal());
0745:
0746: localProxyFactory.setContainer(this );
0747: localProxyFactory.create();
0748: if (localHomeInterface != null)
0749: ejbModule.addLocalHome(this , localProxyFactory
0750: .getEJBLocalHome());
0751: ejbModule.createMissingPermissions(this , metaData);
0752: // Allow the policy to incorporate the policy configs
0753: Policy.getPolicy().refresh();
0754: }
0755:
0756: /**
0757: * A default implementation of starting the container service.
0758: * The container registers it's dynamic MBean interface in the JMX base.
0759: *
0760: * The concrete container classes should override this method to introduce
0761: * implementation specific start behaviour.
0762: *
0763: * todo implement the service lifecycle methods in an xmbean interceptor so
0764: * non lifecycle managed ops are blocked when mbean is not started.
0765: *
0766: * @throws Exception An exception that occured during start
0767: */
0768: protected void startService() throws Exception {
0769: // Setup "java:comp/env" namespace
0770: setupEnvironment();
0771:
0772: localProxyFactory.start();
0773: }
0774:
0775: /**
0776: * A default implementation of stopping the container service (no-op). The
0777: * concrete container classes should override this method to introduce
0778: * implementation specific stop behaviour.
0779: */
0780: protected void stopService() throws Exception {
0781: localProxyFactory.stop();
0782: removeTimerService(null);
0783: teardownEnvironment();
0784: }
0785:
0786: /**
0787: * A default implementation of destroying the container service (no-op).
0788: * The concrete container classes should override this method to introduce
0789: * implementation specific destroy behaviour.
0790: */
0791: protected void destroyService() throws Exception {
0792: localProxyFactory.destroy();
0793: ejbModule.removeLocalHome(this );
0794:
0795: beanClass = null;
0796: homeInterface = null;
0797: remoteInterface = null;
0798: localHomeInterface = null;
0799: localInterface = null;
0800: methodPermissionsCache.clear();
0801: // InvocationStatistics holds refs to Methods from
0802: // application classes, so to avoid a classloader
0803: // leak, lets not just resetStats() but also replace
0804: // the object
0805: invokeStats.resetStats(); // in case someone else has a ref
0806: invokeStats = new InvocationStatistics();
0807: marshalledInvocationMapping.clear();
0808: }
0809:
0810: /**
0811: * This method is called when a method call comes
0812: * in on the Home object. The Container forwards this call to the
0813: * interceptor chain for further processing.
0814: *
0815: * @param mi the object holding all info about this invocation
0816: * @return the result of the home invocation
0817: *
0818: * @throws Exception
0819: */
0820: public abstract Object internalInvokeHome(Invocation mi)
0821: throws Exception;
0822:
0823: /**
0824: * This method is called when a method call comes
0825: * in on an EJBObject. The Container forwards this call to the interceptor
0826: * chain for further processing.
0827: */
0828: public abstract Object internalInvoke(Invocation mi)
0829: throws Exception;
0830:
0831: abstract Interceptor createContainerInterceptor();
0832:
0833: public abstract void addInterceptor(Interceptor in);
0834:
0835: /** The detached invoker operation.
0836: *
0837: * @jmx.managed-operation
0838: *
0839: * @param mi - the method invocation context
0840: * @return the value of the ejb invocation
0841: * @throws Exception on error
0842: */
0843: public Object invoke(Invocation mi) throws Exception {
0844: ClassLoader callerClassLoader = SecurityActions
0845: .getContextClassLoader();
0846: long start = System.currentTimeMillis();
0847: Method m = null;
0848:
0849: Object type = null;
0850: String contextID = getJaccContextID();
0851: try {
0852: // JBAS-3732 - Remove classloader.equals optimization
0853: SecurityActions.setContextClassLoader(this .classLoader);
0854:
0855: // Set the JACC context id
0856: mi.setValue(InvocationKey.JACC_CONTEXT_ID, contextID);
0857: contextID = SecurityActions.setContextID(contextID);
0858: // Set the standard JACC policy context handler data is not a SEI msg
0859: if (mi.getType() != InvocationType.SERVICE_ENDPOINT) {
0860: EJBArgsPolicyContextHandler.setArgs(mi.getArguments());
0861: } else {
0862: SOAPMessage msg = (SOAPMessage) mi
0863: .getValue(InvocationKey.SOAP_MESSAGE);
0864: SOAPMsgPolicyContextHandler.setMessage(msg);
0865: }
0866: // Set custom JACC policy handlers
0867: BeanMetaDataPolicyContextHandler.setMetaData(this
0868: .getBeanMetaData());
0869:
0870: // Check against home, remote, localHome, local, getHome,
0871: // getRemote, getLocalHome, getLocal
0872: type = mi.getType();
0873:
0874: // stat gathering: concurrent calls
0875: this .invokeStats.callIn();
0876:
0877: if (type == InvocationType.REMOTE
0878: || type == InvocationType.LOCAL ||
0879: // web service calls come in as "ordinary" application invocations
0880: type == InvocationType.SERVICE_ENDPOINT) {
0881: if (mi instanceof MarshalledInvocation) {
0882: ((MarshalledInvocation) mi)
0883: .setMethodMap(marshalledInvocationMapping);
0884:
0885: if (log.isTraceEnabled()) {
0886: log.trace("METHOD REMOTE INVOKE "
0887: + mi.getObjectName() + "||"
0888: + mi.getMethod().getName() + "||");
0889: }
0890: }
0891:
0892: m = mi.getMethod();
0893:
0894: Object obj = internalInvoke(mi);
0895: return obj;
0896: } else if (type == InvocationType.HOME
0897: || type == InvocationType.LOCALHOME) {
0898: if (mi instanceof MarshalledInvocation) {
0899:
0900: ((MarshalledInvocation) mi)
0901: .setMethodMap(marshalledInvocationMapping);
0902:
0903: if (log.isTraceEnabled()) {
0904: log.trace("METHOD HOME INVOKE "
0905: + mi.getObjectName() + "||"
0906: + mi.getMethod().getName() + "||"
0907: + mi.getArguments().toString());
0908: }
0909: }
0910: m = mi.getMethod();
0911:
0912: Object obj = internalInvokeHome(mi);
0913: return obj;
0914: } else {
0915: throw new MBeanException(new IllegalArgumentException(
0916: "Unknown invocation type: " + type));
0917: }
0918: }
0919: /**
0920: * Having to catch this exception here in case can not
0921: * unmarshall arguments, values, etc. Then, convert to
0922: * UnmarshalException as defined by spec (JBAS-2999)
0923: */
0924: catch (JBossLazyUnmarshallingException e) {
0925: InvocationType calltype = mi.getType();
0926: boolean isLocal = calltype == InvocationType.LOCAL
0927: || calltype == InvocationType.LOCALHOME;
0928:
0929: // handle unmarshalling exception which should only come if problem unmarshalling
0930: // invocation payload, arguments, or value on remote end.
0931: if (isLocal) {
0932: throw new EJBException("UnmarshalException", e);
0933: } else {
0934: throw new MarshalException("MarshalException", e);
0935: }
0936: } finally {
0937: if (m != null) {
0938: long end = System.currentTimeMillis();
0939: long elapsed = end - start;
0940: this .invokeStats.updateStats(m, elapsed);
0941: }
0942:
0943: // stat gathering: concurrent calls
0944: this .invokeStats.callOut();
0945:
0946: // Restore the incoming class loader
0947: SecurityActions.setContextClassLoader(callerClassLoader);
0948:
0949: // Restore the incoming context id
0950: contextID = SecurityActions.setContextID(contextID);
0951:
0952: if (mi.getType() == InvocationType.SERVICE_ENDPOINT) {
0953: // Remove msg from ThreadLocal to prevent leakage into the thread pool
0954: SOAPMsgPolicyContextHandler.setMessage(null);
0955: } else {
0956: // Remove args from ThreadLocal to prevent leakage into the thread pool
0957: EJBArgsPolicyContextHandler.setArgs(null);
0958: }
0959:
0960: // Remove metadata from ThreadLocal to prevent leakage into the thread pool
0961: BeanMetaDataPolicyContextHandler.setMetaData(null);
0962: }
0963: }
0964:
0965: // Private -------------------------------------------------------
0966:
0967: /**
0968: * This method sets up the naming environment of the bean.
0969: * We create the java:comp/env namespace with properties, EJB-References,
0970: * and DataSource ressources.
0971: */
0972: private void setupEnvironment() throws Exception {
0973: BeanMetaData beanMetaData = getBeanMetaData();
0974: // debug
0975: log.debug("Begin java:comp/env for EJB: "
0976: + beanMetaData.getEjbName());
0977: ClassLoader tcl = SecurityActions.getContextClassLoader();
0978: log.debug("TCL: " + tcl);
0979:
0980: ORB orb = null;
0981: HandleDelegate hd = null;
0982: try {
0983: orb = (ORB) server.getAttribute(ORB_NAME, "ORB");
0984: hd = (HandleDelegate) server.getAttribute(ORB_NAME,
0985: "HandleDelegate");
0986: } catch (Throwable t) {
0987: log.debug("Unable to retrieve orb" + t.toString());
0988: }
0989:
0990: // Since the BCL is already associated with this thread we can start
0991: // using the java: namespace directly
0992: Context ctx = (Context) new InitialContext()
0993: .lookup("java:comp");
0994:
0995: // Bind the orb
0996: if (orb != null) {
0997: NonSerializableFactory.rebind(ctx, "ORB", orb);
0998: log.debug("Bound java:comp/ORB for EJB: "
0999: + getBeanMetaData().getEjbName());
1000:
1001: NonSerializableFactory.rebind(ctx, "HandleDelegate", hd);
1002: log.debug("Bound java:comp:/HandleDelegate for EJB: "
1003: + getBeanMetaData().getEjbName());
1004: }
1005:
1006: Context envCtx = ctx.createSubcontext("env");
1007:
1008: // Bind environment properties
1009: {
1010: Iterator i = beanMetaData.getEnvironmentEntries();
1011: while (i.hasNext()) {
1012: EnvEntryMetaData entry = (EnvEntryMetaData) i.next();
1013:
1014: log.debug("Binding env-entry: " + entry.getName()
1015: + " of type: " + entry.getType() + " to value:"
1016: + entry.getValue());
1017:
1018: EnvEntryMetaData.bindEnvEntry(envCtx, entry);
1019: }
1020: }
1021:
1022: // Bind EJB references
1023: {
1024: Iterator i = beanMetaData.getEjbReferences();
1025: while (i.hasNext()) {
1026: EjbRefMetaData ref = (EjbRefMetaData) i.next();
1027: log.debug("Binding an EJBReference " + ref.getName());
1028:
1029: if (ref.getLink() != null) {
1030: // Internal link
1031: String linkName = ref.getLink();
1032: String jndiName = EjbUtil.findEjbLink(server, di,
1033: linkName);
1034:
1035: log.debug("Binding " + ref.getName()
1036: + " to ejb-link: " + linkName + " -> "
1037: + jndiName);
1038:
1039: if (jndiName == null) {
1040: String msg = "Failed to resolve ejb-link: "
1041: + linkName + " make by ejb-name: "
1042: + ref.getName();
1043: throw new DeploymentException(msg);
1044: }
1045:
1046: Util.bind(envCtx, ref.getName(), new LinkRef(
1047: jndiName));
1048:
1049: } else {
1050: // Get the invoker specific ejb-ref mappings
1051: Iterator it = beanMetaData.getInvokerBindings();
1052: Reference reference = null;
1053: while (it.hasNext()) {
1054: String invokerBinding = (String) it.next();
1055: // Check for an invoker level jndi-name
1056: String name = ref
1057: .getInvokerBinding(invokerBinding);
1058: // Check for an global jndi-name
1059: if (name == null)
1060: name = ref.getJndiName();
1061: if (name == null) {
1062: throw new DeploymentException(
1063: "ejb-ref "
1064: + ref.getName()
1065: + ", expected either ejb-link in ejb-jar.xml or "
1066: + "jndi-name in jboss.xml");
1067: }
1068:
1069: StringRefAddr addr = new StringRefAddr(
1070: invokerBinding, name);
1071: log.debug("adding " + invokerBinding + ":"
1072: + name + " to Reference");
1073:
1074: if (reference == null) {
1075: reference = new Reference(
1076: "javax.naming.LinkRef",
1077: ENCThreadLocalKey.class.getName(),
1078: null);
1079: }
1080: reference.add(addr);
1081: }
1082:
1083: // If there were invoker bindings create bind the reference
1084: if (reference != null) {
1085: if (ref.getJndiName() != null) {
1086: // Add default for the bean level ejb-ref/jndi-name
1087: StringRefAddr addr = new StringRefAddr(
1088: "default", ref.getJndiName());
1089: reference.add(addr);
1090: }
1091: if (reference.size() == 1
1092: && reference.get("default") == null) {
1093: /* There is only one invoker binding and its not default so
1094: create a default binding to allow the link to have a value
1095: when accessed without an invoker active.
1096: */
1097: StringRefAddr addr = (StringRefAddr) reference
1098: .get(0);
1099: String target = (String) addr.getContent();
1100: StringRefAddr addr1 = new StringRefAddr(
1101: "default", target);
1102: reference.add(addr1);
1103: }
1104: Util.bind(envCtx, ref.getName(), reference);
1105: } else {
1106: // Bind the bean level ejb-ref/jndi-name
1107: if (ref.getJndiName() == null) {
1108: throw new DeploymentException(
1109: "ejb-ref "
1110: + ref.getName()
1111: + ", expected either ejb-link in ejb-jar.xml "
1112: + "or jndi-name in jboss.xml");
1113: }
1114: Util.bind(envCtx, ref.getName(), new LinkRef(
1115: ref.getJndiName()));
1116: }
1117: }
1118: }
1119: }
1120:
1121: // Bind Local EJB references
1122: {
1123: Iterator i = beanMetaData.getEjbLocalReferences();
1124: while (i.hasNext()) {
1125: EjbLocalRefMetaData ref = (EjbLocalRefMetaData) i
1126: .next();
1127: String refName = ref.getName();
1128: log.debug("Binding an EJBLocalReference "
1129: + ref.getName());
1130:
1131: if (ref.getLink() != null) {
1132: // Internal link
1133: log.debug("Binding " + refName
1134: + " to bean source: " + ref.getLink());
1135:
1136: String jndiName = EjbUtil.findLocalEjbLink(server,
1137: di, ref.getLink());
1138:
1139: Util.bind(envCtx, ref.getName(), new LinkRef(
1140: jndiName));
1141: } else {
1142: // Bind the bean level ejb-local-ref/local-jndi-name
1143: if (ref.getJndiName() == null) {
1144: throw new DeploymentException(
1145: "ejb-local-ref "
1146: + ref.getName()
1147: + ", expected either ejb-link in ejb-jar.xml "
1148: + "or local-jndi-name in jboss.xml");
1149: }
1150: Util.bind(envCtx, ref.getName(), new LinkRef(ref
1151: .getJndiName()));
1152: }
1153: }
1154: }
1155:
1156: // Bind service references
1157: UnifiedVirtualFile vfsRoot = new URLLoaderAdapter(di.url);
1158: for (ServiceRefMetaData sref : metaData.getServiceReferences()
1159: .values()) {
1160: String refName = sref.getServiceRefName();
1161: new ServiceRefDelegate().bindServiceRef(envCtx, refName,
1162: vfsRoot, di.ucl, sref);
1163: }
1164:
1165: // Bind resource references
1166: {
1167: Iterator i = beanMetaData.getResourceReferences();
1168:
1169: // let's play guess the cast game ;) New metadata should fix this.
1170: ApplicationMetaData application = beanMetaData
1171: .getApplicationMetaData();
1172:
1173: while (i.hasNext()) {
1174: ResourceRefMetaData ref = (ResourceRefMetaData) i
1175: .next();
1176:
1177: String resourceName = ref.getResourceName();
1178: String finalName = application
1179: .getResourceByName(resourceName);
1180: String resType = ref.getType();
1181: // If there was no resource-manager specified then an immeadiate
1182: // jndi-name or res-url name should have been given
1183: if (finalName == null)
1184: finalName = ref.getJndiName();
1185:
1186: if (finalName == null
1187: && resType.equals("java.net.URL") == false) {
1188: // the application assembler did not provide a resource manager
1189: // if the type is javax.sql.Datasoure use the default one
1190:
1191: if (ref.getType().equals("javax.sql.DataSource")) {
1192: // Go through JNDI and look for DataSource - use the first one
1193: Context dsCtx = new InitialContext();
1194: try {
1195: // Check if it is available in JNDI
1196: dsCtx.lookup("java:/DefaultDS");
1197: finalName = "java:/DefaultDS";
1198: } catch (Exception e) {
1199: log
1200: .debug(
1201: "failed to lookup DefaultDS; ignoring",
1202: e);
1203: } finally {
1204: dsCtx.close();
1205: }
1206: }
1207:
1208: // Default failed? Warn user and move on
1209: // POTENTIALLY DANGEROUS: should this be a critical error?
1210: if (finalName == null) {
1211: log.warn("No resource manager found for "
1212: + ref.getResourceName());
1213: continue;
1214: }
1215: }
1216:
1217: if (resType.equals("java.net.URL")) {
1218: // URL bindings
1219: if (ref.getResURL() != null) {
1220: // The URL string was given by the res-url
1221: log
1222: .debug("Binding URL: "
1223: + ref.getRefName()
1224: + " to JDNI ENC as: "
1225: + ref.getResURL());
1226: URL resURL = new URL(ref.getResURL());
1227: Util.bind(envCtx, ref.getRefName(), resURL);
1228: } else {
1229: log.debug("Binding URL: " + ref.getRefName()
1230: + " to: " + finalName);
1231: Object bind = null;
1232: if (ref.getJndiName() != null) {
1233: // Was the url given as a jndi-name reference to link to it
1234: bind = new LinkRef(finalName);
1235: } else {
1236: // The url string was given via a resource-name mapping
1237: bind = new URL(finalName);
1238: }
1239: Util.bind(envCtx, ref.getRefName(), bind);
1240: }
1241: } else {
1242: // Resource Manager bindings, should validate the type...
1243: log.debug("Binding resource manager: "
1244: + ref.getRefName() + " to JDNI ENC as: "
1245: + finalName);
1246:
1247: Util.bind(envCtx, ref.getRefName(), new LinkRef(
1248: finalName));
1249: }
1250: }
1251: }
1252:
1253: // Bind resource env references
1254: {
1255: Iterator i = beanMetaData.getResourceEnvReferences();
1256: while (i.hasNext()) {
1257: ResourceEnvRefMetaData resRef = (ResourceEnvRefMetaData) i
1258: .next();
1259: String encName = resRef.getRefName();
1260: String jndiName = resRef.getJndiName();
1261: // Should validate the type...
1262: log.debug("Binding env resource: " + encName
1263: + " to JDNI ENC as: " + jndiName);
1264:
1265: Util.bind(envCtx, encName, new LinkRef(jndiName));
1266: }
1267: }
1268:
1269: // Bind message destination references
1270: {
1271: Iterator i = beanMetaData.getMessageDestinationReferences();
1272:
1273: while (i.hasNext()) {
1274: MessageDestinationRefMetaData ref = (MessageDestinationRefMetaData) i
1275: .next();
1276:
1277: String refName = ref.getRefName();
1278: String jndiName = ref.getJNDIName();
1279: String link = ref.getLink();
1280: if (link != null) {
1281: if (jndiName == null) {
1282: MessageDestinationMetaData messageDestination = getMessageDestination(link);
1283: if (messageDestination == null)
1284: throw new DeploymentException(
1285: "message-destination-ref '"
1286: + refName
1287: + "' message-destination-link '"
1288: + link
1289: + "' not found and no jndi-name in jboss.xml");
1290: else {
1291: String linkJNDIName = messageDestination
1292: .getJNDIName();
1293: if (linkJNDIName == null)
1294: log
1295: .warn("message-destination '"
1296: + link
1297: + "' has no jndi-name in jboss.xml");
1298: else
1299: jndiName = linkJNDIName;
1300: }
1301: } else
1302: log
1303: .warn("message-destination-ref '"
1304: + refName
1305: + "' ignoring message-destination-link '"
1306: + link
1307: + "' because it has a jndi-name in jboss.xml");
1308: } else if (jndiName == null)
1309: throw new DeploymentException(
1310: "message-destination-ref '"
1311: + refName
1312: + "' has no message-destination-link in ejb-jar.xml and no jndi-name in jboss.xml");
1313: Util.bind(envCtx, refName, new LinkRef(jndiName));
1314: }
1315: }
1316:
1317: // Create a java:comp/env/security/security-domain link to the container
1318: // or application security-domain if one exists so that access to the
1319: // security manager can be made without knowing the global jndi name.
1320:
1321: String securityDomain = metaData.getContainerConfiguration()
1322: .getSecurityDomain();
1323: if (securityDomain == null)
1324: securityDomain = metaData.getApplicationMetaData()
1325: .getSecurityDomain();
1326: if (securityDomain != null) {
1327: log.debug("Binding securityDomain: " + securityDomain
1328: + " to JDNI ENC as: security/security-domain");
1329:
1330: Util.bind(envCtx, "security/security-domain", new LinkRef(
1331: securityDomain));
1332: Util.bind(envCtx, "security/subject", new LinkRef(
1333: securityDomain + "/subject"));
1334: }
1335:
1336: log.debug("End java:comp/env for EJB: "
1337: + beanMetaData.getEjbName());
1338: }
1339:
1340: public MessageDestinationMetaData getMessageDestination(String link) {
1341: return EjbUtil.findMessageDestination(server, di, link);
1342: }
1343:
1344: /**
1345: *The <code>teardownEnvironment</code> method unbinds everything from
1346: * the comp/env context. It would be better do destroy the env context
1347: * but destroyContext is not currently implemented..
1348: *
1349: * @exception Exception if an error occurs
1350: */
1351: private void teardownEnvironment() throws Exception {
1352: Context ctx = (Context) new InitialContext()
1353: .lookup("java:comp");
1354: ctx.unbind("env");
1355: log.debug("Removed bindings from java:comp/env for EJB: "
1356: + getBeanMetaData().getEjbName());
1357: try {
1358: NonSerializableFactory.unbind("ORB");
1359: log.debug("Unbound java:comp/ORB for EJB: "
1360: + getBeanMetaData().getEjbName());
1361:
1362: NonSerializableFactory.unbind("HandleDelegate");
1363: log.debug("Unbound java:comp/HandleDelegate for EJB: "
1364: + getBeanMetaData().getEjbName());
1365: } catch (NamingException ignored) {
1366: }
1367: }
1368:
1369: /**
1370: * The base class for container interceptors.
1371: *
1372: * <p>
1373: * All container interceptors perform the same basic functionality
1374: * and only differ slightly.
1375: */
1376: protected abstract class AbstractContainerInterceptor implements
1377: Interceptor {
1378: protected final Logger log = Logger.getLogger(this .getClass());
1379:
1380: public void setContainer(Container con) {
1381: }
1382:
1383: public void setNext(Interceptor interceptor) {
1384: }
1385:
1386: public Interceptor getNext() {
1387: return null;
1388: }
1389:
1390: public void create() {
1391: }
1392:
1393: public void start() {
1394: }
1395:
1396: public void stop() {
1397: }
1398:
1399: public void destroy() {
1400: }
1401:
1402: protected void rethrow(Exception e) throws Exception {
1403: if (e instanceof IllegalAccessException) {
1404: // Throw this as a bean exception...(?)
1405: throw new EJBException(e);
1406: } else if (e instanceof InvocationTargetException) {
1407: Throwable t = ((InvocationTargetException) e)
1408: .getTargetException();
1409:
1410: if (t instanceof EJBException) {
1411: throw (EJBException) t;
1412: } else if (t instanceof Exception) {
1413: throw (Exception) t;
1414: } else if (t instanceof Error) {
1415: throw (Error) t;
1416: } else {
1417: throw new NestedError("Unexpected Throwable", t);
1418: }
1419: }
1420:
1421: throw e;
1422: }
1423:
1424: // Monitorable implementation ------------------------------------
1425:
1426: public void sample(Object s) {
1427: // Just here to because Monitorable request it but will be removed soon
1428: }
1429:
1430: public Map retrieveStatistic() {
1431: return null;
1432: }
1433:
1434: public void resetStatistic() {
1435: }
1436: }
1437:
1438: /** Perform the MBeanServer.invoke op in a PrivilegedExceptionAction if
1439: * running with a security manager.
1440: */
1441: class MBeanServerAction implements PrivilegedExceptionAction {
1442: private ObjectName target;
1443: String method;
1444: Object[] args;
1445: String[] sig;
1446:
1447: MBeanServerAction() {
1448: }
1449:
1450: MBeanServerAction(ObjectName target, String method,
1451: Object[] args, String[] sig) {
1452: this .target = target;
1453: this .method = method;
1454: this .args = args;
1455: this .sig = sig;
1456: }
1457:
1458: public Object run() throws Exception {
1459: Object rtnValue = server.invoke(target, method, args, sig);
1460: return rtnValue;
1461: }
1462:
1463: Object invoke(ObjectName target, String method, Object[] args,
1464: String[] sig) throws Exception {
1465: SecurityManager sm = System.getSecurityManager();
1466: Object rtnValue = null;
1467: if (sm == null) {
1468: // Direct invocation on MBeanServer
1469: rtnValue = server.invoke(target, method, args, sig);
1470: } else {
1471: try {
1472: // Encapsulate the invocation in a PrivilegedExceptionAction
1473: MBeanServerAction action = new MBeanServerAction(
1474: target, method, args, sig);
1475: rtnValue = AccessController.doPrivileged(action);
1476: } catch (PrivilegedActionException e) {
1477: Exception ex = e.getException();
1478: throw ex;
1479: }
1480: }
1481: return rtnValue;
1482: }
1483: }
1484: }
|