/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ejb3.iiop;
import java.lang.reflect.Method;
import java.security.Principal;
import java.util.HashMap;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.jboss.ejb3.Container;
import org.jboss.ejb3.SessionContainer;
import org.jboss.ejb3.stateful.StatefulContainer;
import org.jboss.ejb3.stateless.StatelessContainer;
import org.jboss.iiop.CorbaORB;
import org.jboss.iiop.csiv2.SASCurrent;
import org.jboss.iiop.rmi.AttributeAnalysis;
import org.jboss.iiop.rmi.InterfaceAnalysis;
import org.jboss.iiop.rmi.OperationAnalysis;
import org.jboss.iiop.rmi.RmiIdlUtil;
import org.jboss.iiop.rmi.marshal.strategy.SkeletonStrategy;
import org.jboss.invocation.iiop.ReferenceData;
import org.jboss.logging.Logger;
import org.jboss.security.SecurityAssociation;
import org.jboss.security.SimplePrincipal;
import org.jboss.tm.TransactionManagerLocator;
import org.jboss.tm.iiop.TxServerInterceptor;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.InterfaceDef;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.InvokeHandler;
import org.omg.CORBA.portable.OutputStream;
import org.omg.CORBA.portable.ResponseHandler;
import org.omg.PortableServer.Current;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.Servant;
/**
* Comment
*
* @author <a href="mailto:carlo.dewolf@jboss.com">Carlo de Wolf</a>
* @version $Revision: 60233 $
*/
public class BeanCorbaServant extends Servant
implements InvokeHandler
{
private static final Logger log = Logger.getLogger(BeanCorbaServant.class);
private final IORFactory factory;
private final Current poaCurrent;
private final Container container;
private final InterfaceDef interfaceDef;
private final String repositoryIds[];
private SASCurrent sasCurrent;
private HashMap<String, SkeletonStrategy> methodMap;
protected BeanCorbaServant(IORFactory factory, Current poaCurrent, Container container, InterfaceDef interfaceDef, InterfaceAnalysis interfaceAnalysis)
{
assert factory != null;
assert poaCurrent != null;
assert container != null;
assert container instanceof SessionContainer; // see invoke
assert interfaceDef != null;
assert interfaceAnalysis != null;
this.factory = factory;
this.poaCurrent = poaCurrent;
this.container = container;
this.interfaceDef = interfaceDef;
this.repositoryIds = interfaceAnalysis.getAllTypeIds();
try
{
this.sasCurrent = (SASCurrent) CorbaORB.getInstance().resolve_initial_references("SASCurrent");
}
catch (InvalidName e)
{
log.warn("Can't find SASCurrent");
this.sasCurrent = null;
}
this.methodMap = new HashMap<String, SkeletonStrategy>();
AttributeAnalysis[] attrs = interfaceAnalysis.getAttributes();
for (int i = 0; i < attrs.length; i++) {
OperationAnalysis op = attrs[i].getAccessorAnalysis();
log.debug(" " + op.getJavaName() + ": " + op.getIDLName());
methodMap.put(op.getIDLName(),
new SkeletonStrategy(op.getMethod()));
op = attrs[i].getMutatorAnalysis();
if (op != null) {
log.debug(" " + op.getJavaName() + ": " + op.getIDLName());
methodMap.put(op.getIDLName(),
new SkeletonStrategy(op.getMethod()));
}
}
OperationAnalysis[] ops = interfaceAnalysis.getOperations();
for (int i = 0; i < ops.length; i++) {
log.debug(" " + ops[i].getJavaName() + ": " + ops[i].getIDLName());
methodMap.put(ops[i].getIDLName(),
new SkeletonStrategy(ops[i].getMethod()));
}
}
@Override
public String[] _all_interfaces(POA poa, byte[] objectId)
{
return (String[]) repositoryIds.clone();
}
/**
* Returns an IR object describing the bean's remote interface.
*/
@Override
public org.omg.CORBA.Object _get_interface_def()
{
if (interfaceDef != null)
return interfaceDef;
else
return super._get_interface_def();
}
public OutputStream _invoke(String opName, InputStream in, ResponseHandler handler) throws SystemException
{
log.trace("invoke: " + opName);
SkeletonStrategy op = (SkeletonStrategy) methodMap.get(opName);
if (op == null)
{
log.debug("Unable to find opname '" + opName + "' valid operations:" + methodMap.keySet());
throw new BAD_OPERATION(opName);
}
org.omg.CORBA_2_3.portable.OutputStream out;
try
{
Object id = ReferenceData.extractObjectId(poaCurrent.get_object_id());
log.trace("id = " + id);
Transaction tx = TxServerInterceptor.getCurrentTransaction();
log.trace("tx = " + tx);
if(sasCurrent != null)
{
byte username[] = sasCurrent.get_incoming_username();
byte credentials[] = sasCurrent.get_incoming_password();
byte principalName[] = sasCurrent.get_incoming_principal_name();
if(username != null && username.length > 0)
{
String name = new String(username, "UTF-8");
int domainIndex = name.lastIndexOf("@");
if(domainIndex > 0)
name = name.substring(0, domainIndex);
log.debug("username = " + name);
Principal principal = new SimplePrincipal(name);
SecurityAssociation.setPrincipal(principal);
}
if(credentials != null && credentials.length > 0)
{
SecurityAssociation.setCredential(new String(credentials, "UTF-8").toCharArray());
}
if(principalName != null && principalName.length > 0)
log.warn("principalName = " + new String(principalName, "UTF-8")); // FIXME: implement principalName support
}
Object args[] = op.readParams((org.omg.CORBA_2_3.portable.InputStream) in);
Object retVal = invoke(tx, id, op.getMethod(), args);
out = (org.omg.CORBA_2_3.portable.OutputStream) handler.createReply();
if(op.isNonVoid())
op.writeRetval(out, retVal);
}
catch(Throwable t)
{
// TODO: check log level before stacktrace?
t.printStackTrace();
if(t instanceof Exception)
{
Exception e = (Exception) t;
RmiIdlUtil.rethrowIfCorbaSystemException(e);
out = (org.omg.CORBA_2_3.portable.OutputStream) handler.createExceptionReply();
op.writeException(out, e);
}
else
throw new RuntimeException("NYI");
}
return out;
}
private TransactionManager getTransactionManager()
{
//return TxUtil.getTransactionManager();
return TransactionManagerLocator.getInstance().locate();
}
private Object invoke(Object id, Method method, Object args[]) throws Throwable
{
// TODO: Support other containers beside Stateless and Stateful?
return ((SessionContainer) container).invoke(factory, id, method, args, null);
}
private Object invoke(Transaction tx, Object id, Method method, Object args[]) throws Throwable
{
if(tx == null)
return invoke(id, method, args);
// FIXME: refactor TxServerInterceptor so that it pushed the tpc into the invocation like ClientTxPropegationInterceptor
// this would require the localInvoke to be also refactored, so that it uses invocation instead of localInvoke.
TransactionManager tm = getTransactionManager();
// see TxPropagationInterceptor
if(tm.getTransaction() != null)
throw new RuntimeException("cannot import a transaction context when a transaction is already associated with the thread");
tm.resume(tx);
try
{
return invoke(id, method, args);
}
finally
{
tm.suspend();
}
}
}
|