package org.jboss.proxy.ejb;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.ejb.EJBHome;
import javax.ejb.EJBMetaData;
import javax.ejb.EJBObject;
import javax.management.ObjectName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.rmi.CORBA.Stub;
import javax.rmi.PortableRemoteObject;
import org.jacorb.ssl.SSLPolicyValue;
import org.jacorb.ssl.SSLPolicyValueHelper;
import org.jacorb.ssl.SSL_POLICY_TYPE;
import org.jboss.ejb.Container;
import org.jboss.ejb.EJBProxyFactory;
import org.jboss.ejb.EJBProxyFactoryContainer;
import org.jboss.ejb.EntityContainer;
import org.jboss.ejb.StatefulSessionContainer;
import org.jboss.ejb.StatelessSessionContainer;
import org.jboss.iiop.CorbaNamingService;
import org.jboss.iiop.CorbaORBService;
import org.jboss.iiop.codebase.CodebasePolicy;
import org.jboss.iiop.csiv2.CSIv2Policy;
import org.jboss.iiop.rmi.AttributeAnalysis;
import org.jboss.iiop.rmi.InterfaceAnalysis;
import org.jboss.iiop.rmi.OperationAnalysis;
import org.jboss.iiop.rmi.ir.InterfaceRepository;
import org.jboss.iiop.rmi.marshal.strategy.SkeletonStrategy;
import org.jboss.invocation.Invocation;
import org.jboss.invocation.iiop.ReferenceFactory;
import org.jboss.invocation.iiop.ServantRegistries;
import org.jboss.invocation.iiop.ServantRegistry;
import org.jboss.invocation.iiop.ServantRegistryKind;
import org.jboss.invocation.iiop.ServantWithMBeanServer;
import org.jboss.logging.Logger;
import org.jboss.metadata.EntityMetaData;
import org.jboss.metadata.InvokerProxyBindingMetaData;
import org.jboss.metadata.IorSecurityConfigMetaData;
import org.jboss.metadata.MetaData;
import org.jboss.metadata.SessionMetaData;
import org.jboss.naming.Util;
import org.jboss.system.Registry;
import org.jboss.web.WebClassLoader;
import org.omg.CORBA.Any;
import org.omg.CORBA.InterfaceDef;
import org.omg.CORBA.InterfaceDefHelper;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
import org.omg.CORBA.Repository;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.InvalidName;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.omg.PortableServer.Current;
import org.omg.PortableServer.CurrentHelper;
import org.omg.PortableServer.POA;
import org.w3c.dom.Element;
public class IORFactory
implements EJBProxyFactory
{
private static final Logger staticLogger =
Logger.getLogger(IORFactory.class);
private ORB orb;
private Container container;
private String jndiName;
private boolean useJNPContext;
private String jnpName;
private EJBMetaDataImplIIOP ejbMetaData;
private Map beanMethodMap;
private Map homeMethodMap;
private String[] beanRepositoryIds;
private String[] homeRepositoryIds;
private ServantRegistry homeServantRegistry;
private ServantRegistry beanServantRegistry;
private ReferenceFactory homeReferenceFactory;
private ReferenceFactory beanReferenceFactory;
private Current poaCurrent;
private Policy codebasePolicy;
private Policy csiv2Policy;
private Policy sslPolicy;
private EJBHome ejbHome;
private InvokerProxyBindingMetaData invokerMetaData;
private ServantRegistries servantRegistries;
private InterfaceRepository iri;
private POA irPoa;
private Logger logger = staticLogger;
public void setContainer(Container container)
{
this.container = container;
if (container != null) {
String loggerName = IORFactory.class.getName() + '.'
+ container.getBeanMetaData().getJndiName();
logger = Logger.getLogger(loggerName);
}
}
public void create() throws Exception
{
try {
orb = (ORB)new InitialContext().lookup("java:/"
+ CorbaORBService.ORB_NAME);
}
catch (NamingException e) {
throw new Exception("Cannot lookup java:/"
+ CorbaORBService.ORB_NAME + ": " + e);
}
try {
irPoa = (POA)new InitialContext().lookup("java:/"
+ CorbaORBService.IR_POA_NAME);
}
catch (NamingException e) {
throw new Exception("Cannot lookup java:/"
+ CorbaORBService.IR_POA_NAME + ": " + e);
}
Element proxyFactoryConfig = invokerMetaData.getProxyFactoryConfig();
boolean interfaceRepositorySupported =
MetaData.getOptionalChildBooleanContent(
proxyFactoryConfig, "interface-repository-supported");
if (interfaceRepositorySupported) {
iri = new InterfaceRepository(orb, irPoa, jndiName);
iri.mapClass(((EJBProxyFactoryContainer)container).getRemoteClass());
iri.mapClass(((EJBProxyFactoryContainer)container).getHomeClass());
iri.finishBuild();
logger.info("CORBA interface repository for " + jndiName + ": "
+ orb.object_to_string(iri.getReference()));
}
logger.debug("Bean methods:");
InterfaceAnalysis interfaceAnalysis =
InterfaceAnalysis.getInterfaceAnalysis(
((EJBProxyFactoryContainer)container).getRemoteClass());
beanMethodMap = new HashMap();
AttributeAnalysis[] attrs = interfaceAnalysis.getAttributes();
for (int i = 0; i < attrs.length; i++) {
OperationAnalysis op = attrs[i].getAccessorAnalysis();
logger.debug(" " + op.getJavaName()
+ "\n " + op.getIDLName());
beanMethodMap.put(op.getIDLName(),
new SkeletonStrategy(op.getMethod()));
op = attrs[i].getMutatorAnalysis();
if (op != null) {
logger.debug(" " + op.getJavaName()
+ "\n " + op.getIDLName());
beanMethodMap.put(op.getIDLName(),
new SkeletonStrategy(op.getMethod()));
}
}
OperationAnalysis[] ops = interfaceAnalysis.getOperations();
for (int i = 0; i < ops.length; i++) {
logger.debug(" " + ops[i].getJavaName()
+ "\n " + ops[i].getIDLName());
beanMethodMap.put(ops[i].getIDLName(),
new SkeletonStrategy(ops[i].getMethod()));
}
beanRepositoryIds = interfaceAnalysis.getAllTypeIds();
logger.debug("Home methods:");
interfaceAnalysis =
InterfaceAnalysis.getInterfaceAnalysis(
((EJBProxyFactoryContainer)container).getHomeClass());
homeMethodMap = new HashMap();
attrs = interfaceAnalysis.getAttributes();
for (int i = 0; i < attrs.length; i++) {
OperationAnalysis op = attrs[i].getAccessorAnalysis();
logger.debug(" " + op.getJavaName()
+ "\n " + op.getIDLName());
homeMethodMap.put(op.getIDLName(),
new SkeletonStrategy(op.getMethod()));
op = attrs[i].getMutatorAnalysis();
if (op != null) {
logger.debug(" " + op.getJavaName()
+ "\n " + op.getIDLName());
homeMethodMap.put(op.getIDLName(),
new SkeletonStrategy(op.getMethod()));
}
}
ops = interfaceAnalysis.getOperations();
for (int i = 0; i < ops.length; i++) {
logger.debug(" " + ops[i].getJavaName()
+ "\n " + ops[i].getIDLName());
homeMethodMap.put(ops[i].getIDLName(),
new SkeletonStrategy(ops[i].getMethod()));
}
homeRepositoryIds = interfaceAnalysis.getAllTypeIds();
logger.debug("container classloader: " + container.getClassLoader()
+ "\ncontainer parent classloader: "
+ container.getClassLoader().getParent());
WebClassLoader wcl = (WebClassLoader)container.getWebClassLoader();
Any codebase = orb.create_any();
codebase.insert_string(wcl.getCodebaseString());
codebasePolicy = orb.create_policy(CodebasePolicy.TYPE, codebase);
logger.debug("codebasePolicy: " + codebasePolicy);
Any secPolicy = orb.create_any();
IorSecurityConfigMetaData iorSecurityConfigMetaData =
container.getBeanMetaData().getIorSecurityConfigMetaData();
secPolicy.insert_Value(iorSecurityConfigMetaData);
csiv2Policy = orb.create_policy(CSIv2Policy.TYPE, secPolicy);
boolean sslRequired = false;
if (iorSecurityConfigMetaData != null) {
IorSecurityConfigMetaData.TransportConfig tc =
iorSecurityConfigMetaData.getTransportConfig();
sslRequired =
tc.getIntegrity() ==
IorSecurityConfigMetaData.TransportConfig.INTEGRITY_REQUIRED
|| tc.getConfidentiality() ==
IorSecurityConfigMetaData.TransportConfig.CONFIDENTIALITY_REQUIRED
|| tc.getEstablishTrustInClient() ==
IorSecurityConfigMetaData.TransportConfig.ESTABLISH_TRUST_IN_CLIENT_REQUIRED;
}
Any sslPolicyValue = orb.create_any();
SSLPolicyValueHelper.insert(
sslPolicyValue,
(sslRequired) ? SSLPolicyValue.SSL_REQUIRED
: SSLPolicyValue.SSL_NOT_REQUIRED);
sslPolicy = orb.create_policy(SSL_POLICY_TYPE.value, sslPolicyValue);
logger.debug("container's SSL policy: " + sslPolicy);
poaCurrent = CurrentHelper.narrow(
orb.resolve_initial_references("POACurrent"));
}
public void start() throws Exception
{
ObjectName oname = new ObjectName(invokerMetaData.getInvokerMBean());
servantRegistries = (ServantRegistries)Registry.lookup(oname);
if (servantRegistries == null)
throw new Exception("invoker is null: " + oname);
ServantRegistryKind registryWithTransientPOA;
ServantRegistryKind registryWithPersistentPOA;
Element proxyFactoryConfig = invokerMetaData.getProxyFactoryConfig();
String poaUsageModel =
MetaData.getOptionalChildContent(proxyFactoryConfig, "poa");
if (poaUsageModel == null || poaUsageModel.equals("shared")) {
registryWithTransientPOA = ServantRegistryKind.SHARED_TRANSIENT_POA;
registryWithPersistentPOA = ServantRegistryKind.SHARED_PERSISTENT_POA;
}
else if (poaUsageModel.equals("per-servant")) {
registryWithTransientPOA =
ServantRegistryKind.TRANSIENT_POA_PER_SERVANT;
registryWithPersistentPOA =
ServantRegistryKind.PERSISTENT_POA_PER_SERVANT;
}
else {
throw new Exception("invalid poa element in proxy factory config: "
+ poaUsageModel);
}
InterfaceDef homeInterfaceDef = null;
if (iri != null) {
Repository ir = iri.getReference();
homeInterfaceDef =
InterfaceDefHelper.narrow(ir.lookup_id(homeRepositoryIds[0]));
}
homeServantRegistry =
servantRegistries.getServantRegistry(registryWithPersistentPOA);
String homeServantLoggerName =
EjbHomeCorbaServant.class.getName() + '.'+ jndiName;
ServantWithMBeanServer homeServant =
new EjbHomeCorbaServant(container.getJmxName(),
container.getClassLoader(),
homeMethodMap,
homeRepositoryIds,
homeInterfaceDef,
Logger.getLogger(homeServantLoggerName));
homeReferenceFactory =
homeServantRegistry.bind(homeServantName(jndiName),
homeServant,
new Policy[] { codebasePolicy,
sslPolicy,
csiv2Policy });
org.omg.CORBA.Object corbaRef =
homeReferenceFactory.createReference(homeRepositoryIds[0]);
((EjbHomeCorbaServant)homeServant).setHomeHandle(
new HomeHandleImplIIOP(corbaRef));
ejbHome = (EJBHome)PortableRemoteObject.narrow(corbaRef, EJBHome.class);
if (container.getBeanMetaData() instanceof EntityMetaData) {
beanServantRegistry =
servantRegistries.getServantRegistry(registryWithPersistentPOA);
Class pkClass;
EntityMetaData metaData = (EntityMetaData)container.getBeanMetaData();
String pkClassName = metaData.getPrimaryKeyClass();
try {
if (pkClassName != null)
pkClass = container.getClassLoader().loadClass(pkClassName);
else
pkClass = container.getClassLoader().loadClass(
metaData.getEjbClass()).getField(
metaData.getPrimKeyField()).getClass();
}
catch (NoSuchFieldException e) {
logger.error("Unable to identify Bean's Primary Key class! "
+ "Did you specify a primary key class and/or field? "
+ "Does that field exist?");
throw new Exception("Primary Key Problem");
}
catch (NullPointerException e) {
logger.error("Unable to identify Bean's Primary Key class! "
+ "Did you specify a primary key class and/or field? "
+ "Does that field exist?");
throw new Exception("Primary Key Problem");
}
ejbMetaData = new EJBMetaDataImplIIOP(
((EJBProxyFactoryContainer)container).getRemoteClass(),
((EJBProxyFactoryContainer)container).getHomeClass(),
pkClass,
false, false, ejbHome);
}
else {
beanServantRegistry =
servantRegistries.getServantRegistry(registryWithTransientPOA);
if (((SessionMetaData)container.getBeanMetaData()).isStateless()) {
ejbMetaData = new EJBMetaDataImplIIOP(
((EJBProxyFactoryContainer)container).getRemoteClass(),
((EJBProxyFactoryContainer)container).getHomeClass(),
null, true, true, ejbHome);
}
else {
ejbMetaData = new EJBMetaDataImplIIOP(
((EJBProxyFactoryContainer)container).getRemoteClass(),
((EJBProxyFactoryContainer)container).getHomeClass(),
null, true, false, ejbHome);
}
}
InterfaceDef beanInterfaceDef = null;
if (iri != null) {
Repository ir = iri.getReference();
beanInterfaceDef =
InterfaceDefHelper.narrow(ir.lookup_id(beanRepositoryIds[0]));
}
String beanServantLoggerName =
EjbObjectCorbaServant.class.getName() + '.'+ jndiName;
ServantWithMBeanServer beanServant =
new EjbObjectCorbaServant(container.getJmxName(),
container.getClassLoader(),
poaCurrent,
beanMethodMap,
beanRepositoryIds,
beanInterfaceDef,
Logger.getLogger(beanServantLoggerName));
beanReferenceFactory =
beanServantRegistry.bind(beanServantName(jndiName),
beanServant,
new Policy[] { codebasePolicy,
sslPolicy,
csiv2Policy });
logger.info("EJBHome reference for " + jndiName + ":\n"
+ orb.object_to_string((org.omg.CORBA.Object)ejbHome));
useJNPContext = MetaData.getOptionalChildBooleanContent(
proxyFactoryConfig, "register-ejbs-in-jnp-context");
Context initialContext = new InitialContext();
if (useJNPContext) {
String jnpContext =
MetaData.getOptionalChildContent(proxyFactoryConfig,
"jnp-context");
if (jnpContext != null && !jnpContext.equals("")) {
jnpName = jnpContext + "/" + jndiName;
}
else {
jnpName = jndiName;
}
try {
Util.rebind(initialContext,
jnpName,
new Reference(
"javax.ejb.EJBHome",
new StringRefAddr("IOR",
orb.object_to_string(
(org.omg.CORBA.Object)ejbHome)),
IIOPHomeFactory.class.getName(),
null));
logger.info("Home IOR for " + container.getBeanMetaData().getEjbName()
+ " bound to " + jnpName + " in JNP naming service");
}
catch (NamingException e) {
throw new Exception("Cannot bind EJBHome in JNDI:\n" + e);
}
}
NamingContextExt corbaContext = null;
try {
corbaContext = NamingContextExtHelper.narrow((org.omg.CORBA.Object)
initialContext.lookup("java:/" +
CorbaNamingService.NAMING_NAME));
}
catch (NamingException e) {
throw new Exception("Cannot lookup java:/" +
CorbaNamingService.NAMING_NAME + ":\n" + e);
}
try {
rebind(corbaContext, jndiName, (org.omg.CORBA.Object)ejbHome);
logger.info("Home IOR for " + container.getBeanMetaData().getEjbName()
+ " bound to " + jndiName + " in CORBA naming service");
}
catch (Exception e) {
logger.error("Cannot bind EJBHome in CORBA naming service:", e);
throw new Exception("Cannot bind EJBHome in CORBA naming service:\n"
+ e);
}
}
public void stop()
{
try {
Context initialContext = new InitialContext();
if (useJNPContext) {
try {
initialContext.unbind(jnpName);
}
catch (NamingException namingException) {
logger.error("Cannot unbind EJBHome from JNDI", namingException);
}
}
NamingContextExt corbaContext =
NamingContextExtHelper.narrow((org.omg.CORBA.Object)
initialContext.lookup("java:/"
+ CorbaNamingService.NAMING_NAME));
try {
NameComponent[] name = corbaContext.to_name(jndiName);
corbaContext.unbind(name);
}
catch (InvalidName invalidName) {
logger.error("Cannot unregister EJBHome from CORBA naming service",
invalidName);
}
catch (NotFound notFound) {
logger.error("Cannot unregister EJBHome from CORBA naming service",
notFound);
}
catch (CannotProceed cannotProceed) {
logger.error("Cannot unregister EJBHome from CORBA naming service",
cannotProceed);
}
}
catch (NamingException namingException) {
logger.error("Unexpected error in JNDI lookup", namingException);
}
try {
homeServantRegistry.unbind(homeServantName(jndiName));
}
catch (Exception e) {
logger.error("Cannot deactivate home servant", e);
}
try {
beanServantRegistry.unbind(beanServantName(jndiName));
}
catch (Exception e) {
logger.error("Cannot deactivate bean servant", e);
}
if (iri != null) {
iri.shutdown();
}
}
public void destroy()
{
}
public void setInvokerMetaData(InvokerProxyBindingMetaData imd)
{
invokerMetaData = imd;
}
public void setInvokerBinding(String binding)
{
jndiName = binding;
}
public boolean isIdentical(Container container, Invocation mi)
{
EJBObject other = (EJBObject) mi.getArguments()[0];
if (other == null)
return false;
EJBObject me;
if (container instanceof StatelessSessionContainer)
me = (EJBObject) getStatelessSessionEJBObject();
else if (container instanceof StatefulSessionContainer)
me = (EJBObject) getStatefulSessionEJBObject(mi.getId());
else if (container instanceof EntityContainer)
me = (EJBObject) getEntityEJBObject(mi.getId());
else
return false;
Stub meStub = (Stub) me;
Stub otherStub = (Stub) other;
return meStub._is_equivalent(otherStub);
}
public EJBMetaData getEJBMetaData()
{
return ejbMetaData;
}
public Object getEJBHome()
{
return ejbHome;
}
public Object getStatelessSessionEJBObject()
{
try {
return (EJBObject)PortableRemoteObject.narrow(
beanReferenceFactory.createReference(beanRepositoryIds[0]),
EJBObject.class);
}
catch (Exception e) {
throw new RuntimeException("Unable to create reference to EJBObject\n"
+ e);
}
}
public Object getStatefulSessionEJBObject(Object id)
{
try {
return (EJBObject)PortableRemoteObject.narrow(
beanReferenceFactory.createReferenceWithId(
id,
beanRepositoryIds[0]),
EJBObject.class);
}
catch (Exception e) {
throw new RuntimeException("Unable to create reference to EJBObject\n"
+ e);
}
}
public Object getEntityEJBObject(Object id)
{
if (logger.isTraceEnabled()) {
logger.trace("getEntityEJBObject(), id class is "
+ id.getClass().getName());
}
try {
Object ejbObject = (id == null ? null :
(EJBObject)PortableRemoteObject.narrow(
beanReferenceFactory.createReferenceWithId(id, beanRepositoryIds[0]),
EJBObject.class));
return ejbObject;
}
catch (Exception e) {
throw new RuntimeException("Unable to create reference to EJBObject\n"
+ e);
}
}
public Collection getEntityCollection(Collection ids)
{
if (logger.isTraceEnabled()) {
logger.trace("entering getEntityCollection()");
}
Collection collection = new ArrayList(ids.size());
Iterator idEnum = ids.iterator();
while(idEnum.hasNext()) {
collection.add(getEntityEJBObject(idEnum.next()));
}
if (logger.isTraceEnabled()) {
logger.trace("leaving getEntityCollection()");
}
return collection;
}
public static String rmiRepositoryId(Class clz)
{
return "RMI:" + clz.getName() + ":0000000000000000";
}
public static void rebind(NamingContextExt ctx,
String strName, org.omg.CORBA.Object obj)
throws Exception
{
NameComponent[] name = ctx.to_name(strName);
NamingContext intermediateCtx = ctx;
for (int i = 0; i < name.length - 1; i++ ) {
NameComponent[] relativeName = new NameComponent[] { name[i] };
try {
intermediateCtx = NamingContextHelper.narrow(
intermediateCtx.resolve(relativeName));
}
catch (NotFound e) {
intermediateCtx = intermediateCtx.bind_new_context(relativeName);
}
}
intermediateCtx.rebind(new NameComponent[] { name[name.length - 1] },
obj);
}
private static String homeServantName(String jndiName)
{
return "EJBHome/" + jndiName;
}
private static String beanServantName(String jndiName)
{
return "EJBObject/" + jndiName;
}
}