Package org.gudy.azureus2.pluginsimpl.local.installer

Source Code of org.gudy.azureus2.pluginsimpl.local.installer.PluginInstallerImpl

/*
* Created on 28-Nov-2004
* Created by Paul Gardner
* 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 org.gudy.azureus2.pluginsimpl.local.installer;

/**
* @author parg
*
*/

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.*;

import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
import org.gudy.azureus2.core3.util.AEThread2;
import org.gudy.azureus2.core3.util.AsyncDispatcher;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.FileUtil;
import org.gudy.azureus2.plugins.*;
import org.gudy.azureus2.plugins.installer.*;
import org.gudy.azureus2.plugins.ui.UIManager;
import org.gudy.azureus2.plugins.ui.UIManagerEvent;
import org.gudy.azureus2.plugins.update.*;
import org.gudy.azureus2.plugins.utils.StaticUtilities;
import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter;
import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException;
import org.gudy.azureus2.pluginsimpl.local.FailedPlugin;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.pluginsimpl.local.update.UpdateCheckInstanceImpl;
import org.gudy.azureus2.pluginsimpl.local.update.UpdateManagerImpl;
import org.gudy.azureus2.pluginsimpl.update.sf.*;

import org.gudy.azureus2.pluginsimpl.update.PluginUpdatePlugin;

import com.aelitis.azureus.core.vuzefile.VuzeFile;
import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
import com.aelitis.azureus.core.vuzefile.VuzeFileProcessor;

public class
PluginInstallerImpl
  implements PluginInstaller
{
  protected static PluginInstallerImpl  singleton;
 
  public static PluginInstallerImpl
  getSingleton(
    PluginManager  _manager )
  {
    if ( singleton == null ){
     
      singleton  = new PluginInstallerImpl( _manager );
    }
   
    return( singleton );
  }
 
  private PluginManager  manager;
  private List      listeners   = new ArrayList();
 
  private AsyncDispatcher    add_file_install_dispatcher;
 
  protected
  PluginInstallerImpl(
    PluginManager  _manager )
  {
    manager  = _manager;
   
    VuzeFileHandler.getSingleton().addProcessor(
        new VuzeFileProcessor()
        {
          public void
          process(
            VuzeFile[]    files,
            int        expected_types )
          {
            for (int i=0;i<files.length;i++){
             
              VuzeFile  vf = files[i];
             
              VuzeFileComponent[] comps = vf.getComponents();
             
              for (int j=0;j<comps.length;j++){
               
                VuzeFileComponent comp = comps[j];
               
                if ( comp.getType() == VuzeFileComponent.COMP_TYPE_PLUGIN ){
                 
                  try{
                    Map  content = comp.getContent();
                   
                    String  id     = new String((byte[])content.get( "id" ), "UTF-8" );
                    String  version = new String((byte[])content.get( "version" ), "UTF-8" );
                    String  suffix  = ((Long)content.get( "is_jar" )).longValue()==1?"jar":"zip";
                   
                    byte[]  plugin_file = (byte[])content.get( "file" );
                   
                    File temp_dir = AETemporaryFileHandler.createTempDir();
                   
                    File temp_file = new File( temp_dir, id + "_" + version + "." + suffix );
                   
                    FileUtil.copyFile( new ByteArrayInputStream( plugin_file ), temp_file );

                    FilePluginInstaller installer = installFromFile( temp_file );

                    addFileInstallOperation( installer );
                   
                    comp.setProcessed();
                   
                  }catch( Throwable e ){
                   
                    Debug.printStackTrace(e);
                  }
                }
              }
            }
          }
        });
  }
 
  protected void
  addFileInstallOperation(
    final FilePluginInstaller    installer )
  {
    synchronized( this ){
     
      if ( add_file_install_dispatcher == null ){
       
        add_file_install_dispatcher = new AsyncDispatcher();
      }
     
      add_file_install_dispatcher.dispatch(
        new AERunnable()
        {
          public void
          runSupport()
          {
            try{
              final AESemaphore done_sem = new AESemaphore( "PluginInstall:fio" );
                                 
              final UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
                 
              new AEThread2( "PluginInstall:fio", true )
                {
                  public void
                  run()
                  {
                    if ( installer.isAlreadyInstalled()){
                                           
                      String details = MessageText.getString(
                          "fileplugininstall.duplicate.desc",
                          new String[]{ installer.getName(), installer.getVersion()});
                     
                      ui_manager.showMessageBox(
                          "fileplugininstall.duplicate.title",
                          "!" + details + "!",
                          UIManagerEvent.MT_OK );
 
                      done_sem.release();
                     
                    }else{
 
                      String details = MessageText.getString(
                          "fileplugininstall.install.desc",
                          new String[]{ installer.getName(), installer.getVersion()});
                                                   
                      long res = ui_manager.showMessageBox(
                          "fileplugininstall.install.title",
                          "!" + details + "!",
                          UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
                     
                      if ( res == UIManagerEvent.MT_YES ){
                     
                        try{
                          install(
                            new InstallablePlugin[]{ installer },
                            false,
                            true,
                            null,
                            new PluginInstallationListener()
                            {                     
                              public void
                              completed()
                              {
                                done_sem.release();
                              }
                             
                              public void
                              cancelled()
                              {
                                done_sem.release();
                              }
                             
                              public void
                              failed(
                                PluginException e )
                              {
                                done_sem.release();
                               
                                Debug.out( "Installation failed", e );
                              }
                            });
                         
                        }catch( Throwable e ){
                         
                          Debug.printStackTrace(e);
                         
                          done_sem.release();
                        }
                      }else if ( res == UIManagerEvent.MT_NO ){
                       
                        done_sem.release();
                       
                      }else{
                       
                        Debug.out( "Message box not handled" );
                       
                        done_sem.release();
                      }
                    }
                  }
                }.start();
 
           
              while( !done_sem.reserve( 60*1000 )){
               
                if ( add_file_install_dispatcher.getQueueSize() > 0 ){
                 
                  Debug.out( "File plugin install operation queued pending completion of previous" );
                }
              }
             
            }catch( Throwable e ){
             
              Debug.printStackTrace(e);
            }
          }
        });
    }
  }
 
  protected PluginManager
  getPluginManager()
  {
    return( manager );
  }
 
  public StandardPlugin[]
  getStandardPlugins()
 
    throws PluginException
  {
    try{
      SFPluginDetailsLoader  loader = SFPluginDetailsLoaderFactory.getSingleton();
   
      SFPluginDetails[]  details = loader.getPluginDetails();

      List  res = new ArrayList();
       
      for (int i=0;i<details.length;i++){
       
        SFPluginDetails  detail = details[i];
       
        String  name   = detail.getId();
       
        String  version = "";
       
        if ( Constants.isCVSVersion()){
         
          version = detail.getCVSVersion();
        }
       
        if ( version == null || version.length() == 0 || !Character.isDigit(version.charAt(0))){
         
          version = detail.getVersion();
         
        }else{
         
            // if cvs version and non-cvs version are the same then show the
            // non-cvs version
         
          String  non_cvs_version = detail.getVersion();
         
          if ( version.equals( non_cvs_version + "_CVS" )){
           
            version = non_cvs_version;
          }
        }
       
        if ( name.startsWith( "azplatform" ) || name.equals( "azupdater" )){
         
            // skip built in ones we don't want to let user install directly
            // not the cleanest of fixes, but it'll do for the moment
         
        }else if ( version == null || version.length() == 0 || !Character.isDigit(version.charAt(0))){
         
            // dodgy version
         
        }else if ( detail.getCategory().equalsIgnoreCase("hidden")){
         
            // not public
         
        }else{
         
          res.add( new StandardPluginImpl( this, details[i], version ));
        }
      }
     
      StandardPlugin[]  res_a = new StandardPlugin[res.size()];

      res.toArray( res_a );
     
      return( res_a );
     
    }catch( SFPluginDetailsException e ){
     
      throw( new PluginException("Failed to load standard plugin details", e ));
    }
  }
 
  public StandardPlugin
    getStandardPlugin(
      String    id )
   
      throws PluginException
    {
      try{
        SFPluginDetailsLoader  loader = SFPluginDetailsLoaderFactory.getSingleton();
     
        SFPluginDetails[]  details = loader.getPluginDetails();

       
        for (int i=0;i<details.length;i++){
         
          SFPluginDetails  detail = details[i];
         
          String  name   = detail.getId();
                   
          if ( name.equals( id )){
           
            String  version = "";
           
            if ( Constants.isCVSVersion()){
             
              version = detail.getCVSVersion();
            }
           
            if ( version == null || version.length() == 0 || !Character.isDigit(version.charAt(0))){
             
              version = detail.getVersion();
             
            }else{
             
                // if cvs version and non-cvs version are the same then show the
                // non-cvs version
             
              String  non_cvs_version = detail.getVersion();
             
              if ( version.equals( non_cvs_version + "_CVS" )){
               
                version = non_cvs_version;
              }
            }
           
            if ( name.startsWith( "azplatform" ) || name.equals( "azupdater" )){
             
                // skip built in ones we don't want to let user install directly
                // not the cleanest of fixes, but it'll do for the moment
             
            }else if ( version == null || version.length() == 0 || !Character.isDigit(version.charAt(0))){
             
                // dodgy version
           
            }else{
           
              return( new StandardPluginImpl( this, details[i], version ));
            }
          }
        } 
       
        return( null );
       
      }catch( SFPluginDetailsException e ){
       
        throw( new PluginException("Failed to load standard plugin details", e ));
      }
    }
 
  public FilePluginInstaller
  installFromFile(
    File        file )
 
    throws PluginException
  {     
    return( new FilePluginInstallerImpl(this,file));
  }
 
  public void
  install(
    InstallablePlugin  installable_plugin,
    boolean        shared )
 
    throws PluginException
  {
    install( new InstallablePlugin[]{installable_plugin}, shared );
  }
 
  public void
  install(
    InstallablePlugin[]  plugins,
    boolean        shared )
 
    throws PluginException
  {
    install( plugins, shared, false, null, null );
  }
 
  public UpdateCheckInstance
  install(
    InstallablePlugin[]          plugins,
    boolean                shared,
    Map<Integer,Object>          properties,
    final PluginInstallationListener  listener )
 
    throws PluginException
  {
    return( install( plugins, shared, false, properties, listener ));
  }
 
  protected UpdateCheckInstance
  install(
    InstallablePlugin[]          plugins,
    boolean                shared,
    boolean                low_noise,
    Map<Integer,Object>          properties,
    final PluginInstallationListener  listener )
 
    throws PluginException
  {
    PluginInterface  pup_pi = manager.getPluginInterfaceByClass( PluginUpdatePlugin.class );
   
    if ( pup_pi == null ){
     
      throw( new PluginException( "Installation aborted, plugin-update plugin unavailable" ));
    }
   
    if ( !pup_pi.getPluginState().isOperational()){
     
      throw( new PluginException( "Installation aborted, plugin-update plugin not operational" ));
    }
   
    PluginUpdatePlugin  pup = (PluginUpdatePlugin)pup_pi.getPlugin();
   
    UpdateManagerImpl  uman = (UpdateManagerImpl)manager.getDefaultPluginInterface().getUpdateManager();
   
    UpdateCheckInstanceImpl  inst =
      uman.createEmptyUpdateCheckInstance(
          UpdateCheckInstance.UCI_INSTALL,
          "update.instance.install",
          low_noise );
   
    if ( properties != null ){
     
      for ( Map.Entry<Integer,Object> entry: properties.entrySet()){
       
        inst.setProperty( entry.getKey(), entry.getValue());
      }
    }
   
    if ( listener != null ){
     
      inst.addListener(
        new UpdateCheckInstanceListener()
        {
          public void
          cancelled(
            UpdateCheckInstance    instance )
          {
            listener.cancelled();
          }
         
          public void
          complete(
            UpdateCheckInstance    instance )
          {
            final Update[] updates = instance.getUpdates();
           
            if ( updates.length == 0 ){
                           
              listener.failed( new PluginException( "No updates were added during check process" ));
             
            }else{
             
              for (int i=0;i<updates.length;i++){
               
                updates[i].addListener(
                  new UpdateListener()
                  {
                    private boolean  cancelled;
                   
                    public void
                    cancelled(
                      Update update)
                    {
                      cancelled = true;
                     
                      check();
                    }
                   
                    public void
                    complete(
                      Update update )
                    {
                      check();
                    }
                   
                    protected void
                    check()
                    {
                      Update failed_update = null;
                     
                      for ( Update update: updates ){
                       
                        if ( !update.isCancelled() && !update.isComplete()){
                         
                          return;
                        }
                       
                        if ( !update.wasSuccessful()){
                         
                          failed_update = update;
                        }
                      }
                     
                      if ( cancelled ){
                       
                        listener.cancelled();
                       
                      }else{
                       
                        if ( failed_update == null ){
                         
                            // flush plugin events through before reporting complete
                         
                          PluginInitializer.waitForPluginEvents();
                         
                          listener.completed();
                         
                        }else{
                       
                          listener.failed(
                            new PluginException(
                              "Install of " + failed_update.getName() + " failed" ));
                        }
                      }
                    }
                  });
              }
            }
          }
        });
    }
   
    try{
     
      for (int i=0;i<plugins.length;i++){
       
        InstallablePlugin  plugin  = plugins[i];
       
        final String  plugin_id = plugin.getId();
       
        PluginInterface  existing_plugin_interface = manager.getPluginInterfaceByID( plugin_id, false );
       
        Plugin      existing_plugin  = null;
       
        if ( existing_plugin_interface != null ){
         
          existing_plugin  = existing_plugin_interface.getPlugin();
         
            // try to check that the new version is higher than the old one!
         
          String  old_version = existing_plugin_interface.getPluginVersion();
         
          if ( old_version != null ){
           
            int  res = Constants.compareVersions( plugin.getVersion(), old_version );
           
            if ( res < 0 ){
             
              throw( new PluginException( "A higher version (" + old_version + ") of Plugin '" + plugin_id + "' is already installed" ));
             
            }else if ( res == 0 ){
             
              throw( new PluginException( "Version (" + old_version + ") of Plugin '" + plugin_id + "' is already installed" ));
            }
          }
        }
       
        String  target_dir;
       
        if ( shared ){
                 
          target_dir   = FileUtil.getApplicationFile( "plugins" ).toString();
         
        }else{
         
          target_dir   = FileUtil.getUserFile( "plugins" ).toString();
        }
       
        target_dir += File.separator + plugin_id;
   
          // this may fail on Vista but it doesn't matter as we recover this later
          // on. So *don't* check for success here
       
        new File( target_dir ).mkdir();
       
        if ( existing_plugin == null ){
         
            // create a dummy plugin at version 0.0 to trigger the "upgrade" to the new
            // installed version
         
          FailedPlugin  dummy_plugin = new FailedPlugin( plugin_id, target_dir );
         
          PluginManager.registerPlugin( dummy_plugin, plugin_id );
       
          final PluginInterface dummy_plugin_interface = manager.getPluginInterfaceByID( plugin_id, false );
         
          ((InstallablePluginImpl)plugin).addUpdate( inst, pup, dummy_plugin, dummy_plugin_interface );
             
          inst.addListener(
            new UpdateCheckInstanceListener()
            {
              public void
              cancelled(
                UpdateCheckInstance    instance )
              {
                try{
               
                  dummy_plugin_interface.getPluginState().unload();
                 
                }catch( Throwable e ){
                 
                  Debug.out( "Failed to unload plugin", e );
                }
              }
             
              public void
              complete(
                UpdateCheckInstance    instance )
              {
                PluginInterface pi = manager.getPluginInterfaceByID( plugin_id, false );
               
                if ( pi != null && pi.getPlugin() instanceof FailedPlugin ){
                 
                  try{
                    pi.getPluginState().unload();
                   
                  }catch( Throwable e ){
                   
                    Debug.out( "Failed to unload plugin", e );
                  }
                }

              }
            });
        }else{
         
          ((InstallablePluginImpl)plugin).addUpdate( inst, pup, existing_plugin, existing_plugin_interface );
        }
      }
   
      inst.start();
     
      return( inst );
     
    }catch( Throwable e ){
     
      inst.cancel();
     
      if ( e instanceof PluginException ){
       
        throw((PluginException)e);
      }else{
       
        throw( new PluginException( "Failed to create installer", e ));
      }
    }
  }
 
  public void
  uninstall(
    InstallablePlugin    standard_plugin )
 
    throws PluginException
  {
    PluginInterface  pi = standard_plugin.getAlreadyInstalledPlugin();
   
    if ( pi == null ){
     
      throw( new PluginException(" Plugin '" + standard_plugin.getId() + "' is not installed"));
    }
   
    pi.getPluginState().uninstall();
  }
 
  public void
  uninstall(
    final PluginInterface    pi )
 
    throws PluginException
  {
    uninstall( new PluginInterface[]{ pi });
  }
 
  public void
  uninstall(
    final PluginInterface[]    pis )
 
    throws PluginException
  {
    for (int i=0;i<pis.length;i++){
     
      PluginInterface  pi = pis[i];
     
      if ( pi.getPluginState().isMandatory()){
       
        throw( new PluginException( "Plugin '" + pi.getPluginID() + "' is mandatory, can't uninstall" ));
      }
     
      if ( pi.getPluginState().isBuiltIn()){
       
        throw( new PluginException( "Plugin '" + pi.getPluginID() + "' is built-in, can't uninstall" ));
      }
     
      String  plugin_dir = pi.getPluginDirectoryName();
     
      if ( plugin_dir == null || !new File(plugin_dir).exists()){
 
        throw( new PluginException( "Plugin '" + pi.getPluginID() + "' is not loaded from the file system, can't uninstall" ));
      }
    }
   
    try{
      UpdateManager  uman = manager.getDefaultPluginInterface().getUpdateManager();
     
      UpdateCheckInstance  inst =
        uman.createEmptyUpdateCheckInstance(
            UpdateCheckInstance.UCI_UNINSTALL,
            "update.instance.uninstall");

      for (int i=0;i<pis.length;i++){
       
        final PluginInterface  pi = pis[i];
       
        final String  plugin_dir = pi.getPluginDirectoryName();

        inst.addUpdatableComponent(
          new UpdatableComponent()
          {
            public String
            getName()
            {
              return( pi.getPluginName());
            }
         
            public int
            getMaximumCheckTime()
            {
              return( 0 );
            }
           
            public void
            checkForUpdate(
              final UpdateChecker  checker )
            {
              try{
                ResourceDownloader rd =
                  manager.getDefaultPluginInterface().getUtilities().getResourceDownloaderFactory().create( new File( plugin_dir ));
 
                  // the plugin may have > 1 plugin interfaces, make the name up appropriately
               
                String  update_name = "";
                 
                PluginInterface[]  ifs = manager.getPluginInterfaces();
               
                  Arrays.sort(
                      ifs,
                      new Comparator()
                    {
                          public int
                      compare(
                        Object o1,
                        Object o2)
                          {
                            return(((PluginInterface)o1).getPluginName().compareTo(((PluginInterface)o2).getPluginName()));
                          }
                    });
                 
                for (int i=0;i<ifs.length;i++){
                 
                  if ( ifs[i].getPluginID().equals(pi.getPluginID())){
                 
                    update_name += (update_name.length()==0?"":",") + ifs[i].getPluginName();
                  }
                }
               
                final Update update = checker.addUpdate(
                  update_name,
                  new String[]{ "Uninstall: " + plugin_dir},
                  pi.getPluginVersion(),
                  rd,
                  pi.getPluginState().isUnloadable()?Update.RESTART_REQUIRED_NO:Update.RESTART_REQUIRED_YES );
                 
                rd.addListener(
                    new ResourceDownloaderAdapter()
                    {
                      public boolean
                      completed(
                        ResourceDownloader  downloader,
                        InputStream      data )
                      {
                        try{
                          if ( pi.getPluginState().isUnloadable()){
                       
                            pi.getPluginState().unload();
                           
                            FileUtil.recursiveDelete( new File( plugin_dir ));
                         
                          }
                                 
                          UpdateInstaller installer = checker.createInstaller();
                           
                          installer.addRemoveAction( new File( plugin_dir ).getCanonicalPath());
                       
                          update.complete( true );
                         
                          try{
                            PluginInitializer.fireEvent(
                              PluginEvent.PEV_PLUGIN_UNINSTALLED,
                              pi.getPluginID());
                           
                          }catch( Throwable e ){
                           
                            Debug.out( e );
                          }
                        }catch( Throwable e ){
                         
                          update.complete( false );
                         
                          Debug.printStackTrace(e);
                         
                          Logger.log(new LogAlert(LogAlert.REPEATABLE,
                              "Plugin uninstall failed", e));
                        }
                       
                          // don't close the stream as we process it later
                         
                        return( true );
                      }
                     
                      public void
                      failed(
                        ResourceDownloader      downloader,
                        ResourceDownloaderException e )
                      {
                        update.complete( false );
                       
                        if ( !downloader.isCancelled()){
                         
                          Logger.log(new LogAlert(LogAlert.REPEATABLE,
                              "Plugin uninstall failed", e));
                        }
                      }
                    });
              }finally{
               
                checker.completed();
              }
               
            }
          }, false );
      }

      inst.start();
     
    }catch( Throwable e ){
     
      Debug.printStackTrace(e);
    }
  }
 
  protected PluginInterface
  getAlreadyInstalledPlugin(
    String  id )
  {
    return( getPluginManager().getPluginInterfaceByID(id, false ));
  }
 
 
  public void
  requestInstall(
    String        reason,
    InstallablePlugin   plugin )
 
    throws PluginException
  {
    for (int i=0;i<listeners.size();i++){
     
      if (((PluginInstallerListener)listeners.get(i)).installRequest( reason, plugin )){
       
        return;
      }
    }
   
    throw( new PluginException( "No listeners registered to perform installation of '" + plugin.getName() +" (" + reason + ")" ));
  }
 
  public void
  addListener(
    PluginInstallerListener    l )
  {
    listeners.add( l );
  }
 
  public void
  removeListener(
    PluginInstallerListener    l )
  {
    listeners.remove( l );
  }
}
TOP

Related Classes of org.gudy.azureus2.pluginsimpl.local.installer.PluginInstallerImpl

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.