Java Source Code: org.gudy.azureus2.ui.common.Main


   1: /*
   2:  * UserInterfaceMain.java
   3:  *
   4:  * Created on 9. Oktober 2003, 19:50
   5:  */
   6: 
   7: package org.gudy.azureus2.ui.common;
   8: 
   9: import java.io.FileReader;
  10: import java.io.OutputStreamWriter;
  11: import java.io.PrintStream;
  12: import java.io.PrintWriter;
  13: import java.io.Reader;
  14: import java.io.StringReader;
  15: 
  16: import java.lang.reflect.Constructor;
  17: import java.lang.reflect.Method;
  18: import java.net.Socket;
  19: 
  20: import java.text.SimpleDateFormat;
  21: 
  22: import java.util.Date;
  23: import java.util.HashMap;
  24: import java.util.Iterator;
  25: import java.util.StringTokenizer;
  26: 
  27: import org.apache.commons.cli.CommandLine;
  28: import org.apache.commons.cli.CommandLineParser;
  29: import org.apache.commons.cli.HelpFormatter;
  30: import org.apache.commons.cli.OptionBuilder;
  31: import org.apache.commons.cli.Options;
  32: import org.apache.commons.cli.ParseException;
  33: import org.apache.commons.cli.PosixParser;
  34: 
  35: import org.apache.log4j.Appender;
  36: import org.apache.log4j.ConsoleAppender;
  37: import org.apache.log4j.Logger;
  38: import org.apache.log4j.PatternLayout;
  39: import org.apache.log4j.varia.DenyAllFilter;
  40: 
  41: import com.aelitis.azureus.core.*;
  42: import com.aelitis.azureus.core.impl.AzureusCoreSingleInstanceClient;
  43: 
  44: import org.gudy.azureus2.core3.config.COConfigurationManager;
  45: import org.gudy.azureus2.ui.common.IUserInterface;
  46: import org.gudy.azureus2.ui.common.UserInterfaceFactory;
  47: /**
  48:  *
  49:  * @author  Tobias Minich
  50:  */
  51:	  public class Main {
  52:  
  53:  public static String DEFAULT_UI = "swt";
  54:  
  55:  public static StartServer start = null;
  56:  
  57:  protected static AzureusCore    core;
  58:  
  59:	    private static CommandLine parseCommands(String[] args, boolean constart) {
  60:    
  61:    if (args==null)
  62:      return null;
  63:    
  64:    CommandLineParser parser = new PosixParser();
  65:    Options options = new Options();
  66:    options.addOption("h", "help", false, "Show this help.");
  67: 
  68:    OptionBuilder.withLongOpt("exec");
  69:    OptionBuilder.hasArg();
  70:    OptionBuilder.withArgName("file");
  71:    OptionBuilder.withDescription("Execute script file. The file should end with 'logout', otherwise the parser thread doesn't stop.");
  72:    options.addOption( OptionBuilder.create('e'));
  73:    
  74:    OptionBuilder.withLongOpt("command");
  75:    OptionBuilder.hasArg();
  76:    OptionBuilder.withArgName("command");
  77:    OptionBuilder.withDescription("Execute single script command. Try '-c help' for help on commands.");
  78:    options.addOption(OptionBuilder.create('c'));
  79:    
  80:    OptionBuilder.withLongOpt("ui");
  81:    OptionBuilder.withDescription("Run <uis>. ',' separated list of user interfaces to run. The first one given will respond to requests without determinable source UI (e.g. further torrents added via command line).");
  82:    OptionBuilder.withArgName("uis");
  83:    OptionBuilder.hasArg();
  84:    options.addOption(OptionBuilder.create('u'));
  85:    
  86:    CommandLine commands = null;
  87:	      try {
  88:      commands = parser.parse(options, args, true);
  89:    } catch( ParseException exp ) {
  90:      Logger.getLogger("azureus2").error("Parsing failed.  Reason: " + exp.getMessage(), exp);
  91:      if (constart)
  92:        System.exit(2);
  93:    }
  94:	      if (commands.hasOption('h')) {
  95:	        if (constart) {
  96:        HelpFormatter hf = new HelpFormatter();
  97:        hf.printHelp("java org.gudy.azureus2.ui.common.Main", "Optionally you can put torrent files to add to the end of the command line.\r\n", options, "Available User Interfaces: swt (default), web, console\r\nThe default interface is not started if you give either the '-e' or '-c' option (But you can start it by hand with '-u').", true);
  98:        System.exit(0);
  99:      }
 100:    }
 101:    return commands;
 102:  }
 103:  
 104:	    public static void initRootLogger() {
 105:	      if (Logger.getRootLogger().getAppender("ConsoleAppender")==null) {
 106:      Appender app;
 107:      app = new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN));
 108:      app.setName("ConsoleAppender");
 109:      app.addFilter( new DenyAllFilter() );  //'log off' by default
 110:      Logger.getRootLogger().addAppender(app);
 111:    }
 112:  }
 113:  
 114:  public static void 
 115:  main(
 116:        String[] args ) 
 117:	    {
 118:        // This *has* to be done first as it sets system properties that are read and cached by Java
 119:        
 120:    COConfigurationManager.preInitialise();
 121: 
 122:    String  mi_str = System.getProperty( "MULTI_INSTANCE" );
 123:    
 124:    boolean mi = mi_str != null && mi_str.equalsIgnoreCase("true");
 125:
 126:    initRootLogger();
 127:    
 128:	      try{
 129:           CommandLine commands = parseCommands(args, true);
 130:
 131:	             if ( commands != null && directLaunch( args, commands )){
 132:               
 133:               return;
 134:           }
 135:            
 136:               // don't create core until we know we really need it
 137:           
 138:	          if( mi ){
 139:            
 140:            System.out.println( "MULTI_INSTANCE enabled" );
 141:            
 142:               core = AzureusCoreFactory.create();
 143:
 144:            processArgs(args, core, commands);
 145:            
 146:            return;
 147:        }
 148:      
 149:        start = new StartServer();
 150:      
 151:	          if ((start == null) || (start.getServerState()==StartServer.STATE_FAULTY)) {
 152:            
 153:     
 154:            new StartSocket( args );
 155:            
 156:        }else{
 157:            
 158:       
 159:          core = AzureusCoreFactory.create();
 160:
 161:
 162:          start.start();
 163:          
 164:          processArgs(args, core, commands);
 165:        }
 166:    }catch( AzureusCoreException e ){
 167:        
 168:        System.out.println( "Start fails:" );
 169:        
 170:        e.printStackTrace();
 171:    }
 172:  }
 173:  
 174:	    public static void shutdown() {
 175:	      if (start!=null){
 176:        
 177:      start.stopIt();
 178:    }
 179:    
 180:	      if ( core != null ){
 181:	          try{
 182:            core.stop();
 183:            
 184:        }catch( AzureusCoreException e ){
 185:            
 186:            System.out.println( "Stop fails:" );
 187:            
 188:            e.printStackTrace();
 189:        }
 190:    }
 191:    
 192:    SimpleDateFormat temp = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
 193:    Logger.getLogger("azureus2").fatal("Azureus stopped at "+temp.format(new Date()));
 194:    //System.exit(0);    - we don't want to force quit, wait until other threads have completed
 195:    // so that resume data etc is saved....
 196:  }
 197:  
 198:      public static boolean 
 199:      directLaunch(
 200:          String[]         args, 
 201:          CommandLine     commands) 
 202:	        {
 203:              // frig to support launch of SWT ui via this means pending a proper rewrite
 204:              // of this stuff
 205:          
 206:	            if ( commands.hasOption('u')) {
 207:          
 208:              String uinames = commands.getOptionValue('u');
 209:       
 210:	                if ( uinames.indexOf(',') != -1 ){
 211:                  
 212:                  return( false );
 213:              }
 214:              
 215:	                if ( !uinames.equalsIgnoreCase( DEFAULT_UI )){
 216:                  
 217:                  return( false );
 218:              }
 219:          }
 220:           
 221:	            try{
 222:              String uiclass = "org.gudy.azureus2.ui." + DEFAULT_UI + ".Main";
 223:         
 224:              Class    main_class = Class.forName( uiclass );
 225:          
 226:              Method main_method = main_class.getMethod( "main", new Class[]{ String[].class });
 227:              
 228:               main_method.invoke( null, new Object[]{ commands.getArgs()});
 229:              
 230:              return( true );
 231:              
 232:          }catch( Throwable e ){
 233:              
 234:              e.printStackTrace();
 235:              
 236:              return( false );
 237:          }
 238:  }
 239:  
 240:  public static void 
 241:  processArgs(
 242:      String[]         args, 
 243:      AzureusCore     new_core, 
 244:    CommandLine     commands) 
 245:	    {
 246:	      if (commands==null) {
 247:      commands = parseCommands(args, false);
 248:    }
 249:	      if (((commands!=null) && (args.length>0)) || (new_core != null)) {
 250:	        if (UIConst.UIS == null) {
 251:        UIConst.UIS = new HashMap();
 252:      }
 253:	        if (commands.hasOption('u')) {
 254:        String uinames = commands.getOptionValue('u');
 255:	          if (uinames.indexOf(',')==-1) {
 256:          if (!UIConst.UIS.containsKey(uinames))
 257:          UIConst.UIS.put(uinames,UserInterfaceFactory.getUI(uinames));
 258:        } else {
 259:          StringTokenizer stok = new StringTokenizer(uinames, ",");
 260:	            while (stok.hasMoreTokens()) {
 261:            String uin = stok.nextToken();
 262:            if (!UIConst.UIS.containsKey(uin))
 263:              UIConst.UIS.put(uin,UserInterfaceFactory.getUI(uin));
 264:          }
 265:        }
 266:      } else {
 267:        if (UIConst.UIS.isEmpty() && !commands.hasOption('c') && !commands.hasOption('e'))
 268:          UIConst.UIS.put(DEFAULT_UI, UserInterfaceFactory.getUI(DEFAULT_UI));
 269:      }
 270:
 271:      Iterator uis = UIConst.UIS.values().iterator();
 272:      boolean isFirst = true;
 273:      String [] theRest = commands.getArgs();
 274:	        while (uis.hasNext()) {
 275:        IUserInterface ui = (IUserInterface) uis.next();
 276:        ui.init(isFirst, (UIConst.UIS.size()>1));
 277:        theRest = ui.processArgs(theRest);
 278:        isFirst = false;
 279:      }
 280:
 281:	        if ( new_core != null ){
 282:          
 283:        SimpleDateFormat temp = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
 284:        
 285:        UIConst.startTime = new Date();
 286:        
 287:        Logger.getLogger("azureus2").fatal("Azureus started at "+temp.format(UIConst.startTime));
 288:        
 289:	          try{
 290:            new_core.start();
 291:            
 292:            UIConst.setAzureusCore( new_core );
 293:            
 294:        }catch( AzureusCoreException e ){
 295:            
 296:              Logger.getLogger("azureus2").error("Start fails", e);
 297:           
 298:        }
 299:      }
 300:
 301:      uis = UIConst.UIS.values().iterator();
 302:      while (uis.hasNext())
 303:        ((IUserInterface) uis.next()).startUI();
 304:           
 305:      Class clConsoleInput;
 306:      Constructor conConsoleInput =null;
 307:	        try {
 308:          clConsoleInput = Class.forName("org.gudy.azureus2.ui.console.ConsoleInput");
 309:          
 310:              // change this and you'll need to change the parameters below....
 311:          
 312:          Class params[] = {String.class, AzureusCore.class, Reader.class, PrintStream.class, Boolean.class};
 313:          
 314:          conConsoleInput=clConsoleInput.getConstructor(params);
 315:      } catch (Exception e) {
 316:          e.printStackTrace();
 317:      }
 318:	        if (commands.hasOption('e')) {
 319:	            if (conConsoleInput != null) {
 320:	              try {
 321:                Object params[] = {commands.getOptionValue('e'), new_core, new FileReader(commands.getOptionValue('e')), System.out, Boolean.FALSE};
 322:                conConsoleInput.newInstance(params);
 323:            } catch (FileNotFoundException e) {
 324:              Logger.getLogger("azureus2").error("Script file not found: "+e.toString());
 325:            } catch (Exception e) {
 326:                Logger.getLogger("azureus2").error("Error invocating the script processor: "+e.toString());
 327:            }
 328:          } else
 329:              Logger.getLogger("azureus2").error("ConsoleInput class not found. You need the console ui package to use '-e'");
 330:      }
 331:      
 332:	        if (commands.hasOption('c')) {
 333:	            if (conConsoleInput != null) {
 334:            String comm = commands.getOptionValue('c');
 335:            comm+="\nlogout\n";
 336:            Object params[] = {commands.getOptionValue('c'), UIConst.getAzureusCore(), new StringReader(comm), System.out, Boolean.FALSE};
 337:	              try {
 338:                conConsoleInput.newInstance(params);
 339:            } catch (Exception e) {
 340:                Logger.getLogger("azureus2").error("Error invocating the script processor: "+e.toString());
 341:            }
 342:          } else
 343:              Logger.getLogger("azureus2").error("ConsoleInput class not found. You need the console ui package to use '-e'");
 344:      }
 345:      
 346:      openTorrents(theRest);
 347:    } else {
 348:      Logger.getLogger("azureus2").error("No commands to process");
 349:    }
 350:  }
 351:  
 352:	    public static void openTorrents(String[] torrents) {
 353:	      if ((UIConst.UIS!=null) && (!UIConst.UIS.isEmpty()) && (torrents.length>0)) {
 354:	        for(int l=0; l<torrents.length; l++) {
 355:        ((IUserInterface) UIConst.UIS.values().toArray()[0]).openTorrent(torrents[l]);
 356:      }
 357:    }
 358:  }
 359:  
 360:	    public static class StartSocket {
 361:	      public StartSocket(String args[]) {
 362:      Socket sck = null;
 363:      PrintWriter pw = null;
 364:	        try {
 365:        System.out.println("StartSocket: passing startup args to already-running process.");
 366:        
 367:        // NOTE - this formatting is also used by AzureusCoreSingleInstanceClient and other org.gudy.azureus2.ui.swt.StartSocket
 368:        
 369:        sck = new Socket("127.0.0.1",6880);
 370:        pw = new PrintWriter(new OutputStreamWriter(sck.getOutputStream()));
 371:        StringBuffer buffer = new StringBuffer(AzureusCoreSingleInstanceClient.ACCESS_STRING+";args;");
 372:	          for(int i = 0 ; i < args.length ; i++) {
 373:          String arg = args[i].replaceAll("&","&&").replaceAll(";","&;");
 374:          buffer.append(arg);
 375:          buffer.append(';');
 376:        }
 377:        pw.println(buffer.toString());
 378:        pw.flush();
 379:      } catch(Exception e) {
 380:        e.printStackTrace();
 381:      } finally {
 382:	          try {
 383:          if (pw != null)
 384:            pw.close();
 385:        } catch (Exception e) {
 386:        }
 387:	          try {
 388:          if (sck != null)
 389:            sck.close();
 390:        } catch (Exception e) {
 391:        }
 392:      }
 393:    }
 394:  }
 395:}