/* * UserInterfaceMain.java * * Created on 9. Oktober 2003, 19:50 */ package org.gudy.azureus2.ui.common; import java.io.FileReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.StringTokenizer; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.apache.log4j.Appender; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.varia.DenyAllFilter; import com.aelitis.azureus.core.*; import com.aelitis.azureus.core.impl.AzureusCoreSingleInstanceClient; import com.aelitis.azureus.launcher.Launcher; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.util.Constants; import org.gudy.azureus2.ui.common.IUserInterface; import org.gudy.azureus2.ui.common.UserInterfaceFactory; /** * * @author Tobias Minich */ public class Main { public static String DEFAULT_UI = "swt"; public static StartServer start = null; protected static AzureusCore core; private static CommandLine parseCommands(String[] args, boolean constart) { if (args==null) return null; CommandLineParser parser = new PosixParser(); Options options = new Options(); options.addOption("h", "help", false, "Show this help."); OptionBuilder.withLongOpt("exec"); OptionBuilder.hasArg(); OptionBuilder.withArgName("file"); OptionBuilder.withDescription("Execute script file. The file should end with 'logout', otherwise the parser thread doesn't stop."); options.addOption( OptionBuilder.create('e')); OptionBuilder.withLongOpt("command"); OptionBuilder.hasArg(); OptionBuilder.withArgName("command"); OptionBuilder.withDescription("Execute single script command. Try '-c help' for help on commands."); options.addOption(OptionBuilder.create('c')); OptionBuilder.withLongOpt("ui"); 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)."); OptionBuilder.withArgName("uis"); OptionBuilder.hasArg(); options.addOption(OptionBuilder.create('u')); CommandLine commands = null; try { commands = parser.parse(options, args, true); } catch( ParseException exp ) { Logger.getLogger("azureus2").error("Parsing failed. Reason: " + exp.getMessage(), exp); if (constart) System.exit(2); } if ( commands != null && commands.hasOption('h')) { if (constart) { HelpFormatter hf = new HelpFormatter(); 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); System.exit(0); } } return commands; } public static void initRootLogger() { if (Logger.getRootLogger().getAppender("ConsoleAppender")==null) { Appender app; app = new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)); app.setName("ConsoleAppender"); app.addFilter( new DenyAllFilter() ); //'log off' by default Logger.getRootLogger().addAppender(app); } } public static void main(String[] args) { if(Launcher.checkAndLaunch(Main.class, args)) return; // This *has* to be done first as it sets system properties that are read and cached by Java COConfigurationManager.preInitialise(); String mi_str = System.getProperty( "MULTI_INSTANCE" ); boolean mi = mi_str != null && mi_str.equalsIgnoreCase("true"); initRootLogger(); try{ CommandLine commands = parseCommands(args, true); if ( commands != null && directLaunch( args, commands )){ return; } // don't create core until we know we really need it if( mi ){ System.out.println( "MULTI_INSTANCE enabled" ); core = AzureusCoreFactory.create(); processArgs(args, core, commands); return; } start = new StartServer(); if ((start == null) || (start.getServerState()==StartServer.STATE_FAULTY)) { new StartSocket( args ); }else{ core = AzureusCoreFactory.create(); start.start(); processArgs(args, core, commands); } }catch( AzureusCoreException e ){ System.out.println( "Start fails:" ); e.printStackTrace(); } } public static void shutdown() { if (start!=null){ start.stopIt(); } if ( core != null ){ try{ core.stop(); }catch( AzureusCoreException e ){ System.out.println( "Stop fails:" ); e.printStackTrace(); } } SimpleDateFormat temp = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"); Logger.getLogger("azureus2").fatal("Azureus stopped at "+temp.format(new Date())); //System.exit(0); - we don't want to force quit, wait until other threads have completed // so that resume data etc is saved.... } public static boolean directLaunch( String[] args, CommandLine commands) { // frig to support launch of SWT ui via this means pending a proper rewrite // of this stuff if ( commands.hasOption('u')) { String uinames = commands.getOptionValue('u'); if ( uinames.indexOf(',') != -1 ){ return( false ); } if ( !uinames.equalsIgnoreCase( DEFAULT_UI )){ return( false ); } } try{ String uiclass = "org.gudy.azureus2.ui." + DEFAULT_UI + ".Main"; Class main_class = Class.forName( uiclass ); Method main_method = main_class.getMethod( "main", new Class[]{ String[].class }); main_method.invoke( null, new Object[]{ commands.getArgs()}); return( true ); }catch( Throwable e ){ e.printStackTrace(); return( false ); } } public static void processArgs( String[] args, AzureusCore new_core, CommandLine commands) { if (commands==null) { commands = parseCommands(args, false); } if (commands!=null && ( args.length > 0 || new_core != null)) { if (UIConst.UIS == null) { UIConst.UIS = new HashMap(); } if (commands.hasOption('u')) { String uinames = commands.getOptionValue('u'); if (uinames.indexOf(',')==-1) { if (!UIConst.UIS.containsKey(uinames)) UIConst.UIS.put(uinames,UserInterfaceFactory.getUI(uinames)); } else { StringTokenizer stok = new StringTokenizer(uinames, ","); while (stok.hasMoreTokens()) { String uin = stok.nextToken(); if (!UIConst.UIS.containsKey(uin)) UIConst.UIS.put(uin,UserInterfaceFactory.getUI(uin)); } } } else { if (UIConst.UIS.isEmpty() && !commands.hasOption('c') && !commands.hasOption('e')) UIConst.UIS.put(DEFAULT_UI, UserInterfaceFactory.getUI(DEFAULT_UI)); } Iterator uis = UIConst.UIS.values().iterator(); boolean isFirst = true; String [] theRest = commands.getArgs(); while (uis.hasNext()) { IUserInterface ui = (IUserInterface) uis.next(); ui.init(isFirst, (UIConst.UIS.size()>1)); theRest = ui.processArgs(theRest); isFirst = false; } if ( new_core != null ){ SimpleDateFormat temp = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"); UIConst.startTime = new Date(); Logger.getLogger("azureus2").fatal("Azureus started at "+temp.format(UIConst.startTime)); UIConst.setAzureusCore( new_core ); } uis = UIConst.UIS.values().iterator(); while (uis.hasNext()) ((IUserInterface) uis.next()).startUI(); Class clConsoleInput; Constructor conConsoleInput =null; try { clConsoleInput = Class.forName("org.gudy.azureus2.ui.console.ConsoleInput"); // change this and you'll need to change the parameters below.... Class params[] = {String.class, AzureusCore.class, Reader.class, PrintStream.class, Boolean.class}; conConsoleInput=clConsoleInput.getConstructor(params); } catch (Exception e) { e.printStackTrace(); } if (commands.hasOption('e')) { if (conConsoleInput != null) { try { Object params[] = {commands.getOptionValue('e'), new_core, new FileReader(commands.getOptionValue('e')), System.out, Boolean.FALSE}; conConsoleInput.newInstance(params); } catch (java.io.FileNotFoundException e) { Logger.getLogger("azureus2").error("Script file not found: "+e.toString()); } catch (Exception e) { Logger.getLogger("azureus2").error("Error invocating the script processor: "+e.toString()); } } else Logger.getLogger("azureus2").error("ConsoleInput class not found. You need the console ui package to use '-e'"); } if (commands.hasOption('c')) { if (conConsoleInput != null) { String comm = commands.getOptionValue('c'); comm+="\nlogout\n"; Object params[] = {commands.getOptionValue('c'), UIConst.getAzureusCore(), new StringReader(comm), System.out, Boolean.FALSE}; try { conConsoleInput.newInstance(params); } catch (Exception e) { Logger.getLogger("azureus2").error("Error invocating the script processor: "+e.toString()); } } else Logger.getLogger("azureus2").error("ConsoleInput class not found. You need the console ui package to use '-e'"); } openTorrents(theRest); } else { Logger.getLogger("azureus2").error("No commands to process"); } } public static void openTorrents(String[] torrents) { if ((UIConst.UIS!=null) && (!UIConst.UIS.isEmpty()) && (torrents.length>0)) { for(int l=0; l<torrents.length; l++) { ((IUserInterface) UIConst.UIS.values().toArray()[0]).openTorrent(torrents[l]); } } } public static class StartSocket { public StartSocket(String args[]) { Socket sck = null; PrintWriter pw = null; try { System.out.println("StartSocket: passing startup args to already-running process."); // NOTE - this formatting is also used by AzureusCoreSingleInstanceClient and other org.gudy.azureus2.ui.swt.StartSocket sck = new Socket("127.0.0.1", Constants.INSTANCE_PORT ); pw = new PrintWriter(new OutputStreamWriter(sck.getOutputStream())); StringBuffer buffer = new StringBuffer(AzureusCoreSingleInstanceClient.ACCESS_STRING+";args;"); for(int i = 0 ; i < args.length ; i++) { String arg = args[i].replaceAll("&","&&").replaceAll(";","&;"); buffer.append(arg); buffer.append(';'); } pw.println(buffer.toString()); pw.flush(); } catch(Exception e) { e.printStackTrace(); } finally { try { if (pw != null) pw.close(); } catch (Exception e) { } try { if (sck != null) sck.close(); } catch (Exception e) { } } } } }