Changeset 5615 for trunk/src/core


Ignore:
Timestamp:
Apr 19, 2011, 3:42:31 PM (11 years ago)
Author:
Nicklas Nordborg
Message:

References #1592: Unified installation procedure for plug-ins, extensions and more...

Added file processor for installing plug-ins as part of a scan for extensions. Trying to link information about plug-in into the tree with extensions information.

Added "disabled" property to plug-ins to make them behave more similar to extensions. There may still be synchronization issues with the in-memory information and the database information.

Changed the installation procedure somewhat to allow re-using the same code for installing plug-ins (eg. from initdb/updatedb, and scanning extensions). There are some bumps to fix yet.

Location:
trunk/src/core
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/common-queries.xml

    r5566 r5615  
    19791979        (plg.requiresConfiguration = true AND NOT cfg.id IS NULL)
    19801980      )
     1981      AND plg.disabled = false
    19811982      GROUP BY plg.mainType
    19821983    </sql>
  • trunk/src/core/net/sf/basedb/core/Application.java

    r5608 r5615  
    555555        // TODO -- should this be moved to a utility class? Probably...
    556556        Registry xtRegistry = new Registry();
    557         java.io.File xtSettings = new java.io.File(pluginsDirectory, "settings.xml");
     557        java.io.File xtSettings = new java.io.File(userFilesDirectory, "extension-settings.xml");
    558558        xtManager = new ExtensionsManager(xtRegistry, xtSettings);
    559559       
    560560        // Add core extension points and extensions
    561561        xtManager.addURI(Application.class.getResource("/core-extensions.xml").toURI());
     562        // Add core plug-ins
     563        xtManager.addURI(Application.class.getResource("/core-plugins.xml").toURI());
    562564       
    563565        if (!Config.getBoolean("extensions.disabled"))
  • trunk/src/core/net/sf/basedb/core/Install.java

    r5613 r5615  
    691691          "net.sf.basedb.core.plugin.NonRestartable", null);
    692692     
    693       createPluginDefinitions("/core-plugins.xml", keyEveryoneUse, update);
     693      createPluginDefinitions("/core-plugins.xml", new ItemKey(keyEveryoneUse), update);
    694694     
    695695      // Plugin configurations
     
    24242424    Read plug-in definitions from the given file.
    24252425  */
    2426   private static void createPluginDefinitions(String filePath, ItemKeyData shareToEveryone, boolean update)
     2426  private static void createPluginDefinitions(String filePath, ItemKey shareToEveryone, boolean update)
    24272427  {
    24282428    DbControl dc = null;
     
    24582458    Create a {@link PluginDefinition}.
    24592459  */
    2460   private static PluginDefinition createPluginDefinition(PluginInfo info, ItemKeyData shareToEveryone)
    2461     throws BaseException
    2462   {
    2463     PluginDefinition pd = null;
     2460  private static PluginDefinition createPluginDefinition(PluginInfo info, ItemKey shareToEveryone)
     2461    throws BaseException
     2462  {
     2463    PluginDefinition plugin = null;
    24642464    DbControl dc = null;
    24652465    String className = info.getClassName();
     
    24682468     
    24692469      dc = sessionControl.newDbControl();
    2470      
    2471       try
    2472       {
    2473         pd = PluginDefinition.getByClassName(dc, className);
    2474       }
    2475       catch (ItemNotFoundException ex)
    2476       {}
    2477      
    2478       if (pd != null)
    2479       {
    2480         pd.loadPluginInformation(null, className, true);
    2481         pd.setAbout(info.getAbout(), false);
    2482         dc.commit();
     2470      plugin = PluginDefinition.installOrUpdate(dc, info, null, shareToEveryone);
     2471      boolean isNew = !plugin.isInDatabase();
     2472     
     2473      if (isNew)
     2474      {
     2475        plugin.setTrusted(true);
     2476      }
     2477      dc.commit();
     2478     
     2479      if (isNew)
     2480      {
     2481        log.info("createPluginDefinition: OK [class="+className+"]");
     2482      }
     2483      else
     2484      {
    24832485        log.info("createPluginDefinition: UPDATED [class="+className+"]");
    24842486      }
    2485       else
    2486       {
    2487         pd = PluginDefinition.getNew(dc, className, null, true);
    2488         pd.setAbout(info.getAbout(), false);
    2489         pd.setTrusted(true);
    2490         pd.setMaxMemory(Values.getLong(info.getProperty("max-memory"), null));
    2491         pd.setAllowImmediateExecution(Values.getBoolean(info.getProperty("immediate-execution")));
    2492         if (Values.getBoolean(info.getProperty("everyone-use")))
    2493         {
    2494           pd.getData().setItemKey(shareToEveryone);
    2495         }
    2496         dc.saveItem(pd);
    2497         dc.commit();
    2498         log.info("createPluginDefinition: OK [class="+className+"]");
    2499       }
    25002487    }
    25012488    catch (BaseException ex)
     
    25082495      if (dc != null) dc.close();
    25092496    }
    2510     return pd;
     2497    return plugin;
    25112498  }
    25122499
  • trunk/src/core/net/sf/basedb/core/ItemKey.java

    r5590 r5615  
    2929import net.sf.basedb.core.hibernate.TypeWrapper;
    3030
     31import java.util.EnumSet;
    3132import java.util.Map;
    3233import java.util.List;
     
    128129
    129130  /**
     131    Get a key that can be used to share items to the EVERYONE group with the
     132    given permissions.
     133    @param dc An open DbControl
     134    @param permission The permissions
     135    @return An ItemKey object
     136    @since 3.0
     137  */
     138  public static ItemKey getShareToEveryOneKey(DbControl dc, Permission permission)
     139  {
     140    Group everyone = Group.getById(dc, SystemItems.getId(Group.EVERYONE));
     141    GroupPermissions gp = new GroupPermissions();
     142    gp.setPermissions(everyone, EnumSet.of(permission));
     143    ItemKey everyoneKey = ItemKey.getNewOrExisting(dc, null, gp);
     144    return everyoneKey;
     145  }
     146 
     147  /**
    130148    Get an <code>ItemKey</code> item when you know the ID.
    131149
  • trunk/src/core/net/sf/basedb/core/PluginDefinition.java

    r5613 r5615  
    4141import net.sf.basedb.util.ClassUtil;
    4242import net.sf.basedb.util.JarClassLoader;
     43import net.sf.basedb.util.Values;
     44import net.sf.basedb.util.extensions.xml.PluginInfo;
    4345
    4446import java.util.Collection;
     
    297299        (plg.requiresConfiguration = true AND NOT cfg.id IS NULL)
    298300      )
     301      AND plg.disabled = false
    299302      GROUP BY plg.mainType
    300303    */
     
    332335   
    333336    return result;
     337  }
     338 
     339  /**
     340    Check the installation status of the given list of
     341    plug-ins.
     342    @param dc An optional DbControl (if null a new internal connection will be used)
     343    @param plugins An array with plug-in information objects
     344    @since 3.0
     345  */
     346  public static void checkInstallation(DbControl dc, Collection<PluginInfo> plugins)
     347  {
     348    if (plugins == null || plugins.size() == 0) return;
     349   
     350    org.hibernate.Session session = dc == null ? HibernateUtil.newSession() : dc.getHibernateSession();
     351    try
     352    {
     353      org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session,
     354        "GET_PLUGINDEFINITION_FOR_CLASSNAME");
     355     
     356      for (PluginInfo info : plugins)
     357      {
     358        query.setString("className", info.getClassName());
     359        PluginDefinitionData plugin = HibernateUtil.loadData(PluginDefinitionData.class, query);
     360        if (plugin != null)
     361        {
     362          info.setInternalId(plugin.getId());
     363          info.setDisabled(plugin.isDisabled());
     364        }
     365      }
     366    }
     367    finally
     368    {
     369      if (dc == null)
     370      {
     371        HibernateUtil.close(session);
     372      }
     373    }
     374  }
     375 
     376  public static PluginDefinition installOrUpdate(DbControl dc, PluginInfo info, String jarFile, ItemKey shareToEveryone)
     377  {
     378    PluginDefinition plugin = null;
     379    String className = info.getClassName();
     380    try
     381    {
     382      plugin = PluginDefinition.getByClassName(dc, className);
     383      plugin.loadPluginInformation(jarFile, className, true);
     384    }
     385    catch (ItemNotFoundException ex)
     386    {
     387      plugin = PluginDefinition.getNew(dc, className, jarFile, true);
     388      plugin.setMaxMemory(Values.getLong(info.getProperty("max-memory"), null));
     389      plugin.setAllowImmediateExecution(Values.getBoolean(info.getProperty("immediate-execution")));
     390      if (Values.getBoolean(info.getProperty("everyone-use")))
     391      {
     392        plugin.setItemKey(shareToEveryone);
     393      }
     394      dc.saveItem(plugin);
     395    }
     396    plugin.setAbout(info.getAbout(), true);
     397   
     398    return plugin;
     399   
     400    /*
     401    if (plugin != null)
     402    {
     403      pd.loadPluginInformation(null, className, true);
     404      pd.setAbout(info.getAbout(), false);
     405      dc.commit();
     406      log.info("createPluginDefinition: UPDATED [class="+className+"]");
     407    }
     408    else
     409    {
     410      pd = PluginDefinition.getNew(dc, className, null, true);
     411      pd.setAbout(info.getAbout(), false);
     412      pd.setTrusted(true);
     413      pd.setMaxMemory(Values.getLong(info.getProperty("max-memory"), null));
     414      pd.setAllowImmediateExecution(Values.getBoolean(info.getProperty("immediate-execution")));
     415      if (Values.getBoolean(info.getProperty("everyone-use")))
     416      {
     417        pd.getData().setItemKey(shareToEveryone);
     418      }
     419      dc.saveItem(pd);
     420      dc.commit();
     421        log.info("createPluginDefinition: OK [class="+className+"]");
     422      }
     423    }
     424    catch (BaseException ex)
     425    {
     426      log.error("createPluginDefinition: FAILED [class="+className+"]", ex);
     427      throw ex;
     428    }
     429    finally
     430    {
     431      if (dc != null) dc.close();
     432    }
     433    return pd;
     434    */
     435
    334436  }
    335437 
     
    709811 
    710812  /**
     813    Checks if this plugin is disabled or not. A disabled plugin
     814    can't be used.
     815    @return
     816  */
     817  public boolean isDisabled()
     818  {
     819    return getData().isDisabled();
     820  }
     821 
     822  /**
     823    Disabled or enabled this plugin.
     824  */
     825  public void setDisabled(boolean disabled)
     826  {
     827    checkPermission(Permission.WRITE);
     828    getData().setDisabled(disabled);
     829  }
     830 
     831  /**
    711832    If this plugin is trusted or not. A trusted plugin is executed without any
    712833    restrictions, an untrusted have restrictions similar to an applet in a
     
    10291150  {
    10301151    checkPermission(Permission.USE);
     1152    if (isDisabled())
     1153    {
     1154      throw new PermissionDeniedException("The plugin is disabled: " + getName());
     1155    }
    10311156    return newInstance(getJarPath(), getClassName(), null, false);
    10321157  }
    1033 
    1034   /*
    1035   Plugin newInstance(String jarPath)
    1036     throws PermissionDeniedException, BaseException
    1037   {
    1038     checkPermission(Permission.USE);
    1039     return newInstance(jarPath == null ? getJarPath() : jarPath, getClassName(), false);
    1040   }
    1041   */
    10421158 
    10431159  /**
     
    10531169  {
    10541170    checkPermission(Permission.USE);
     1171    if (isDisabled())
     1172    {
     1173      throw new PermissionDeniedException("The plugin is disabled: " + getName());
     1174    }
    10551175    ClassLoader alternateClassLoader = null;
    10561176    if (clazz.getClassLoader() != this.getClass().getClassLoader())
  • trunk/src/core/net/sf/basedb/core/data/PluginDefinitionData.java

    r5595 r5615  
    288288  }
    289289 
     290  private boolean disabled;
     291  /**
     292    If the plugin is enabled or disabled.
     293    // Mapped in hibernate-properties-PluginDefinitionData.xml since annotation doesn't support a default value
     294  */
     295  public boolean isDisabled()
     296  {
     297    return disabled;
     298  }
     299  public void setDisabled(boolean disabled)
     300  {
     301    this.disabled = disabled;
     302  }
     303 
    290304  private boolean interactive;
    291305  /**
  • trunk/src/core/net/sf/basedb/util/AutoDetectFileFormat.java

    r5595 r5615  
    3535import net.sf.basedb.core.PluginConfiguration;
    3636import net.sf.basedb.core.PluginDefinition;
     37import net.sf.basedb.core.query.Expressions;
    3738import net.sf.basedb.core.query.Orders;
    3839import net.sf.basedb.core.query.Hql;
     40import net.sf.basedb.core.query.Restrictions;
    3941import net.sf.basedb.core.plugin.AutoDetectingImporter;
    4042import net.sf.basedb.core.plugin.GuiContext;
     
    105107        PluginDefinition.getQuery(context, AutoDetectingImporter.class.getName());
    106108      pluginQuery.order(Orders.asc(Hql.property("name")));
     109      pluginQuery.restrict(Restrictions.eq(Hql.property("disabled"), Expressions.parameter("isDisabled", false)));
    107110      pluginQuery.include(Include.MINE, Include.SHARED, Include.IN_PROJECT, Include.OTHERS);
    108111      pluginDefs = pluginQuery.list(dc);
  • trunk/src/core/net/sf/basedb/util/extensions/manager/ExtensionsManager.java

    r5607 r5615  
    135135  /**
    136136    Add a directory to this manager. The directory is automatically
    137     scanned for files with .xml or .jar extensions which are
    138     added as extension files. This method call is ignored if the
     137    scanned for previously known files with .xml or .jar extensions
     138    which are added as extension files. To also scan for new files,
     139    call the {@link #scanForNewAndUpdated()} method.
     140    <p>
     141    This method call is ignored if the
    139142    path is not pointing to an existing directory.
    140143   
     
    147150    if (dir == null) throw new NullPointerException("dir");
    148151    directories.add(dir);
    149     int numNew = scanForNewFiles(dir);
     152    int numNew = scanForNewFiles(dir, false);
    150153    return numNew;
    151154  }
     
    193196    xtFile.validate();
    194197    xtFiles.put(xtFile.getURI(), xtFile);
     198    if (xtFile.getFile() != null)
     199    {
     200      settings.setKnownFile(xtFile.getFile());
     201    }
    195202    log.info("Added file: " + xtFile);
    196203  }
     
    204211    implementation that checks {@link ExtensionsFile#exists()}.
    205212
     213    @param installAllNew TRUE to install all new files, FALSE to only install
     214      new files that are previously known according to {@link Settings#isKnownFile(File)}
    206215    @return The number of new + modified files that was found
    207216  */
    208   public synchronized int scanForNewAndUpdated()
     217  public synchronized int scanForNewAndUpdated(boolean installAllNew)
    209218  {
    210219    numNew = 0;
     
    222231        log.debug("File '" + xtFile + "' has been deleted.");
    223232        unregisterAllObjects(xtFile);
     233        settings.removeKnownFile(xtFile.getFile());
    224234        it.remove();
    225235        numDeleted++;
     
    245255    for (File dir : directories)
    246256    {
    247       numNew += scanForNewFiles(dir);
    248     }
     257      numNew += scanForNewFiles(dir, installAllNew);
     258    }
     259   
     260    settings.save();
     261   
    249262    return numModified + numNew;
    250263  }
     
    288301  /**
    289302    Scan the given directory and add files that are new.
     303    @param dir The directory to scan
     304    @param installAllNew TRUE to install all new files, FALSE to only install
     305      new files that are previously known according to {@link Settings#isKnownFile(File)}
    290306    @return The number of new files in the given directory
    291307  */
    292   private int scanForNewFiles(File dir)
     308  private int scanForNewFiles(File dir, boolean installAllNew)
    293309  {
    294310    int numNew = 0;
     
    323339        else
    324340        {
    325           xtFile = new ExtensionsFile(this, file);
    326           addExtensionsFile(xtFile);
    327           numNew++;
     341          if (installAllNew || settings.isKnownFile(file))
     342          {
     343            log.debug("Installing file: " + file);
     344            xtFile = new ExtensionsFile(this, file);
     345            addExtensionsFile(xtFile);
     346            numNew++;
     347          }
     348          else
     349          {
     350            log.debug("File '" + file + "' is an unknown file.");
     351          }
    328352        }
    329353      }
  • trunk/src/core/net/sf/basedb/util/extensions/manager/Settings.java

    r5606 r5615  
    3232import net.sf.basedb.core.Presets;
    3333import net.sf.basedb.core.Presets.Preset;
     34import net.sf.basedb.util.Values;
    3435import net.sf.basedb.util.extensions.DefaultFilter;
    3536import net.sf.basedb.util.extensions.Extension;
     
    7071  private Presets presets;
    7172  private Preset settings;
     73  private Preset knownFiles;
    7274  private Preset disabledExtensions;
    7375  private Preset disabledExtensionPoints;
     
    99101    }
    100102    this.settings = presets.getDefault();
     103    this.knownFiles = presets.getPreset("known-files");
    101104    this.disabledExtensionPoints = presets.getPreset("disabled-extension-points");
    102105    this.disabledExtensions = presets.getPreset("disabled-extensions");
     
    149152  }
    150153 
     154  public boolean isKnownFile(File file)
     155  {
     156    return Values.getBoolean(knownFiles.getSetting(file.getAbsolutePath()));
     157  }
     158 
     159  public void setKnownFile(File file)
     160  {
     161    hasChanged = true;
     162    knownFiles.setSetting(file.getAbsolutePath(), "1");
     163  }
     164 
     165  public void removeKnownFile(File file)
     166  {
     167    hasChanged = true;
     168    knownFiles.setSetting(file.getAbsolutePath(), null);
     169  }
     170 
    151171  /**
    152172    Save the settings to disk. If the settings has not been
  • trunk/src/core/net/sf/basedb/util/extensions/xml/PluginInfo.java

    r5610 r5615  
    2525import java.util.Map;
    2626
     27import net.sf.basedb.core.DbControl;
     28import net.sf.basedb.core.PluginDefinition;
    2729import net.sf.basedb.core.plugin.About;
    2830
    2931/**
     32  Object for holding information about a plug-in definition as
     33  it is loaded from the extensions definition file. This class
     34  has no effect on the actual installed plug-ins. To get
     35  more information about what is installed and what is not,
     36  call {@link PluginDefinition#checkInstallation(DbControl, java.util.Collection)}.
    3037
    3138  @author Nicklas
     
    4148  private Map<String, String> properties;
    4249 
     50  private int internalId;
     51  private boolean disabled;
     52 
     53  /**
     54    Create a new information object.
     55  */
    4356  public PluginInfo(String id)
    4457  {
     
    4659  }
    4760 
     61  /**
     62    Get the class name of the plug-in.
     63  */
     64  public String getClassName()
     65  {
     66    return className;
     67  }
    4868  public void setClassName(String className)
    4969  {
     
    5171  }
    5272 
    53   public String getClassName()
     73  /**
     74    Get information about the authors of the plug-in.
     75  */
     76  public About getAbout()
    5477  {
    55     return className;
     78    return about;
    5679  }
    57  
    5880  public void setAbout(About about)
    5981  {
    6082    this.about = about;
    61   }
    62  
    63   public About getAbout()
    64   {
    65     return about;
    6683  }
    6784 
     
    7794  }
    7895 
     96  /**
     97    Get the internal if of this plug-in. This information is
     98    only available after {@link PluginDefinition#checkInstallation(DbControl, java.util.Collection)}
     99    has been called.
     100  */
     101  public int getInternalId()
     102  {
     103    return internalId;
     104  }
     105 
     106  public void setInternalId(int internalId)
     107  {
     108    this.internalId = internalId;
     109  }
     110 
     111  /**
     112    Is this plug-in installed or not?
     113  */
     114  public boolean isInstalled()
     115  {
     116    return internalId != 0;
     117  }
     118 
     119  /**
     120    Is this plug-in enabled or not?
     121  */
     122  public boolean isDisabled()
     123  {
     124    return disabled;
     125  }
     126 
     127  public void setDisabled(boolean disabled)
     128  {
     129    this.disabled = disabled;
     130  }
    79131 
    80132}
  • trunk/src/core/net/sf/basedb/util/extensions/xml/XmlLoader.java

    r5610 r5615  
    209209  private Filter<Element> filter;
    210210  /**
    211     Set a filter that all &lt;extension-point&gt;, &lt;extension&gt;
    212     and &lt;ref&gt; tags must pass to be loaded and registered.
     211    Set a filter that all &lt;extension-point&gt;, &lt;extension&gt;,
     212    &lt;ref&gt; and &lt;plugin-definition&gt; tags must pass to be loaded
     213    and registered.
    213214    @param filter A filter or null to remove an existing filter
    214215    @since 3.0
     
    824825      log.debug("Processing plug-in definition: " + id);
    825826     
    826       // <about>
    827       AboutBean about = loadAbout(pdTag.getChild("about", ns));
    828       if (globalAbout != null)
    829       {
    830         if (about == null) about = new AboutBean();
    831         about.copy(globalAbout, false);
    832       }
    833      
    834       // <plugin-class>
    835       String className = Values.getStringOrNull(pdTag.getChildText("plugin-class", ns));
    836      
    837       PluginInfo info = new PluginInfo(id);
    838       info.setAbout(about);
    839       info.setClassName(className);
    840      
    841       temp.add(info);
    842      
    843       // <settings>
    844       Element settingsTag = pdTag.getChild("settings", ns);
    845       if (settingsTag != null)
    846       {
    847         for (Element propertyTag : (List<Element>)settingsTag.getChildren("property", ns))
    848         {
    849           String name = propertyTag.getAttributeValue("name");
    850           String value = Values.getStringOrNull(propertyTag.getText());
    851           info.setProperty(name, value);
    852         }
    853       }
    854      
    855       if (!verifyBaseVersion(about, false))
    856       {
    857         String min = about.getMinBaseVersion();
    858         String max = about.getMaxBaseVersion();
    859         log.info("Plug-in definition '" + id + "' require BASE version between " +
    860           (min == null ? "*" : min) + " and " + (max == null ? "*" : max)
    861         );
    862       }
    863       else
    864       {
    865         // <action-factory>
    866         /*
    867         Element afTag = epTag.getChild("action-factory", ns);
    868         ActionFactory af = null;
    869         if (afTag != null)
    870         {
    871           af = createFactory(afTag, classLoader, ActionFactory.class);
    872         }
    873         */
     827      if (filter == null || filter.evaluate(pdTag))
     828      {
     829        // <about>
     830        AboutBean about = loadAbout(pdTag.getChild("about", ns));
     831        if (globalAbout != null)
     832        {
     833          if (about == null) about = new AboutBean();
     834          about.copy(globalAbout, false);
     835        }
     836       
     837        // <plugin-class>
     838        String className = Values.getStringOrNull(pdTag.getChildText("plugin-class", ns));
     839       
     840        PluginInfo info = new PluginInfo(id);
     841        info.setAbout(about);
     842        info.setClassName(className);
     843       
     844        temp.add(info);
     845       
     846        // <settings>
     847        Element settingsTag = pdTag.getChild("settings", ns);
     848        if (settingsTag != null)
     849        {
     850          for (Element propertyTag : (List<Element>)settingsTag.getChildren("property", ns))
     851          {
     852            String name = propertyTag.getAttributeValue("name");
     853            String value = Values.getStringOrNull(propertyTag.getText());
     854            info.setProperty(name, value);
     855          }
     856        }
     857       
     858        if (!verifyBaseVersion(about, false))
     859        {
     860          String min = about.getMinBaseVersion();
     861          String max = about.getMaxBaseVersion();
     862          log.info("Plug-in definition '" + id + "' require BASE version between " +
     863            (min == null ? "*" : min) + " and " + (max == null ? "*" : max)
     864          );
     865        }
     866        else
     867        {
     868          // <action-factory>
     869          /*
     870          Element afTag = epTag.getChild("action-factory", ns);
     871          ActionFactory af = null;
     872          if (afTag != null)
     873          {
     874            af = createFactory(afTag, classLoader, ActionFactory.class);
     875          }
     876          */
     877        }
    874878      }
    875879    }
Note: See TracChangeset for help on using the changeset viewer.