Package com.aelitis.azureus.core.update.impl

Source Code of com.aelitis.azureus.core.update.impl.AzureusRestarterImpl

/*
* Created on May 16, 2004
* Created by Olivier Chalouhi
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package com.aelitis.azureus.core.update.impl;

import java.io.*;
import java.util.Properties;

import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.platform.PlatformManager;
import org.gudy.azureus2.platform.PlatformManagerFactory;
import org.gudy.azureus2.platform.unix.ScriptAfterShutdown;
import org.gudy.azureus2.platform.win32.access.AEWin32Access;
import org.gudy.azureus2.platform.win32.access.AEWin32Manager;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.platform.PlatformManagerException;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.update.UpdaterUtils;

import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreException;
import com.aelitis.azureus.core.update.AzureusRestarter;

public class
AzureusRestarterImpl
  implements AzureusRestarter
{   
  private static final LogIDs LOGID = LogIDs.CORE;
  private static final String MAIN_CLASS     = "org.gudy.azureus2.update.Updater";
  private static final String UPDATER_JAR   = "Updater.jar";
  private static final String EXE_UPDATER    = "AzureusUpdater.exe";
 
 
  public static final String    UPDATE_PROPERTIES  = "update.properties";

  protected static boolean  restarted    = false;
 
  private static String JAVA_EXEC_DIR = System.getProperty("java.home") +
                                         System.getProperty("file.separator") +
                                         "bin" +
                                         System.getProperty("file.separator");
 
 
  protected AzureusCore  azureus_core;
  protected String    classpath_prefix;
 
  public
  AzureusRestarterImpl(
    AzureusCore    _azureus_core )
  {
    azureus_core  = _azureus_core;
  }
 
  public void
  restart(
    boolean  update_only )
  {
    if ( restarted ){
     
      Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING,
          "AzureusRestarter: already restarted!!!!"));
     
      return;
    }
   
    restarted  = true;
   
    try{
   
      runUpdateProcess( update_only, false );
     
    }catch( Throwable e ){
      // already logged
    }
  }
 
  public void
  updateNow()
 
    throws AzureusCoreException
  {
    if ( !runUpdateProcess( true, true )){
     
      throw( new AzureusCoreException( "Failed to invoke restart" ));
    }
  }
 
  private boolean
  runUpdateProcess(
    boolean    update_only,
    boolean    no_wait )
 
    throws AzureusCoreException
  {
    PluginInterface pi = azureus_core.getPluginManager().getPluginInterfaceByID( "azupdater" );
   
    if ( pi == null ){
      Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR,
          "Can't update/restart, mandatory plugin 'azupdater' not found"));
     
      throw( new AzureusCoreException( "mandatory plugin 'azupdater' not found" ));
    }
   
    String  updater_dir = pi.getPluginDirectoryName();
   
    classpath_prefix = updater_dir + File.separator + UPDATER_JAR;
   
      String  app_path = SystemProperties.getApplicationPath();
     
      while( app_path.endsWith(File.separator)){
       
        app_path = app_path.substring(0,app_path.length()-1);
      }
     
     String  user_path = SystemProperties.getUserPath();
     
      while( user_path.endsWith(File.separator)){
       
        user_path = user_path.substring(0,user_path.length()-1);
      }
     
      String config_override = System.getProperty( SystemProperties.SYS_PROP_CONFIG_OVERRIDE );
     
      if ( config_override == null ){
       
        config_override = "";
      }
     
      String[]  parameters = {
          update_only?"updateonly":"restart",
          app_path,
          user_path,
        config_override,
      };
     
      FileOutputStream  fos  = null;
     
      try{
        Properties  update_properties = new Properties();
     
        long  max_mem = Runtime.getRuntime().maxMemory();
                         
        update_properties.put( "max_mem", ""+max_mem );
        update_properties.put( "app_name", SystemProperties.getApplicationName());
        update_properties.put( "app_entry", SystemProperties.getApplicationEntryPoint());
       
        if ( System.getProperty( "azureus.nativelauncher" ) != null || Constants.isOSX ){
          //NOTE: new 2306 osx bundle now sets azureus.nativelauncher=1, but older bundles dont
         
          try{
            String  cmd = PlatformManagerFactory.getPlatformManager().getApplicationCommandLine();
           
            if ( cmd != null ){
             
              update_properties.put( "app_cmd", cmd );
            }
          }catch( Throwable e ){
           
            Debug.printStackTrace(e);
          }
        }       
       
        if ( no_wait ){
         
          update_properties.put( "no_wait", "1" );
        }
       
        fos  = new FileOutputStream( new File( user_path, UPDATE_PROPERTIES ));
       
          // this handles unicode chars by writing \\u escapes
       
        update_properties.store(fos, "Azureus restart properties" );
       
      }catch( Throwable e ){
       
        Debug.printStackTrace( e );
       
      }finally{
       
        if ( fos != null ){
         
          try{
           
            fos.close();
           
          }catch( Throwable e ){
           
            Debug.printStackTrace(e);
          }
        }
      }
     
      String[]  properties = { "-Duser.dir=\"" + app_path + "\"" };
     
    ByteArrayOutputStream os = new ByteArrayOutputStream();
   
    boolean res = restartAzureus(new PrintWriter(os) {
      public void println(String str) {
        // we intercept these logs and log immediately
        Logger.log(new LogEvent(LOGID, str));
      }

    }, MAIN_CLASS, properties, parameters, update_only);
   
      // just check if any non-logged data exists
   
    byte[]  bytes = os.toByteArray();
   
    if ( bytes.length > 0 ){
     
      Logger.log(new LogEvent(LOGID, "AzureusUpdater: extra log - "
          + new String(bytes)));
    }
   
    return( res );
  }
 
 
  private String
  getClassPath()
  {
    String classPath = System.getProperty("java.class.path");
       
      classPath = classpath_prefix + System.getProperty("path.separator") + classPath;
     
      return( "-classpath \"" + classPath + "\" " );
  }
   
 
  private boolean
  win32NativeRestart(
    PrintWriter  log,
    String    exec )
  {
      try{
          // we need to spawn without inheriting handles
       
        PlatformManager pm = PlatformManagerFactory.getPlatformManager();
       
        pm.createProcess( exec, false );
     
        return( true );
       
      }catch(Throwable e) {
          e.printStackTrace(log);
         
          return( false );
      }
  }
 

  private String getExeUpdater(PrintWriter log) {
    try {

        // Vista test:   We will need to run an elevated EXE updater if we can't
        //              write to the program dir.
     
      if (Constants.isWindowsVistaOrHigher ){
       
        if (PluginInitializer.getDefaultInterface().getUpdateManager().getInstallers().length > 0) {
         
          log.println( "Vista restart w/Updates.. checking if EXE needed" );
         
          if ( !FileUtil.canReallyWriteToAppDirectory()){
           
            log.println( "It appears we can't write to the application dir, using the EXE updater" );
           
            return( EXE_UPDATER );
          }
        }
      }
    }catch ( Throwable t ){
      // ignore vista test
    }

    return null;
  }

  private boolean restartViaEXE(PrintWriter log,
      String exeUpdater,
      String[]  properties,
      String[]  parameters,
      String backupJavaRunString,
      boolean update_only)
  {
    String azRunner = null;
    File fileRestart = null;
    if (!update_only) {
      try {
        azRunner = PlatformManagerFactory.getPlatformManager().getApplicationCommandLine();
      } catch (PlatformManagerException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    try {
      int result;
      AEWin32Access accessor = AEWin32Manager.getAccessor(true);
      if (accessor == null) {
        result = -123;
      } else {
        if (azRunner != null) {
          // create a batch file to run the updater, then to restart azureus
          // bceause the updater would restart azureus as administrator user
          // and confuse the user
          fileRestart = FileUtil.getUserFile("restart.bat");
          String s = "title Azureus Updater Runner\r\n";
          s += exeUpdater + " \"updateonly\"";
          for (int i = 1; i < parameters.length; i++) {
            s += " \"" + parameters[i].replaceAll("\\\"", "") + "\"";
          }
          s += "\r\n";
          s += "start \"\" \"" + azRunner + "\"";
         
          byte[]  bytes;
         
          String  encoding = FileUtil.getScriptCharsetEncoding();
         
          if ( encoding == null ){
            bytes = s.getBytes();
          }else{
            try{
              bytes = s.getBytes( encoding );
            }catch( Throwable e){
              e.printStackTrace();
             
              bytes = s.getBytes();
            }
          }
          FileUtil.writeBytesAsFile(fileRestart.getAbsolutePath(),bytes);

          result = accessor.shellExecute(null, fileRestart.getAbsolutePath(),
              null, SystemProperties.getApplicationPath(),
              AEWin32Access.SW_SHOWMINIMIZED);
        } else {
          String execEXE = "\"-J" + getClassPath().replaceAll("\\\"", "")
              + "\" ";

          for (int i = 0; i < properties.length; i++) {
            execEXE += "\"-J" + properties[i].replaceAll("\\\"", "") + "\" ";
          }

          for (int i = 0; i < parameters.length; i++) {
            execEXE += " \"" + parameters[i].replaceAll("\\\"", "") + "\"";
          }

          log.println("Launch via " + exeUpdater + " params " + execEXE);
          result = accessor.shellExecute(null, exeUpdater, execEXE,
              SystemProperties.getApplicationPath(), AEWin32Access.SW_NORMAL);
        }
      }

      /*
       * Some results:
       * 0: OOM
       * 2: FNF
       * 3: Path Not Foud
       * 5: Access Denied (User clicked cancel on admin access dialog)
       * 8: OOM
       * 11: Bad Format
       * 26: Sharing Violation
       * 27: Association incomplete
       * 28: DDE Timeout
       * 29: DDE Fail
       * 30: DDE Busy
       * 31: No Association
       * 32: DLL Not found
       * >32: OK!
       */
      log.println("   -> " + result);

      if (result <= 32) {
        String sErrorReason = "";
        String key = null;

        switch (result) {
          case 0:
          case 8:
            key = "oom";
            break;

          case 2:
            key = "fnf";
            break;

          case 3:
            key = "pnf";
            break;

          case 5:
            key = "denied";
            break;

          case 11:
            key = "bad";
            break;

          case -123:
            key = "nowin32";
            break;

          default:
            sErrorReason = "" + result;
            break;
        }
        if (key != null) {
          sErrorReason = MessageText.getString("restart.error." + key,
              new String[] {
                exeUpdater,
                SystemProperties.getApplicationPath(),
              });
        }
        Logger.log(new LogAlert(false, LogAlert.AT_ERROR,
            MessageText.getString("restart.error", new String[] {
              sErrorReason
            })));
        return false;
      }
    } catch (Throwable f) {

      f.printStackTrace(log);

      return javaSpawn(log, backupJavaRunString);
    }

    return true;
  }
 

  // ****************** This code is copied into Restarter / Updater so make changes there too !!!
 
 


  public boolean
  restartAzureus(
      PrintWriter log,
    String    mainClass,
    String[]  properties,
    String[]  parameters,
    boolean update_only)
  {
    if(Constants.isOSX){
     
      return( restartAzureus_OSX(log,mainClass,properties,parameters));
     
    }else if( Constants.isUnix ){
     
      return( restartAzureus_Unix(log,mainClass,properties,parameters));
     
    }else{
     
      return( restartAzureus_win32(log,mainClass,properties,parameters,update_only));
    }
  }
 
  private boolean
  restartAzureus_win32(
      PrintWriter log,
    String    mainClass,
    String[]  properties,
    String[]  parameters,
    boolean  update_only)
  {
    String exeUpdater = getExeUpdater(log)// Not for Updater.java

    String exec;

    //Classic restart way using Runtime.exec directly on java(w)
    exec = "\"" + JAVA_EXEC_DIR + "javaw\" " + getClassPath() + getLibraryPath();

    for (int i = 0; i < properties.length; i++) {
      exec += properties[i] + " ";
    }

    exec += mainClass;

    for (int i = 0; i < parameters.length; i++) {
      exec += " \"" + parameters[i] + "\"";
    }

    if (exeUpdater != null) {
      return( restartViaEXE(log, exeUpdater, properties, parameters, exec, update_only));
    } else {
      if (log != null) {
        log.println("  " + exec);
      }

      if (!win32NativeRestart(log, exec)) {
        return( javaSpawn(log, exec));
      }else{
        return( true );
      }
    }
  }
 

  private boolean
  javaSpawn(
    PrintWriter log,
    String execString)
  {
    try {
      // hmm, try java method - this WILL inherit handles but might work :)

      log.println("Using java spawn");

      //NOTE: no logging done here, as we need the method to return right away, before the external process completes
      Process p = Runtime.getRuntime().exec(execString);

      log.println("    -> " + p);

      return true;
    } catch (Throwable g) {

      g.printStackTrace();
      return false;
    }
  }

  private boolean
  restartAzureus_OSX(
      PrintWriter log,
    String mainClass,
    String[]  properties,
    String[] parameters)
  {

     String exec = "\"" + JAVA_EXEC_DIR + "java\" " + getClassPath() + getLibraryPath();
    
     for (int i=0;i<properties.length;i++){
       exec += properties[i] + " ";
     }
   
     exec += mainClass ;
   
     for(int i = 0 ; i < parameters.length ; i++) {
       exec += " \"" + parameters[i] + "\"";
     }

     return( runExternalCommandViaUnixShell( log, exec ));
  }
 
 
 
  private int getUnixScriptVersion() {
    String sVersion = System.getProperty("azureus.script.version", "0");
    int version = 0;
    try {
      version = Integer.parseInt(sVersion);
    } catch (Throwable t) {
    }
    return version;
  }

  private boolean
  restartAzureus_Unix(
    PrintWriter log,
  String    mainClass,
  String[]  properties,
  String[]  parameters)
  {
   
    String exec = "\"" + JAVA_EXEC_DIR + "java\" " + getClassPath() +  getLibraryPath();
   
    for (int i=0;i<properties.length;i++){
      exec += properties[i] + " ";
    }
   
    int scriptVersion = getUnixScriptVersion();
    boolean restartByScript = Constants.compareVersions(
        UpdaterUtils.getUpdaterPluginVersion(), "1.8.5") >= 0
        && scriptVersion > 0;
    if (restartByScript) {
      exec += "-Dazureus.script.version=\"" + scriptVersion + "\" ";
    }
   
    exec += mainClass ;
   
    for(int i = 0 ; i < parameters.length ; i++) {
      exec += " \"" + parameters[i] + "\"";
    }
   
    if (restartByScript) {
      // run script after az shutdown to launch updater and then re-run az
      ScriptAfterShutdown.addExtraCommand("echo \"Applying (possible) patches before restarting..\"\n"
          + exec + "\n"
          + "echo \"Restarting Azureus..\"\n"
          + "$0\n");
      ScriptAfterShutdown.setRequiresExit(true);
     
      return( true );
    } else {
      return( runExternalCommandViaUnixShell( log, exec ));
    }
  }
 
 
 
  private String
  getLibraryPath()
  {
    String libraryPath = System.getProperty("java.library.path");
   
    if ( libraryPath == null ){
     
      libraryPath = "";
     
    }else{
     
        // remove any quotes from the damn thing
     
      String  temp = "";
     
      for (int i=0;i<libraryPath.length();i++){
       
        char  c = libraryPath.charAt(i);
       
        if ( c != '"' ){
         
          temp += c;
        }
      }
     
      libraryPath  = temp;
     
        // remove trailing separator chars if they exist as they stuff up
        // the following "
     
      while( libraryPath.endsWith(File.separator)){
     
        libraryPath = libraryPath.substring( 0, libraryPath.length()-1 );
      }
     
      if ( libraryPath.length() > 0 ){
 
        libraryPath = "-Djava.library.path=\"" + libraryPath + "\" ";
      }
    }
   
    return( libraryPath );
  }
 
  /*
  private void logStream(String message,InputStream stream,PrintWriter log) {
    BufferedReader br = new BufferedReader (new InputStreamReader(stream));
    String line = null;
    boolean first = true;
   
    try {
      while((line = br.readLine()) != null) {
        if( first ) {
          log.println(message);
          first = false;
        }
       
        log.println(line);
      }
    } catch(Exception e) {
       log.println(e);
       e.printStackTrace(log);
    }
  }
 
 
  private void chMod(String fileName,String rights,PrintWriter log) {
    String[] execStr = new String[3];
    execStr[0] = "chmod";
    execStr[1] = rights;
    execStr[2] = fileName;
   
    runExternalCommandsLogged( log, execStr );
  }
 
 
  private Process runExternalCommandLogged( PrintWriter log, String command ) {  //NOTE: will not return until external command process has completed
    log.println("About to execute: R:[" +command+ "]" );
   
    try {
      Process runner = Runtime.getRuntime().exec( command );
      runner.waitFor();   
      logStream( "runtime.exec() output:", runner.getInputStream(), log);
      logStream( "runtime.exec() error:", runner.getErrorStream(), log);
      return runner;
    }
    catch( Throwable t ) {
      log.println( t.getMessage() != null ? t.getMessage() : "<null>" );
      log.println( t );
      t.printStackTrace( log );
      return null;
    }
  }
 
  private Process runExternalCommandsLogged( PrintWriter log, String[] commands ) {  //NOTE: will not return until external command process has completed
    String cmd = "About to execute: R:[";
    for( int i=0; i < commands.length; i++ ) {
      cmd += commands[i];
      if( i < commands.length -1 )  cmd += " ";
    }
    cmd += "]";
   
    log.println( cmd );
   
    try {
      Process runner = Runtime.getRuntime().exec( commands );
      runner.waitFor();   
      logStream( "runtime.exec() output:", runner.getInputStream(), log);
      logStream( "runtime.exec() error:", runner.getErrorStream(), log);
      return runner;
    }
    catch( Throwable t ) {
      log.println( t.getMessage() != null ? t.getMessage() : "<null>" );
      log.println( t );
      t.printStackTrace( log );
      return null;
    }
  }
  */
 
 
  private boolean runExternalCommandViaUnixShell( PrintWriter log, String command ) {
    String[] to_run = new String[3];
    to_run[0] = "/bin/sh";
    to_run[1] = "-c";
    to_run[2] = command;
     
    if( log != null log.println("Executing: R:[" +to_run[0]+ " " +to_run[1]+ " " +to_run[2]+ "]" );

    try {
      //NOTE: no logging done here, as we need the method to return right away, before the external process completes
      Runtime.getRuntime().exec( to_run )
     
      return( true );
    }
    catch(Throwable t) {
      if( log != null )  {
        log.println( t.getMessage() != null ? t.getMessage() : "<null>" );
        log.println( t );
        t.printStackTrace( log );
      }
      else {
        t.printStackTrace();
      }
     
      return( false );
    }
  }
 
 
}
TOP

Related Classes of com.aelitis.azureus.core.update.impl.AzureusRestarterImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.