001: package org.obe.runtime.tool;
002:
003: import org.apache.commons.logging.Log;
004: import org.apache.commons.logging.LogFactory;
005: import org.obe.XMLException;
006: import org.obe.client.api.repository.EJBMethodMetaData;
007: import org.obe.client.api.repository.RepositoryException;
008:
009: import javax.ejb.EJBHome;
010: import javax.ejb.EJBMetaData;
011: import javax.naming.Context;
012: import javax.naming.NamingException;
013: import javax.rmi.PortableRemoteObject;
014: import java.lang.reflect.InvocationTargetException;
015: import java.lang.reflect.Method;
016: import java.rmi.RemoteException;
017:
018: /**
019: * A tool agent that invokes a home or business method on an EJB.
020: *
021: * @author Adrian Price
022: */
023: public final class EJBMethod extends JavaMethod {
024: private static final long serialVersionUID = -8007893008342865647L;
025: private static final Log _logger = LogFactory
026: .getLog(EJBMethod.class);
027:
028: private final EJBMethodMetaData _metadata;
029: private Object _home;
030: private Method _createMethod;
031:
032: public EJBMethod(EJBMethodMetaData metaData)
033: throws ClassNotFoundException, NoSuchMethodException,
034: NamingException, RemoteException {
035:
036: super (metaData);
037: _metadata = metaData;
038:
039: // Look up the JNDI object bound to the specified name.
040: Object jndiObject;
041: Context ctx = null;
042: try {
043: jndiObject = ctx.lookup(metaData.getJndiName());
044: } finally {
045: if (ctx != null)
046: ctx.close();
047: }
048:
049: // Extract home and remote interfaces by introspecting the bound object.
050: Class homeClass;
051: Class intfClass;
052: try {
053: // The only way to tell whether this is a remote home is to cast it.
054: EJBHome home = (EJBHome) PortableRemoteObject.narrow(
055: jndiObject, EJBHome.class);
056: _home = home;
057: EJBMetaData ejbMeta = home.getEJBMetaData();
058: homeClass = ejbMeta.getHomeInterfaceClass();
059: intfClass = ejbMeta.getRemoteInterfaceClass();
060:
061: if (_logger.isDebugEnabled()) {
062: _logger.debug("JNDI name '" + metaData.getJndiName()
063: + "' is bound to a remote home: " + homeClass);
064: }
065: } catch (ClassCastException e) {
066: // This isn't strictly accurate, because it's the class that's
067: // implementing the home, not the actual home interface itself, but
068: // it's close enough for us to determine the local interface.
069: // Typically both will be dynamic proxies.
070: _home = jndiObject;
071: homeClass = jndiObject.getClass();
072: // Cast required to suppress JDK1.5 varargs compiler warning.
073: _createMethod = homeClass.getMethod("create",
074: (Class[]) null);
075: intfClass = _createMethod.getReturnType();
076:
077: if (_logger.isDebugEnabled()) {
078: _logger.debug("JNDI name '" + metaData.getJndiName()
079: + "' is bound to a local home: " + homeClass);
080: }
081: }
082:
083: // Inform superclass of implementing class, method name and param types.
084: setMethod(metaData.isHomeMethod() ? homeClass : intfClass,
085: metaData.getMethod(), metaData.getMethodSig());
086: }
087:
088: protected Object getTarget() throws XMLException,
089: RepositoryException, IllegalAccessException,
090: InvocationTargetException {
091:
092: // If this is a business method we'll need a target EJB instance.
093: // TODO: for SFSBs we need the create method signature & args as well.
094: Object target;
095: if (_metadata.isHomeMethod()) {
096: target = _home;
097: } else {
098: target = getTargetFromWorkflow();
099: if (target == null) {
100: target = _target;
101: if (target == null) {
102: // Cast required to suppress JDK1.5 varargs compiler warning.
103: _target = target = _createMethod.invoke(_home,
104: (Object[]) null);
105: if (_logger.isDebugEnabled())
106: _logger.debug("Created target EJB: " + target);
107: }
108: }
109: }
110: return target;
111: }
112: }
|