package dmg.cells.services.login ;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import dmg.cells.nucleus.CellAdapter;
import dmg.cells.nucleus.CellMessage;
import dmg.cells.nucleus.CellNucleus;
import dmg.cells.nucleus.CellShell;
import dmg.util.Gate;
import dmg.util.StreamEngine;
import org.dcache.auth.Subjects;
import org.dcache.util.Args;
/**
*
*
* @author Patrick Fuhrmann
* @version 0.1, 15 Feb 1998
*/
public class LoginCell
extends CellAdapter
implements Runnable {
private static final Logger _log =
LoggerFactory.getLogger(LoginCell.class);
private StreamEngine _engine ;
private BufferedReader _in ;
private PrintWriter _out ;
private InetAddress _host ;
private Subject _subject ;
private Thread _workerThread ;
private CellShell _shell ;
private String _prompt;
private boolean _syncMode = true ;
private Gate _readyGate = new Gate(false) ;
private int _syncTimeout = 10 ;
private int _commandCounter;
private String _lastCommand = "<init>" ;
private Reader _reader;
public LoginCell(String name, StreamEngine engine, Args args)
{
super(name, args);
_engine = engine;
}
@Override
protected void starting() throws Exception
{
_reader = _engine.getReader();
_in = new BufferedReader(_reader);
_out = new PrintWriter(_engine.getWriter());
_subject = _engine.getSubject();
_host = _engine.getInetAddress();
_loadShells(getArgs());
useInterpreter(false);
_prompt = getCellName();
_workerThread = new Thread(this);
}
@Override
protected void started()
{
_workerThread.start();
}
private static final Class<?>[][] _signature = {
{
String.class ,
CellNucleus.class ,
Args.class
} ,
{
CellNucleus.class ,
},
{}
} ;
private void _loadShells( Args args ){
Object [] [] objList = new Object[_signature.length][] ;
for( int i= 0 ; i < objList.length ; i++ ) {
objList[i] = new Object[_signature[i].length];
}
objList[0][0] = _subject ;
objList[0][1] = getNucleus() ;
objList[0][2] = new Args(args);
objList[1][0] = getNucleus() ;
Class<?> c;
Constructor<?> con = null ;
Object o;
for( int i = 0 ; i < args.argc() ; i++ ){
_log.info( "Trying to load shell : "+args.argv(i) ) ;
try{
c = Class.forName( args.argv(i) ) ;
int j ;
for( j = 0 ; j < _signature.length ; j++ ){
try{
con = c.getConstructor( _signature[j] ) ;
break ;
}catch(Exception e){
}
}
if( j == _signature.length ) {
throw new Exception("No constructor found");
}
o = con.newInstance( objList[j] ) ;
addCommandListener( o ) ;
_log.info( "Added : "+args.argv(i) ) ;
}catch(Exception ee ){
_log.warn( "Failed to load shell : "+args.argv(i)+" : "+ee ) ;
if( ee instanceof InvocationTargetException ){
_log.warn( " -> Problem in constructor : "+
((InvocationTargetException)ee).getTargetException() ) ;
}
}
}
}
@Override
public void run(){
if( Thread.currentThread() == _workerThread ){
print( prompt() ) ;
while( true ){
try{
if( ( _lastCommand = _in.readLine() ) == null ) {
break;
}
_commandCounter++ ;
if( execute( _lastCommand ) > 0 ){
//
// we need to close the socket AND
// have to go back to readLine to
// finish the ssh protocol gracefully.
//
try{ _out.close() ; }catch(Exception ee){}
}else{
print( prompt() ) ;
}
}catch( IOException e ){
_log.info("EOF Exception in read line : "+e ) ;
break ;
}catch( Exception e ){
_log.info("I/O Error in read line : "+e ) ;
break ;
}
}
_log.info( "EOS encountered" ) ;
_readyGate.open() ;
kill() ;
}
}
@Override
public void stopped(){
_log.info( "Clean up called" ) ;
println("");
_out.close();
_readyGate.check() ;
_log.info( "finished" ) ;
}
public void println( String str ){
_out.print( str ) ;
if((!str.isEmpty()) &&
( ! str.substring(str.length()-1).equals("\n") ) ) {
_out.println("");
}
_out.flush() ;
}
public void print( String str ){
_out.print( str ) ;
_out.flush() ;
}
public String prompt(){
return _prompt == null ? " .. > " : (_prompt+" > ") ;
}
public int execute( String command ) throws Exception {
if( command.equals("exit") ) {
return 1;
}
println( command( command ) ) ;
return 0 ;
}
//
// the cell implemetation
//
public String toString(){ return Subjects.getDisplayName(_subject) + '@' + _host ; }
@Override
public void getInfo( PrintWriter pw ){
pw.println( " Generic Login Cell" ) ;
pw.println( " User : "+Subjects.getDisplayName(_subject) ) ;
pw.println( " Host : "+_host ) ;
pw.println( " Last Command : "+_lastCommand ) ;
pw.println( " Command Count : "+_commandCounter ) ;
}
@Override
public void messageArrived( CellMessage msg ){
Object obj = msg.getMessageObject() ;
println("");
println( " CellMessage From : "+msg.getSourcePath() ) ;
println( " CellMessage To : "+msg.getDestinationPath() ) ;
println( " CellMessage Class : "+obj.getClass().getName() ) ;
Class<?> c = obj.getClass() ;
Method [] methods = c.getMethods() ;
Object result;
for (Method method : methods) {
if (method.getDeclaringClass().equals(Object.class)) {
continue;
}
if (!method.getName().startsWith("get")) {
continue;
}
if (method.getParameterTypes().length > 0) {
continue;
}
try {
result = method.invoke(obj);
println(" " + method.getName() + " -> " + result);
} catch (IllegalAccessException | InvocationTargetException e) {
println(" " + method.getName() + " -> (???)");
}
}
print( prompt() );
}
}