Package org.gudy.azureus2.pluginsimpl.local.launch

Source Code of org.gudy.azureus2.pluginsimpl.local.launch.PluginLauncherImpl

/*
* Created on 25-Jul-2005
* Created by Paul Gardner
* Copyright (C) 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.launch;

import java.io.*;
import java.net.*;
import java.util.*;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.SystemProperties;
import org.gudy.azureus2.plugins.LaunchablePlugin;
import org.gudy.azureus2.plugins.Plugin;
import org.gudy.azureus2.plugins.logging.LoggerChannel;
import org.gudy.azureus2.plugins.logging.LoggerChannelListener;
import org.gudy.azureus2.pluginsimpl.PluginUtils;


import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.launcher.Launcher;

public class
PluginLauncherImpl
{
  private static Map    preloaded_plugins  = new HashMap();
 
  // used as callback (via reflection) by Launcher
  private static void main(String[] args)
  {
    launch(args);
  }

  public static void
  launch(
    String[]    args )
  {
    if(Launcher.checkAndLaunch(PluginLauncherImpl.class, args))
      return;
      // This *has* to be done first as it sets system properties that are read and cached by Java
     
      COConfigurationManager.preInitialise();
        
    final LoggerChannelListener  listener =
      new LoggerChannelListener()
      {
        public void
        messageLogged(
          int    type,
          String  content )
        {
          logcontent, false );
        }
       
        public void
        messageLogged(
          String    str,
          Throwable  error )
        {
          logstr, true );
         
          StringWriter  sw = new StringWriter();
         
          PrintWriter    pw = new PrintWriter( sw );
         
          error.printStackTrace( pw );
         
          pw.flush();
         
          log( sw.toString(), true );
        }
       
        protected synchronized void
        log(
          String  str,
          boolean  stdout )
        {
            File  log_file   = getApplicationFile("launch.log");

            PrintWriter  pw = null;
           
            try{
            pw = new PrintWriter(new FileWriter( log_file, true ));

            if ( str.endsWith( "\n" )){
             
              if ( stdout ){
                System.err.print( "PluginLauncher: " + str );
              }
             
              pw.print( str );
             
            }else{
             
              if ( stdout ){
                System.err.println( "PluginLauncher: " + str );
              }
             
              pw.println( str );
            }
           
            }catch( Throwable e ){
             
            }finally{
             
              if ( pw != null ){
               
                pw.close();
              }
            }
        }
      };
     
    LaunchablePlugin[]  launchables = findLaunchablePlugins(listener);
   
    if ( launchables.length == 0 ){
     
      listener.messageLogged( LoggerChannel.LT_ERROR, "No launchable plugins found" );
     
      return;
     
    }else if ( launchables.length > 1 ){
     
      listener.messageLogged( LoggerChannel.LT_ERROR, "Multiple launchable plugins found, running first" );
    }
   
    try{
        // set default details for restarter
     
      SystemProperties.setApplicationEntryPoint( "org.gudy.azureus2.plugins.PluginLauncher" );

      launchables[0].setDefaults( args );     

        // see if we're a secondary instance
     
      if ( PluginSingleInstanceHandler.process( listener, args )){
       
        return;
      }
        // we have to run the core startup on a separate thread and then effectively pass "this thread"
        // through to the launchable "process" method
     
      Thread core_thread =
        new Thread( "PluginLauncher" )
        {
          public void
          run()
          {
            try{
                // give 'process' call below some time to start up
             
              Thread.sleep(500);
             
              AzureusCore azureus_core = AzureusCoreFactory.create();

              azureus_core.start();
             
            }catch( Throwable e ){
             
              listener.messageLogged( "PluginLauncher: launch fails", e );
            }         
          }
        };
     
      core_thread.setDaemon( true );
     
      core_thread.start();
     
      boolean  restart = false;
     
      boolean  process_succeeded  = false;
     
      try{
        restart = launchables[0].process();
       
        process_succeeded  = true;
       
      }finally{
       
        try{
          if ( restart ){
           
            AzureusCoreFactory.getSingleton().restart();
 
          }else{
           
            AzureusCoreFactory.getSingleton().stop();
          }
        }catch( Throwable e ){
         
            // only report this exception if we're not already failing
         
          if ( process_succeeded ){
           
            throw( e );
          }
        }
      }
     
    }catch( Throwable e ){
     
      listener.messageLogged( "PluginLauncher: launch fails", e );
    }
  }
 
   private static LaunchablePlugin[]
  findLaunchablePlugins(
    LoggerChannelListener  listener )
  {
        // CAREFUL - this is called BEFORE any AZ initialisation has been performed and must
        // therefore NOT use anything that relies on this (such as logging, debug....)
     
    List  res = new ArrayList();
   
      File  app_dir   = getApplicationFile("plugins");
     
      if ( !( app_dir.exists()) && app_dir.isDirectory()){
       
        listener.messageLogged( LoggerChannel.LT_ERROR, "Application dir '" + app_dir + "' not found" );
       
        return( new LaunchablePlugin[0] );
      }
     
      File[] plugins = app_dir.listFiles();
 
      if ( plugins == null || plugins.length == 0 ){
       
        listener.messageLogged( LoggerChannel.LT_ERROR, "Application dir '" + app_dir + "' empty" );
 
        return( new LaunchablePlugin[0] );
      }
     
      for ( int i=0;i<plugins.length;i++ ) {
         
        File  plugin_dir = plugins[i];
       
          if( !plugin_dir.isDirectory()){
           
            continue;
          }
         
        try{
                   
            ClassLoader classLoader = PluginLauncherImpl.class.getClassLoader();
               
            ClassLoader  root_cl = classLoader;
           
          File[] contents = plugin_dir.listFiles();
             
            if ( contents == null || contents.length == 0){
             
              continue;
            }
                                           
              // take only the highest version numbers of jars that look versioned
             
            String[]  plugin_version   = {null};
            String[]  plugin_id     = {null};
             
            contents  = getHighestJarVersions( contents, plugin_version, plugin_id, true );
             
            for( int j = 0 ; j < contents.length ; j++){
                               
              classLoader = addFileToClassPath( root_cl, classLoader, contents[j]);
            }
                               
            Properties props = new Properties();
           
            File  properties_file = new File( plugin_dir, "plugin.properties");
          
              // if properties file exists on its own then override any properties file
              // potentially held within a jar               
            
            if ( properties_file.exists()){
               
              FileInputStream  fis = null;
                 
              try{
                fis = new FileInputStream( properties_file );
                 
                props.load( fis );
                   
                }finally{
                   
                  if ( fis != null ){
                     
                    fis.close();
                  }
                }     
            }else{
                 
              if ( classLoader instanceof URLClassLoader ){
                   
                URLClassLoader  current = (URLClassLoader)classLoader;
                           
                  URL url = current.findResource("plugin.properties");
                 
                  if ( url != null ){
                     
                    props.load(url.openStream());
                  }
                }
            }
 
          String plugin_class = (String)props.get( "plugin.class");
                                             
            // don't support multiple launchable plugins
         
          if ( plugin_class == null || plugin_class.indexOf(';') != -1 ){
             
            continue;
          }
                             
          Class c = classLoader.loadClass(plugin_class);
                   
          Plugin      plugin  = (Plugin) c.newInstance();
      
          if ( plugin instanceof LaunchablePlugin ){
           
            preloaded_plugins.put( plugin_class, plugin );
           
            res.add( plugin );
          }
        }catch( Throwable e ){
         
          listener.messageLogged( "Load of plugin in '" + plugin_dir + "' fails", e );
        }
      }
     
      LaunchablePlugin[]  x = new LaunchablePlugin[res.size()];
     
      res.toArray( x );
     
      return( x );
  }
  
   public static Plugin
   getPreloadedPlugin(
     String  cla )
   {
     return((Plugin)preloaded_plugins.get( cla ));
   }
  
   private static File
   getApplicationFile(
     String filename)
   {     
       String path = SystemProperties.getApplicationPath();
        
       if (Constants.isOSX ){
        
           path = path + "/" + SystemProperties.getApplicationName() + ".app/Contents/";
       }
        
       return new File(path, filename);
   }
  
    public static File[]
  getHighestJarVersions(
    File[]    files,
    String[]  version_out ,
    String[]  id_out,  // currently the version of last versioned jar found...
    boolean    discard_non_versioned_when_versioned_found )
  {
        // WARNING!!!!
        // don't use Debug/lglogger here as we can be called before AZ has been initialised
     
      List  res     = new ArrayList();
      Map    version_map  = new HashMap();
     
      for (int i=0;i<files.length;i++){
       
        File  f = files[i];
       
        String  name = f.getName().toLowerCase();
       
        if ( name.endsWith(".jar")){
         
          int cvs_pos = name.lastIndexOf("_cvs");
         
          int sep_pos;
         
          if (cvs_pos <= 0)
            sep_pos = name.lastIndexOf("_");
          else
            sep_pos = name.lastIndexOf("_", cvs_pos - 1);
          
          if (   sep_pos == -1 ||
              sep_pos == name.length()-1 ||
            !Character.isDigit(name.charAt(sep_pos+1))){
           
              // not a versioned jar
           
            res.add( f );
           
          }else{
           
            String  prefix = name.substring(0,sep_pos);
         
          String  version = name.substring(sep_pos+1, (cvs_pos <= 0) ? name.length()-4 : cvs_pos);
         
          String  prev_version = (String)version_map.get(prefix);
         
          if ( prev_version == null ){
           
            version_map.put( prefix, version );
           
          }else{
         
            if ( PluginUtils.comparePluginVersions( prev_version, version ) < 0 ){
                           
              version_map.put( prefix, version );
            }             
          }
          }
         }
      }
     
        // If any of the jars are versioned then the assumption is that all of them are
        // For migration purposes (i.e. on the first real introduction of the update versioning
        // system) we drop all non-versioned jars from the set
     
      if ( version_map.size() > 0 && discard_non_versioned_when_versioned_found ){
       
        res.clear();
      }
     
      // fix a problem we had with the rating plugin. It went out as rating_x.jar when it should
      // have been azrating_x.jar. If there are any azrating entries then we remove any rating ones
      // to avoid load problems
   
      if ( version_map.containsKey( "azrating" )){
              
        version_map.remove( "rating" );
      }
     
      Iterator it = version_map.keySet().iterator();
     
      while(it.hasNext()){
       
        String  prefix   = (String)it.next();
        String  version  = (String)version_map.get(prefix);
       
        String  target = prefix + "_" + version;
       
        version_out[0]   = version;
        id_out[0]    = prefix;
       
        for (int i=0;i<files.length;i++){
         
          File  f = files[i];
         
          String  lc_name = f.getName().toLowerCase();
         
          if ( lc_name.equals( target + ".jar" ) ||
             lc_name.equals( target + "_cvs.jar" )){
                       
            res.add( f );
           
            break;
          }
        }
      }
     
     
     
      File[]  res_array = new File[res.size()];
     
      res.toArray( res_array );
     
      return( res_array );
    }
   
    public static ClassLoader
    addFileToClassPath(
        ClassLoader    root,
        ClassLoader    classLoader,
        File       f)
    {
      if (   f.exists() &&
          (!f.isDirectory())&&
          f.getName().endsWith(".jar")){

        try {

          classLoader = extendClassLoader( root, classLoader, f.toURL());

        }catch( Exception e){

          // don't use Debug/lglogger here as we can be called before AZ has been initialised

          e.printStackTrace();
        }
      }

      return( classLoader );
    }
   
    public static ClassLoader
    extendClassLoader(
      ClassLoader    root,
      ClassLoader    classLoader,
      URL        url )
    {
      // URL classloader doesn't seem to delegate to parent classloader properly
      // so if you get a chain of them then it fails to find things. Here we
      // make sure that all of our added URLs end up within a single URLClassloader
      // with its parent being the one that loaded this class itself
   
    if ( classLoader instanceof URLClassLoader ){
     
      URL[]  old = ((URLClassLoader)classLoader).getURLs();

      URL[]  new_urls = new URL[old.length+1];
     
      System.arraycopy( old, 0, new_urls, 1, old.length );
     
      new_urls[0]= url;
     
      classLoader = new URLClassLoader(
                new_urls,
                classLoader==root?
                    classLoader:
                    classLoader.getParent());
    }else{
           
      classLoader = new URLClassLoader(new URL[]{ url },classLoader);
    }
   
    return( classLoader );
    }
}
TOP

Related Classes of org.gudy.azureus2.pluginsimpl.local.launch.PluginLauncherImpl

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.