0001: /**
0002: * JOnAS: Java(TM) Open Application Server
0003: * Copyright (C) 1999-2005 Bull S.A.
0004: * Contact: jonas-team@objectweb.org
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation; either
0009: * version 2.1 of the License, or any later version.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU Lesser General Public
0017: * License along with this library; if not, write to the Free Software
0018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
0019: * USA
0020: *
0021: * --------------------------------------------------------------------------
0022: * $Id: JContainer.java 9792 2006-10-24 13:44:21Z coqp $
0023: * --------------------------------------------------------------------------
0024: */package org.objectweb.jonas_ejb.container;
0025:
0026: import java.io.File;
0027: import java.lang.reflect.Method;
0028: import java.util.Collections;
0029: import java.util.Enumeration;
0030: import java.util.HashMap;
0031: import java.util.HashSet;
0032: import java.util.Iterator;
0033: import java.util.Properties;
0034: import java.util.Set;
0035:
0036: import javax.ejb.AccessLocalException;
0037: import javax.ejb.EJBException;
0038: import javax.management.MBeanServer;
0039: import javax.management.ObjectName;
0040: import javax.naming.Context;
0041: import javax.naming.InitialContext;
0042: import javax.naming.LinkRef;
0043: import javax.naming.NamingException;
0044: import javax.naming.NameNotFoundException;
0045: import javax.naming.Reference;
0046: import javax.naming.StringRefAddr;
0047: import javax.resource.spi.ActivationSpec;
0048: import javax.resource.spi.work.WorkManager;
0049: import javax.security.jacc.PolicyContext;
0050: import javax.transaction.Transaction;
0051:
0052: import org.objectweb.jonas.common.JProp;
0053: import org.objectweb.jonas.jmx.JmxService;
0054: import org.objectweb.jonas.resource.Rar;
0055: import org.objectweb.jonas.service.ServiceManager;
0056: import org.objectweb.jonas.ws.JServiceFactory;
0057: import org.objectweb.jonas.ws.JServiceFactoryFinder;
0058: import org.objectweb.jonas_ejb.container.jorm.RdbFactory;
0059: import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
0060: import org.objectweb.jonas_ejb.deployment.api.EntityBmpDesc;
0061: import org.objectweb.jonas_ejb.deployment.api.EntityCmpDesc;
0062: import org.objectweb.jonas_ejb.deployment.api.EntityDesc;
0063: import org.objectweb.jonas_ejb.deployment.api.EntityJdbcCmp1Desc;
0064: import org.objectweb.jonas_ejb.deployment.api.EntityJdbcCmp2Desc;
0065: import org.objectweb.jonas_ejb.deployment.api.MessageDrivenDesc;
0066: import org.objectweb.jonas_ejb.deployment.api.SessionStatefulDesc;
0067: import org.objectweb.jonas_ejb.deployment.api.SessionStatelessDesc;
0068: import org.objectweb.jonas_ejb.lib.EJBInvocation;
0069:
0070: import org.objectweb.jonas_lib.deployment.api.EjbLocalRefDesc;
0071: import org.objectweb.jonas_lib.deployment.api.EjbRefDesc;
0072: import org.objectweb.jonas_lib.deployment.api.EnvEntryDesc;
0073: import org.objectweb.jonas_lib.deployment.api.MessageDestinationRefDesc;
0074: import org.objectweb.jonas_lib.deployment.api.ResourceEnvRefDesc;
0075: import org.objectweb.jonas_lib.deployment.api.ResourceRefDesc;
0076: import org.objectweb.jonas_lib.naming.ContainerNaming;
0077: import org.objectweb.jonas_lib.security.PermissionManagerException;
0078:
0079: import org.objectweb.jonas_jms.api.JmsManager;
0080:
0081: import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
0082:
0083: import org.objectweb.transaction.jta.TransactionManager;
0084:
0085: import org.objectweb.carol.rmi.exception.NamingExceptionHelper;
0086:
0087: import org.objectweb.util.monolog.api.BasicLevel;
0088:
0089: /**
0090: * This class represents an EJB container. A container is where an enterprise
0091: * Bean object lives. All beans from a same ejb-jar file are installed in a
0092: * single container. For each EJB installed, the container provides a factory
0093: * and makes it available in the JNDI name space. The JContainer basically
0094: * manages a set of BeanFactory objects.
0095: * @author Philippe Coq
0096: * @author Jeff Mesnil (Security)
0097: * @author Christophe Ney (Making easier Enhydra integration)
0098: * @author Philippe Durieux (New architecture for local interfaces)
0099: * @author Florent Benoit (Ear service, ejb-link, JACC security)
0100: * @author Ludovic Bert (Ear service, ejb-link)
0101: * @author Benjamin Bonnet (max size for thread pool)
0102: */
0103:
0104: public class JContainer implements Container {
0105:
0106: /**
0107: * This class is the default factory class name used for the Entity bean.
0108: */
0109: public static final String DEFAULT_FACTORY_CLASS_NAME = "org.objectweb.jonas_ejb.container.JEntityFactory";
0110:
0111: /**
0112: * Work Manager, used as a pool of threads.
0113: */
0114: private static WorkManager workManager = null;
0115:
0116: /**
0117: * List of beans (key=EJBName / Value=BeanFactory)
0118: */
0119: private HashMap beanList = new HashMap();
0120:
0121: /**
0122: * Name of the ear application containing this container.
0123: */
0124: private String earFileName = null;
0125:
0126: /**
0127: * Container file name x.jar or x.xml
0128: */
0129: private String fileName;
0130:
0131: /**
0132: * External file name
0133: */
0134: private String externalFileName;
0135:
0136: /**
0137: * Jms manager
0138: */
0139: private JmsManager jms = null;
0140:
0141: /**
0142: * Classloader used by this container
0143: */
0144: private ClassLoader loader = null;
0145:
0146: /**
0147: * Container name
0148: */
0149: private String myname;
0150:
0151: /**
0152: * Naming object used to do lookup/bind in environment
0153: */
0154: private ContainerNaming naming = null;
0155:
0156: /**
0157: * Permission manager of this container. JACC
0158: */
0159: private PermissionManager permissionManager = null;
0160:
0161: /**
0162: * Factory used to make Principal objects
0163: */
0164: private PrincipalFactory principalFactory = null;
0165:
0166: /**
0167: * Enable / disable security
0168: */
0169: private boolean securityFlag = true;
0170:
0171: /**
0172: * Swapper object
0173: */
0174: private Swapper swapper;
0175:
0176: /**
0177: * Transaction manager
0178: */
0179: private TransactionManager tm = null;
0180:
0181: private String tmpDirName = null;
0182:
0183: /**
0184: * This is the default name for JORAM that will be used when trying to configure an MDB
0185: * when the JMS service is not running.
0186: */
0187: private static final String DEFAULT_ACTIVATION_SPEC_NAME = "joramActivationSpec";
0188:
0189: /**
0190: * constructor
0191: * @param name name of the container.
0192: * @param extFileName external file name
0193: * @param file file name (.jar or .xml)
0194: * @param ld the class loader to be used
0195: */
0196: public JContainer(String name, String extFileName, String file,
0197: ClassLoader ld) {
0198: myname = name;
0199: externalFileName = extFileName;
0200: fileName = file;
0201: loader = ld;
0202: swapper = new Swapper(this );
0203: swapper.start();
0204: if (TraceEjb.isDebugIc()) {
0205: TraceEjb.interp.log(BasicLevel.DEBUG,
0206: "New Container extFN= " + externalFileName
0207: + " filename=" + fileName);
0208: }
0209: tmpDirName = JProp.getJonasBase() + File.separator + "work"
0210: + File.separator + "beans";
0211: File d = new File(tmpDirName);
0212: d.mkdir();
0213: }
0214:
0215: public String getTmpDirName() {
0216: return tmpDirName;
0217: }
0218:
0219: // -------------------------------------------------------------------
0220: // Methods used by JOnAS Server (but not part of JContainer interface)
0221: // -------------------------------------------------------------------
0222:
0223: /**
0224: * Adds beans in container. This method is not part of JContainer interface,
0225: * although it is used by JOnAS Server, because we don't want to get all
0226: * BeanDesc classes (jonas_ejb.deployment.api) LATER: Replace this by
0227: * setDeploymentDesc ?
0228: * @param dd The Bean Deployment Descriptor
0229: * @return The bean factory created for this bean.
0230: * @throws EJBException
0231: */
0232: public synchronized BeanFactory addBean(BeanDesc dd) {
0233: BeanFactory bf = null;
0234: String beanName = dd.getEjbName();
0235: if (dd instanceof SessionStatefulDesc) {
0236: if (TraceEjb.isDebugIc()) {
0237: TraceEjb.interp.log(BasicLevel.DEBUG,
0238: "add SessionStatefulBean " + beanName);
0239: }
0240: bf = new JStatefulFactory((SessionStatefulDesc) dd, this );
0241: } else if (dd instanceof SessionStatelessDesc) {
0242: if (TraceEjb.isDebugIc()) {
0243: TraceEjb.interp.log(BasicLevel.DEBUG,
0244: "add SessionStatelessBean " + beanName);
0245: }
0246: bf = new JStatelessFactory((SessionStatelessDesc) dd, this );
0247: } else if (dd instanceof MessageDrivenDesc) {
0248: if (TraceEjb.isDebugIc()) {
0249: TraceEjb.interp.log(BasicLevel.DEBUG,
0250: "add MessageDrivenBean " + beanName);
0251: }
0252: Object obj = null;
0253: InitialContext ictx = null;
0254: String destJName = ((MessageDrivenDesc) dd)
0255: .getDestinationJndiName();
0256: try {
0257: ictx = naming.getInitialContext();
0258: obj = getActivationSpecFromContext(ictx, destJName);
0259: } catch (NamingException ex) {
0260: // Test also the root cause as with iiop, we got a NamingException with a NameNotFoundException as root cause
0261: if (ex instanceof NameNotFoundException
0262: || ex.getCause() instanceof NameNotFoundException) {
0263: TraceEjb.interp.log(BasicLevel.DEBUG,
0264: "Can not find destination JNDI name "
0265: + destJName, ex);
0266: } else {
0267: throw new EJBException(ex);
0268: }
0269: }
0270: if (obj != null && obj instanceof ActivationSpec) {
0271: bf = new JMdbEndpointFactory((MessageDrivenDesc) dd,
0272: this , (ActivationSpec) obj);
0273: } else if (getJmsManager() == null) {
0274: // This is the case where we need to attach the MDB to an RAR, but it is either configured
0275: // as an EJB 2.0 MDB or incorrectly for a 2.1 MDB.
0276: if (((MessageDrivenDesc) dd).getDestination() != null) {
0277: if (TraceEjb.isDebugIc()) {
0278: TraceEjb.interp.log(BasicLevel.DEBUG,
0279: "JMS service not started and specified ActivationSpec("
0280: + destJName + ") not deployed");
0281: }
0282: throw new EJBException(
0283: "JMS service not started and specified ActivationSpec("
0284: + destJName + ") not deployed");
0285: }
0286:
0287: // Get the default ActivationSpec name and attempt to configure it
0288: String dest = Rar.getDefaultAS(); //default name
0289: if (dest == null) {
0290: dest = DEFAULT_ACTIVATION_SPEC_NAME; //default name
0291: }
0292:
0293: try {
0294: obj = getActivationSpecFromContext(ictx, dest);
0295: } catch (Exception ex) {
0296: if (TraceEjb.isDebugIc()) {
0297: TraceEjb.interp.log(BasicLevel.DEBUG,
0298: "JMS service not started and default ActivationSpec("
0299: + dest + ") not deployed");
0300: }
0301: throw new EJBException(
0302: "JMS service not started and default ActivationSpec("
0303: + dest + ") not deployed", ex);
0304: }
0305: if (obj != null && obj instanceof ActivationSpec) {
0306: bf = new JMdbEndpointFactory(
0307: (MessageDrivenDesc) dd, dest, this ,
0308: (ActivationSpec) obj);
0309: } else {
0310: if (TraceEjb.isDebugIc()) {
0311: TraceEjb.interp.log(BasicLevel.DEBUG,
0312: "Invalid destination: No ActivationSpec deployed matching "
0313: + dest);
0314: }
0315: throw new EJBException(
0316: "Invalid destination: No ActivationSpec deployed matching "
0317: + dest);
0318: }
0319: } else {
0320: // This is the case where a 2.1 MDB is trying to connect to an RAR that isn't deployed
0321: if (((MessageDrivenDesc) dd).getDestination() != null) {
0322: if (TraceEjb.isDebugIc()) {
0323: TraceEjb.interp.log(BasicLevel.DEBUG,
0324: "JMS service started and specified ActivationSpec("
0325: + destJName + ") not deployed");
0326: }
0327: throw new EJBException(
0328: "JMS service started and specified ActivationSpec("
0329: + destJName + ") not deployed");
0330: }
0331: bf = new JMdbFactory((MessageDrivenDesc) dd, this );
0332: }
0333: } else if (dd instanceof EntityJdbcCmp2Desc) {
0334: EntityJdbcCmp2Desc ecd = (EntityJdbcCmp2Desc) dd;
0335: // TODO We only manage "Jdbc" CMP2 entity beans today.
0336: if (TraceEjb.isDebugIc()) {
0337: TraceEjb.interp.log(BasicLevel.DEBUG,
0338: "add CMP2 EntityBean " + beanName);
0339: }
0340: // Instanciate the Factory depending on the mapper
0341: String cn = null;
0342: try {
0343: String dsn = ecd.getDatasourceJndiName();
0344: // Pb: We need the mapper to instanciate the Factory.
0345: // The mapper is in the Datasource. No way to get it in a
0346: // standard way
0347: // since Datasource interface is very simple (getConnection()
0348: // only)
0349: //
0350: // This will now try to call a getMapperName method for the
0351: // datasource,
0352: // if it doesn't exist then get the mapper.properties file and
0353: // look for the
0354: // jndiname. This allows flexibility for additional data source
0355: // support,
0356: // but still is not perfect.
0357:
0358: InitialContext ictx = naming.getInitialContext();
0359: String mapperName = null;
0360: // Attempt to call getMapperName method and if it doesn't exist
0361: // then
0362: // read the mapper.properties file
0363: try {
0364: Object cls = ictx.lookup(dsn);
0365: Method meth = cls.getClass().getMethod(
0366: "getMapperName", (Class[]) null);
0367: mapperName = (String) meth.invoke(cls,
0368: (Object[]) null);
0369: } catch (Exception e1) {
0370: if (TraceEjb.isDebugIc()) {
0371: TraceEjb.interp.log(BasicLevel.DEBUG,
0372: "Cannot read mapper name", e1);
0373: }
0374: }
0375: if (mapperName == null
0376: || mapperName.trim().length() == 0) {
0377: // Method doesn't exist so go read mapper.properties and
0378: // look for jndiname mapping
0379: try {
0380: JProp dsProps = JProp.getInstance("mapper");
0381: mapperName = dsProps.getValue(dsn, "");
0382: } catch (Exception e2) {
0383: throw new EJBException(
0384: "Unable to retrieve mapperName for "
0385: + dsn, e2);
0386: }
0387: if (mapperName == null) {
0388: throw new EJBException(
0389: "Unable to retrieve mapperName for "
0390: + dsn + ". mappername is null.");
0391: }
0392: }
0393:
0394: cn = ecd.getFactoryClassName();
0395: bf = (JEntityFactory) loader.loadClass(cn)
0396: .newInstance();
0397: ((RdbFactory) bf).init(ecd, this , mapperName);
0398: // set minimum timeout for the swapper
0399: setSwapTime(((EntityDesc) ecd).getPassivationTimeout());
0400: setSwapTime(((EntityDesc) ecd).getInactivityTimeout());
0401: TraceEjb.interp.log(BasicLevel.INFO, beanName
0402: + " is loaded and using " + mapperName);
0403: } catch (Exception e) {
0404: TraceEjb.interp.log(BasicLevel.ERROR,
0405: "Impossible to instanciate the entity factory: "
0406: + cn, e);
0407: throw new EJBException(
0408: "Impossible to instanciate the entity factory: "
0409: + cn, e);
0410: }
0411: } else if (dd instanceof EntityDesc) {
0412: if (TraceEjb.isDebugIc()) {
0413: TraceEjb.interp.log(BasicLevel.DEBUG, "add EntityBean "
0414: + beanName);
0415: }
0416: // Instanciate the default factory
0417: String cn = null;
0418: try {
0419: cn = DEFAULT_FACTORY_CLASS_NAME;
0420: bf = (JEntityFactory) loader.loadClass(cn)
0421: .newInstance();
0422: } catch (Exception e) {
0423: throw new EJBException(
0424: "Impossible to instanciate the specified entity factory: "
0425: + cn, e);
0426: }
0427: ((JEntityFactory) bf).init((EntityDesc) dd, this );
0428: // set minimum timeout for the swapper
0429: setSwapTime(((EntityDesc) dd).getPassivationTimeout());
0430: setSwapTime(((EntityDesc) dd).getInactivityTimeout());
0431: } else {
0432: throw new EJBException("Bad Descriptor Type for "
0433: + beanName);
0434: }
0435: beanList.put(beanName, bf);
0436: TraceEjb.interp.log(BasicLevel.INFO, beanName + " available");
0437:
0438: try {
0439: ServiceManager sm = ServiceManager.getInstance();
0440: MBeanServer mbeanServer = ((JmxService) sm.getJmxService())
0441: .getJmxServer();
0442: Object[] params = { fileName };
0443: String[] signature = { "java.lang.String" };
0444: ObjectName areaServiceName = new ObjectName("AreaService",
0445: "name", "Service");
0446:
0447: // only use the area service if it was previously registered in the MBeanServer
0448: if (mbeanServer.isRegistered(areaServiceName)) {
0449: mbeanServer.invoke(areaServiceName,
0450: "addPackageInEJBArea", params, signature);
0451: }
0452: } catch (Exception e) {
0453: TraceEjb.interp.log(BasicLevel.ERROR,
0454: "Area service unreachable : " + e.getMessage(), e);
0455: }
0456:
0457: return bf;
0458: }
0459:
0460: /**
0461: * Lookup the ActivationSpec from the Bean InitialContext.
0462: * @param context JNDI Context of the Bean.
0463: * @param jndiName JNDI Name of the resource to lookup.
0464: * @return Returns the instance found if any.
0465: * @throws NamingException If JNDI lookup fails.
0466: */
0467: private Object getActivationSpecFromContext(InitialContext context,
0468: String jndiName) throws NamingException {
0469: // save the old TCCL
0470: ClassLoader old = Thread.currentThread()
0471: .getContextClassLoader();
0472: Object obj = null;
0473: try {
0474: // set TCCL befaore lookup
0475: Thread.currentThread().setContextClassLoader(loader);
0476: // lookup
0477: obj = context.lookup(jndiName);
0478: } finally {
0479: // reset TCCL
0480: Thread.currentThread().setContextClassLoader(old);
0481: }
0482: return obj;
0483: }
0484:
0485: /**
0486: * Used by the above getXXXDependence() methods.
0487: * @param beanFactories the bean factories managed by this container.
0488: * @param rName jndi name of a resource (datasource, JMS destination or
0489: * connection factory, mail factory).
0490: * @param isResRef true for resource-ref, false for resource-env-ref.
0491: * @return set of Properties, where each Properties provides the bean name,
0492: * the container's file-name and the type of the bean which uses the
0493: * resource.
0494: */
0495: private Set beansDependence(Enumeration beanFactories,
0496: String rName, boolean isResRef) {
0497: HashSet result = new HashSet();
0498: BeanFactory bf = null;
0499: while (beanFactories.hasMoreElements()) {
0500: // for each bean,
0501: bf = (BeanFactory) beanFactories.nextElement();
0502: BeanDesc ejbDesc = bf.getDeploymentDescriptor();
0503:
0504: boolean isDependent = false; // suppose its not dependent
0505:
0506: // get its type from the DeploymentDescriptor
0507: String ejbType = null;
0508: if (bf instanceof JEntityFactory) {
0509: if (ejbDesc instanceof EntityBmpDesc) {
0510: ejbType = "ejbbmp";
0511: }
0512: if (ejbDesc instanceof EntityCmpDesc) {
0513: ejbType = "ejbcmp";
0514: }
0515: } else if (bf instanceof JStatefulFactory) {
0516: ejbType = "ejbsbf";
0517: } else if (bf instanceof JStatelessFactory) {
0518: ejbType = "ejbsbl";
0519: } else if (bf instanceof JMdbFactory
0520: || bf instanceof JMdbEndpointFactory) {
0521: ejbType = "ejbmdb";
0522: }
0523:
0524: if (isResRef) {
0525: // if this is a cmp bean, directly compare rName with the data
0526: // source JNDI name
0527: // from its deployment descriptor
0528: if (ejbType.equals("ejbcmp")) {
0529: String jndiName = null;
0530: if (ejbDesc instanceof EntityJdbcCmp1Desc) {
0531: jndiName = ((EntityJdbcCmp1Desc) ejbDesc)
0532: .getDatasourceJndiName();
0533: } else if (ejbDesc instanceof EntityJdbcCmp2Desc) {
0534: jndiName = ((EntityJdbcCmp2Desc) ejbDesc)
0535: .getDatasourceJndiName();
0536: }
0537: isDependent = rName.equals(jndiName);
0538: }
0539: // get the description of the bean's resource-refs
0540: ResourceRefDesc[] rrDesc = ejbDesc.getResourceRefDesc();
0541: for (int i = 0; i < rrDesc.length; i++) {
0542: // for each resource-ref compare its name with rName
0543: if (rrDesc[i].getJndiName().equals(rName)) {
0544: isDependent = true;
0545: break;
0546: }
0547: }
0548: } else {
0549: if (ejbType.equals("ejbmdb")) {
0550: if (rName.equals(((MessageDrivenDesc) ejbDesc)
0551: .getDestinationJndiName())) {
0552: isDependent = true;
0553: }
0554: }
0555: // get the description of the bean's resource-env-refs
0556: ResourceEnvRefDesc[] rerDesc = ejbDesc
0557: .getResourceEnvRefDesc();
0558: for (int i = 0; i < rerDesc.length; i++) {
0559: // for each resource-env-ref compare its name with rName
0560: if (rerDesc[i].getJndiName().equals(rName)) {
0561: isDependent = true;
0562: break;
0563: }
0564: }
0565: }
0566:
0567: if (isDependent) {
0568: Properties toAdd = new Properties();
0569: toAdd.setProperty("type", ejbType);
0570: toAdd.setProperty("fname", getFileName());
0571: toAdd.setProperty("name", ejbDesc.getEjbName());
0572: toAdd.setProperty("cname", getName());
0573: String earFileName = getEarFileName();
0574: if (earFileName != null) {
0575: toAdd.setProperty("earFileName", earFileName);
0576: }
0577: result.add(toAdd);
0578: }
0579:
0580: }
0581: return result;
0582: }
0583:
0584: /**
0585: * Check Security. No control for Message Driven Beans
0586: * @param ejbName name of the EJB of which do control
0587: * @param ejbInv object containing security signature of the method, args of
0588: * method, etc
0589: * @param inRunAs bean calling this method is running in run-as mode or not ?
0590: */
0591: protected void checkSecurity(String ejbName, EJBInvocation ejbInv,
0592: boolean inRunAs) {
0593: String oldContextId = PolicyContext.getContextID();
0594:
0595: boolean accessIsOk = false;
0596: try {
0597: // Set contextID to PermissionManager contextID (EJB ContextID)
0598: if (permissionManager != null) {
0599: accessIsOk = permissionManager.checkSecurity(ejbName,
0600: ejbInv, inRunAs);
0601: }
0602: } catch (Exception e) {
0603: TraceEjb.security.log(BasicLevel.ERROR,
0604: "Error while checking security", e);
0605: } finally {
0606: PolicyContext.setContextID(oldContextId);
0607: }
0608: if (!accessIsOk) {
0609: StringBuffer errMsg = new StringBuffer(
0610: "Access Denied on bean '");
0611: errMsg.append(ejbName);
0612: errMsg.append("' with run-as = '");
0613: errMsg.append(inRunAs);
0614: errMsg.append("'. ");
0615: if (ejbInv != null
0616: && ejbInv.methodPermissionSignature != null) {
0617: errMsg.append(" Method signature = '");
0618: errMsg.append(ejbInv.methodPermissionSignature);
0619: errMsg.append("'.");
0620: }
0621: throw new AccessLocalException(errMsg.toString());
0622: }
0623:
0624: }
0625:
0626: /**
0627: * Get the bean factory for the given bean.
0628: * @param ejbName the name of the bean
0629: * @return the bean factory for this bean
0630: */
0631: public BeanFactory getBeanFactory(String ejbName) {
0632: return (BeanFactory) beanList.get(ejbName);
0633: }
0634:
0635: /**
0636: * @return total Number of Beans
0637: */
0638: public int getBeanNb() {
0639: return beanList.size();
0640: }
0641:
0642: /**
0643: * @return the classloader used for this Container
0644: */
0645: public ClassLoader getClassLoader() {
0646: if (loader == null) {
0647: TraceEjb.logger.log(BasicLevel.ERROR,
0648: "container has been removed");
0649: //return Thread.currentThread().getContextClassLoader();
0650: return null;
0651: } else {
0652: return loader;
0653: }
0654: }
0655:
0656: /**
0657: * used internally by all the EJB Container classes.
0658: * @return the ContainerNaming object
0659: */
0660: public ContainerNaming getContainerNaming() {
0661: return naming;
0662: }
0663:
0664: /**
0665: * Management method used by the EJBServiceImpl MBean. Determine which are
0666: * the ejbs using a given data source.
0667: * @param dsName JNDI name of the data source
0668: * @return a set of Properties describing the beans that use the data source
0669: */
0670: public Set getDataSourceDependence(String dsName) {
0671: // the true param corresponds to a resource-ref
0672: return beansDependence(Collections.enumeration(beanList
0673: .values()), dsName, true);
0674: }
0675:
0676: /**
0677: * get the name of the ear application containing this container.
0678: * @return the name of the ear application containing this container.
0679: */
0680: public String getEarFileName() {
0681: return earFileName;
0682: }
0683:
0684: /**
0685: * @return int Number of BMP type currently in this container
0686: */
0687: public int getEntityBMPNb() {
0688: BeanFactory bf;
0689: int total = 0;
0690: Iterator it = beanList.values().iterator();
0691: while (it.hasNext()) {
0692: bf = (BeanFactory) it.next();
0693: if (bf.getDeploymentDescriptor() instanceof EntityBmpDesc) {
0694: total++;
0695: }
0696: }
0697: return total;
0698: }
0699:
0700: /**
0701: * @return int Number of CMP type currently in this container
0702: */
0703: public int getEntityCMPNb() {
0704: BeanFactory bf;
0705: int total = 0;
0706: Iterator it = beanList.values().iterator();
0707: while (it.hasNext()) {
0708: bf = (BeanFactory) it.next();
0709: if (bf.getDeploymentDescriptor() instanceof EntityCmpDesc) {
0710: total++;
0711: }
0712: }
0713: return total;
0714: }
0715:
0716: /**
0717: * @return the file name of the container (.xml or .jar)
0718: */
0719: public String getFileName() {
0720: return fileName;
0721: }
0722:
0723: /**
0724: * @return the external file name of the container
0725: */
0726: public String getExternalFileName() {
0727: return externalFileName;
0728: }
0729:
0730: /**
0731: * Management method used by the EJBServiceImpl MBean. Determine which are
0732: * the ejbs using a JMS Connection Factory.
0733: * @param cfName JNDI name of a JMS Connection Factory.
0734: * @return a set of Properties describing the beans that use the JMS
0735: * Connection Factory.
0736: */
0737: public Set getJmsConnectionFactoryDependence(String cfName) {
0738: // the true param corresponds to a resource-ref
0739: return beansDependence(Collections.enumeration(beanList
0740: .values()), cfName, true);
0741: }
0742:
0743: /**
0744: * Management method used by the EJBServiceImpl MBean. Determine which are
0745: * the beans using a JMS destination.
0746: * @param destName JNDI name of a JMS destination
0747: * @return a set of Properties describing the ejbs that use the JMS
0748: * destination.
0749: */
0750: public Set getJmsDestinationDependence(String destName) {
0751: // the true param corresponds to a resource-ref
0752: return beansDependence(Collections.enumeration(beanList
0753: .values()), destName, false);
0754: }
0755:
0756: /**
0757: * used internally by all the EJB Container classes.
0758: * @return the JmsManager object
0759: */
0760: public JmsManager getJmsManager() {
0761: return jms;
0762: }
0763:
0764: /**
0765: * Management method used by the EJBServiceImpl MBean. Determine which are
0766: * the ejbs using a Mail Factory.
0767: * @param mfName JNDI name of a Mail Factory.
0768: * @return a set of Properties describing the beans that use the given Mail
0769: * Factory.
0770: */
0771: public Set getMailFactoryDependence(String mfName) {
0772: // the true param corresponds to a resource-ref
0773: return beansDependence(Collections.enumeration(beanList
0774: .values()), mfName, true);
0775: }
0776:
0777: /**
0778: * @return int Number of MDB type currently in this container
0779: */
0780: public int getMessageDrivenNb() {
0781: BeanFactory bf;
0782: int total = 0;
0783: Iterator it = beanList.values().iterator();
0784: while (it.hasNext()) {
0785: bf = (BeanFactory) it.next();
0786: if (bf.getDeploymentDescriptor() instanceof MessageDrivenDesc) {
0787: total++;
0788: }
0789: }
0790: return total;
0791: }
0792:
0793: /**
0794: * @return name of this Container
0795: */
0796: public String getName() {
0797: return myname;
0798: }
0799:
0800: /**
0801: * Gets the permission manager
0802: * @return the permission manager
0803: */
0804: public PermissionManager getPermissionManager() {
0805: return permissionManager;
0806: }
0807:
0808: /**
0809: * @return the PrincipalFactory of the Container
0810: */
0811: public PrincipalFactory getPrincipalFactory() {
0812: return principalFactory;
0813: }
0814:
0815: /**
0816: * @return int Number of SBF type currently in this container
0817: */
0818: public int getStatefulSessionNb() {
0819: BeanFactory bf;
0820: int total = 0;
0821: Iterator it = beanList.values().iterator();
0822: while (it.hasNext()) {
0823: bf = (BeanFactory) it.next();
0824: if (bf.getDeploymentDescriptor() instanceof SessionStatefulDesc) {
0825: total++;
0826: }
0827: }
0828: return total;
0829: }
0830:
0831: /**
0832: * @return int Number of SBL type currently in this container
0833: */
0834: public int getStatelessSessionNb() {
0835: BeanFactory bf;
0836: int total = 0;
0837: Iterator it = beanList.values().iterator();
0838: while (it.hasNext()) {
0839: bf = (BeanFactory) it.next();
0840: if (bf.getDeploymentDescriptor() instanceof SessionStatelessDesc) {
0841: total++;
0842: }
0843: }
0844: return total;
0845: }
0846:
0847: /**
0848: * return the Transaction Manager used internally by all the EJB Container
0849: * classes.
0850: * @return the Transaction Manager
0851: */
0852: public TransactionManager getTransactionManager() {
0853: return tm;
0854: }
0855:
0856: /**
0857: * Return true if only if this ejbjar is in an ear file.
0858: * @return true if only if this ejbjar is in an ear file.
0859: */
0860: public boolean isInEarCase() {
0861: return (earFileName != null);
0862: }
0863:
0864: // ---------------------------------------------------------------
0865: // Container Implementation
0866: // ---------------------------------------------------------------
0867:
0868: /**
0869: * @return List of beans hosted in this Container
0870: */
0871: public String[] listBeanNames() {
0872: return (String[]) beanList.keySet().toArray(new String[0]);
0873: }
0874:
0875: // -------------------------------------------------------------------
0876: // Other public methods, used internally in this package.
0877: // -------------------------------------------------------------------
0878:
0879: /**
0880: * register a BeanFactory
0881: * @param bf The Bean Factory to be registered
0882: */
0883: public void registerBF(BeanFactory bf) {
0884: swapper.addBeanFactory(bf);
0885: }
0886:
0887: /**
0888: * register a BeanFactory for Sync
0889: * @param bf The Bean Factory to be registered
0890: */
0891: public void registerBFS(BeanFactory bf) {
0892: swapper.addBeanFactorySync(bf);
0893: }
0894:
0895: /**
0896: * Remove the JOnAS container and unregister all beans.
0897: */
0898: public synchronized void remove() {
0899: if (TraceEjb.isDebugIc()) {
0900: TraceEjb.interp.log(BasicLevel.DEBUG, myname);
0901: }
0902:
0903: // Stop the swapper.
0904: swapper.stopIt();
0905:
0906: // synchronize all entity beans before removing them.
0907: // must be done here, not in the swapper.
0908: // This is necessary for CS policy only.
0909: syncAll(true, false);
0910:
0911: // remove all factories
0912: Iterator it = beanList.values().iterator();
0913: ServiceManager sm = ServiceManager.getInstance();
0914: MBeanServer mbeanServer = ((JmxService) sm.getJmxService())
0915: .getJmxServer();
0916: while (it.hasNext()) {
0917: BeanFactory bf = (BeanFactory) it.next();
0918: try {
0919: bf.stop();
0920: TraceEjb.interp.log(BasicLevel.INFO, myname + ": "
0921: + bf.getEJBName() + " no longer available");
0922: Object[] params = { fileName };
0923: String[] signature = { new String("java.lang.String") };
0924: ObjectName areaServiceName = new ObjectName(
0925: "AreaService", "name", "Service");
0926: try {
0927: if (mbeanServer.isRegistered(areaServiceName)) {
0928: mbeanServer.invoke(areaServiceName,
0929: "removePackageFromEJBArea", params,
0930: signature);
0931: }
0932: } catch (Exception exc) {
0933: TraceEjb.interp.log(BasicLevel.ERROR,
0934: "Area service unreachable : "
0935: + exc.getMessage(), exc);
0936: }
0937: } catch (Exception e) {
0938: TraceEjb.logger.log(BasicLevel.ERROR, myname, e);
0939: }
0940: }
0941: beanList.clear();
0942:
0943: // to unload all classes.
0944: loader = null;
0945:
0946: // Remove permission manager
0947: try {
0948: if (permissionManager != null) {
0949: permissionManager.delete();
0950: }
0951: } catch (PermissionManagerException pme) {
0952: TraceEjb.logger.log(BasicLevel.ERROR, myname, pme);
0953: }
0954: permissionManager = null;
0955:
0956: // Run the garbage collector
0957: Runtime.getRuntime().gc();
0958: }
0959:
0960: /**
0961: * Set the bean environment
0962: * @param ctx Context for this bean
0963: * @param dd Bean Deployment Descriptor
0964: * @throws NamingException if could not rebind objects
0965: */
0966: public void setBeanEnvironment(Context ctx, BeanDesc dd)
0967: throws NamingException {
0968:
0969: // Set bean context
0970: // Build comp/env
0971: Context ctxold = naming.setComponentContext(ctx);
0972: Context envCtx = ctx.createSubcontext("comp/env");
0973:
0974: // Bean Environment
0975: EnvEntryDesc[] envt = dd.getEnvEntryDesc();
0976: for (int i = 0; i < envt.length; i++) {
0977: // get information in descriptor
0978: String name = envt[i].getName();
0979: Object obj = envt[i].getValue();
0980: // register object in JNDI
0981: if (TraceEjb.isDebugIc()) {
0982: TraceEjb.interp.log(BasicLevel.DEBUG, myname
0983: + ": Binding object " + name + " -> " + obj);
0984: }
0985: envCtx.rebind(name, obj);
0986: }
0987:
0988: // Resource References
0989: ResourceRefDesc[] resref = dd.getResourceRefDesc();
0990: for (int i = 0; i < resref.length; i++) {
0991: // get information in descriptor
0992: String name = resref[i].getName();
0993: String resname = resref[i].getJndiName();
0994: String type = resref[i].getTypeName();
0995: // build the LinkRef that will be registered:
0996: // FactoryClassName = null, size = 1, refAddr = resname.
0997:
0998: // register object in JNDI
0999: if (TraceEjb.isDebugIc()) {
1000: TraceEjb.interp.log(BasicLevel.DEBUG, myname
1001: + ": Linking resource " + name + " -> "
1002: + resname);
1003: }
1004:
1005: if (type.equalsIgnoreCase("java.net.URL")) {
1006: // Specify the factory to use with the right URL
1007: Reference ref = new Reference(
1008: "java.net.URL",
1009: "org.objectweb.jonas_lib.naming.factory.URLFactory",
1010: null);
1011: StringRefAddr refAddr = new StringRefAddr("url",
1012: resname);
1013: ref.add(refAddr);
1014: envCtx.rebind(name, ref);
1015: } else {
1016: LinkRef lref = new LinkRef(resname);
1017: envCtx.rebind(name, lref);
1018: }
1019: }
1020:
1021: // Resource Environment References
1022: ResourceEnvRefDesc[] resEnvref = dd.getResourceEnvRefDesc();
1023: for (int i = 0; i < resEnvref.length; i++) {
1024: // get information in descriptor
1025: String name = resEnvref[i].getName();
1026: String resname = resEnvref[i].getJndiName();
1027: LinkRef lref = new LinkRef(resname);
1028:
1029: if (TraceEjb.isDebugIc()) {
1030: TraceEjb.interp.log(BasicLevel.DEBUG, myname
1031: + ": Linking resource environment " + name
1032: + " -> " + resname);
1033: }
1034: envCtx.rebind(name, lref);
1035: }
1036:
1037: // EJB References
1038: EjbRefDesc[] ejbref = dd.getEjbRefDesc();
1039: for (int i = 0; i < ejbref.length; i++) {
1040: // get information in descriptor
1041: String name = ejbref[i].getEjbRefName();
1042: String ejbname = null;
1043: ejbname = ejbref[i].getJndiName();
1044: LinkRef lref = new LinkRef(ejbname);
1045:
1046: if (TraceEjb.isDebugIc()) {
1047: TraceEjb.interp.log(BasicLevel.DEBUG, myname
1048: + ": Linking ejb " + name + " -> " + ejbname);
1049: }
1050: envCtx.rebind(name, lref);
1051: }
1052:
1053: // EJB Local Refs
1054: // We use here ejb-link tag. This should be used also for ejb-ref when
1055: // we are able to manage references to another jar file.
1056: EjbLocalRefDesc[] ejblocalref = dd.getEjbLocalRefDesc();
1057: for (int i = 0; i < ejblocalref.length; i++) {
1058: String name = ejblocalref[i].getEjbRefName();
1059: String ejbname = ejblocalref[i].getJndiLocalName();
1060: LinkRef lref = new LinkRef(ejbname);
1061: if (TraceEjb.isDebugIc()) {
1062: TraceEjb.interp.log(BasicLevel.DEBUG, myname
1063: + ": Linking ejb " + name + " -> " + ejbname);
1064: }
1065: envCtx.rebind(name, lref);
1066: }
1067:
1068: // ServiceRef
1069: ServiceRefDesc[] serviceRefs = dd.getServiceRefDesc();
1070: if (serviceRefs.length != 0) {
1071:
1072: // get the JServiceFactory
1073: JServiceFactory factory = null;
1074:
1075: for (int i = 0; i < serviceRefs.length; i++) {
1076:
1077: if (factory == null) {
1078: factory = JServiceFactoryFinder
1079: .getJOnASServiceFactory();
1080: }
1081: // Create the Service from the ServiceRef description
1082: String refname = serviceRefs[i].getServiceRefName();
1083:
1084: // create a full Reference
1085: Reference ref;
1086: try {
1087: ref = factory.getServiceReference(serviceRefs[i],
1088: loader);
1089: } catch (Exception e1) {
1090: throw NamingExceptionHelper.create(
1091: "Cannot get service reference", e1);
1092: }
1093: envCtx.rebind(refname, ref);
1094: if (TraceEjb.isDebugIc()) {
1095: TraceEjb.interp.log(BasicLevel.DEBUG,
1096: "Adding service-ref 'java:comp/env/"
1097: + refname + "'");
1098: }
1099: }
1100: }
1101:
1102: // MessageDestination References
1103: MessageDestinationRefDesc[] mdref = dd
1104: .getMessageDestinationRefDesc();
1105: for (int i = 0; i < mdref.length; i++) {
1106: // get information in descriptor
1107: String name = mdref[i].getMessageDestinationRefName();
1108: String mdname = null;
1109: mdname = mdref[i].getJndiName();
1110: LinkRef lref = new LinkRef(mdname);
1111:
1112: if (TraceEjb.isDebugIc()) {
1113: TraceEjb.interp.log(BasicLevel.DEBUG, myname
1114: + ": Linking message-destination " + name
1115: + " -> " + mdname);
1116: }
1117: envCtx.rebind(name, lref);
1118: }
1119:
1120: // Reset bean context
1121: naming.setComponentContext(ctxold);
1122: }
1123:
1124: /**
1125: * set the ContainerNaming object Called by the EJB Server when starting the
1126: * service.
1127: * @param naming the ContainerNaming object
1128: */
1129: public void setContainerNaming(ContainerNaming naming) {
1130: this .naming = naming;
1131: }
1132:
1133: /**
1134: * set the name of the ear application containing this container.
1135: * @param fileName the name of the ear application containing this
1136: * container.
1137: */
1138: public void setEarFileName(String fileName) {
1139: earFileName = fileName;
1140: }
1141:
1142: /**
1143: * set the JmsManager object Called by the EJB Server when starting ths
1144: * service.
1145: * @param jms the JmsManager
1146: */
1147: public void setJmsManager(JmsManager jms) {
1148: this .jms = jms;
1149: }
1150:
1151: /**
1152: * Set the permission manager object
1153: * @param permissionManager permission manager object
1154: */
1155: public void setPermissionManager(PermissionManager permissionManager) {
1156: this .permissionManager = permissionManager;
1157: }
1158:
1159: /**
1160: * Set the PrincipalFactory. This factory can be JOnAS Server dependant. The
1161: * Container makes no assumption on how to get the Principal.
1162: * @param pf the PrincipalFactory
1163: */
1164: public void setPrincipalFactory(PrincipalFactory pf) {
1165: principalFactory = pf;
1166: }
1167:
1168: /**
1169: * Set the security flag to enable or disable security
1170: * @param b true or false to enable/disable security
1171: */
1172: public void setSecurity(boolean b) {
1173: securityFlag = b;
1174: }
1175:
1176: /**
1177: * Take into account the swapping time for the bean.
1178: * @param t time in seconds (t = 0 no time out)
1179: */
1180: public void setSwapTime(int t) {
1181: if (t > 0) {
1182: if (TraceEjb.isDebugSwapper()) {
1183: TraceEjb.swapper.log(BasicLevel.DEBUG, myname + " sec="
1184: + t);
1185: }
1186: swapper.setSwapperTimeout(t);
1187: }
1188: }
1189:
1190: /**
1191: * set the Work Manager. Called by the EJB Server when starting the
1192: * service.
1193: * @param wm the Work Manager.
1194: */
1195: public void setWorkManager(WorkManager wm) {
1196: workManager = wm;
1197: }
1198:
1199: /**
1200: * @return the WorkManager unique instance
1201: */
1202: public WorkManager getWorkManager() {
1203: return workManager;
1204: }
1205:
1206: /**
1207: * set the Transaction Manager. Called by the EJB Server when starting the
1208: * service.
1209: * @param tm the Transaction Manager.
1210: */
1211: public void setTransactionManager(TransactionManager tm) {
1212: this .tm = tm;
1213: }
1214:
1215: /**
1216: * Try to passivate all entity bean instances
1217: * @param store True if store even if passivationTimeout not reached
1218: * @param passivate true if bean instances will be released after having
1219: * been written on storage.
1220: */
1221: public synchronized void syncAll(boolean store, boolean passivate) {
1222: if (TraceEjb.isDebugIc()) {
1223: TraceEjb.interp.log(BasicLevel.DEBUG, myname);
1224: }
1225: BeanFactory bf = null;
1226: Iterator it = beanList.values().iterator();
1227: while (it.hasNext()) {
1228: bf = (BeanFactory) it.next();
1229: if (passivate) {
1230: bf.reduceCache();
1231: } else {
1232: bf.syncDirty(store);
1233: }
1234: }
1235: }
1236:
1237: /**
1238: * Gets the context ID of this container (for jacc)
1239: * @return contextID used for JACC
1240: */
1241: public String getContextId() {
1242: return externalFileName;
1243: }
1244:
1245: /**
1246: * Try to store all entity bean instances modified in the transaction
1247: * this method has been introduced to fix bug #305711
1248: * it's, may be, bad for performance
1249: * @param tx
1250: */
1251: public synchronized void storeAll(Transaction tx) {
1252: if (TraceEjb.isDebugIc()) {
1253: TraceEjb.interp.log(BasicLevel.DEBUG, myname);
1254: }
1255: BeanFactory bf = null;
1256: Iterator it = beanList.values().iterator();
1257: while (it.hasNext()) {
1258: bf = (BeanFactory) it.next();
1259: bf.storeInstances(tx);
1260: }
1261: }
1262: }
|