Changeset 4207


Ignore:
Timestamp:
Apr 4, 2008, 2:44:51 PM (15 years ago)
Author:
Nicklas Nordborg
Message:

References #436: Create extension system for the web application

Refactored factory interfaces to make it possible to create dynamic factories that works with different types of extension points and actions. Documentation will be updated next week.

Location:
trunk
Files:
6 added
22 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/AbstractJspActionFactory.java

    r4198 r4207  
    2626import net.sf.basedb.util.extensions.Action;
    2727import net.sf.basedb.util.extensions.ActionFactory;
    28 import net.sf.basedb.util.extensions.Context;
    29 import net.sf.basedb.util.extensions.Extension;
     28import net.sf.basedb.util.extensions.InvokationContext;
    3029
    3130/**
     
    3938  be propagated to the {@link JspContext#addScript(String)}
    4039  and {@link JspContext#addStylesheet(String)} methods in
    41   the {@link #prepareContext(Context, Extension)}.
     40  the {@link #prepareContext(InvokationContext)}.
    4241 
    4342  @author nicklas
     
    6867  */
    6968  @Override
    70   public boolean prepareContext(Context context, Extension<? super A> extension)
     69  public boolean prepareContext(InvokationContext<? super A> context)
    7170  {
    72     prepareContext((JspContext)context);
     71    prepareContext((JspContext)context.getClientContext());
    7372    return true;
    7473  }
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/AbstractJspRendererFactory.java

    r4198 r4207  
    2525
    2626import net.sf.basedb.util.extensions.Action;
    27 import net.sf.basedb.util.extensions.Context;
    28 import net.sf.basedb.util.extensions.Extension;
     27import net.sf.basedb.util.extensions.InvokationContext;
    2928import net.sf.basedb.util.extensions.RendererFactory;
    3029
     
    3938  be propagated to the {@link JspContext#addScript(String)}
    4039  and {@link JspContext#addStylesheet(String)} methods in
    41   the {@link #prepareContext(Context, Extension)}.
     40  the {@link #prepareContext(InvokationContext)}.
    4241 
    4342  @author nicklas
     
    6665  */
    6766  @Override
    68   public void prepareContext(Context context, Extension<? extends A> extension)
     67  public void prepareContext(InvokationContext<? extends A> context)
    6968  {
    70     prepareContext((JspContext)context);
     69    prepareContext((JspContext)context.getClientContext());
    7170  }
    7271  // ----------------------------------
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/ExtensionsControl.java

    r4202 r4207  
    182182      Extension points that are not found are ignored.
    183183    @return An invoker instance
    184     @see Registry#useExtensions(net.sf.basedb.util.extensions.Context, net.sf.basedb.util.extensions.ExtensionsFilter, String...)
     184    @see Registry#useExtensions(net.sf.basedb.util.extensions.ClientContext, net.sf.basedb.util.extensions.ExtensionsFilter, String...)
    185185  */
    186186  public static ExtensionsInvoker<?> useExtensions(JspContext context, String...extensionPoints)
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/ExtensionsDirectory.java

    r4202 r4207  
    333333          numDeleted++;
    334334        }
    335         catch (Exception ex)
     335        catch (Throwable ex)
    336336        {
    337337          extFile.setError(true);
     
    482482        }
    483483      }
    484       catch (Exception ex)
     484      catch (Throwable ex)
    485485      {
    486486        extFile.setError(true);
     
    528528        }
    529529      }
    530       catch (Exception ex)
     530      catch (Throwable ex)
    531531      {
    532532        extFile.setError(true);
     
    561561        }
    562562      }
    563       catch (Exception ex)
     563      catch (Throwable ex)
    564564      {
    565565        extFile.setError(true);
     
    580580        results.addMessage(extFile, num + " extensions registered.");
    581581      }
    582       catch (Exception ex)
     582      catch (Throwable ex)
    583583      {
    584584        extFile.setError(true);
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/JspContext.java

    r4202 r4207  
    3333import net.sf.basedb.core.SessionControl;
    3434import net.sf.basedb.util.extensions.ActionFactory;
    35 import net.sf.basedb.util.extensions.Context;
     35import net.sf.basedb.util.extensions.ClientContext;
    3636import net.sf.basedb.util.extensions.Extension;
     37import net.sf.basedb.util.extensions.InvokationContext;
    3738import net.sf.basedb.util.extensions.RendererFactory;
    3839
    3940/**
    4041  Context object for the web application. Instances of this class
    41   are always used for passing context information to web extensions.
    42   This means that it is always safe to cast the context to this
    43   class in the {@link ActionFactory#prepareContext(Context, Extension)}
    44   and {@link ActionFactory#getActions(Context, Extension)} methods
     42  are always used for passing client context information to web extensions.
     43  This means that it is always safe to cast the client context to this
     44  class in the {@link ActionFactory#prepareContext(InvokationContext)}
     45  and {@link ActionFactory#getActions(InvokationContext)} methods
    4546  and other methods that has a context parameter.
    4647 
    4748  <pre class="code">
    4849@Override
    49 public boolean prepareContext(Context context, Extension extension)
     50public boolean prepareContext(InvokationContext context)
    5051{
    51   JspContext jspContext = (JspContext)context;
     52  JspContext jspContext = (JspContext)context.getClientContext();
    5253  jspContext.addStylesheet("/base/include/styles/mystylesheet.css");
    5354  // Do other things
     
    6869*/
    6970public class JspContext
    70   extends Context
     71  extends ClientContext
    7172{
    7273 
     
    100101    Note! The writer is only intended to be used by render
    101102    objects when rendering the extensions. Using the writer
    102     from the ActionFactory#prepareContext(Context, Extension)} or
    103     {@link RendererFactory#prepareContext(Context, Extension)}
     103    from the {@link ActionFactory#prepareContext(InvokationContext)} or
     104    {@link RendererFactory#prepareContext(InvokationContext)}
    104105    method may produce unpredictable results.
    105106   
     
    138139    <p>
    139140    Note 1! This method must be called from the {@link
    140     ActionFactory#prepareContext(Context, Extension)} or
    141     {@link RendererFactory#prepareContext(Context, Extension)}
     141    ActionFactory#prepareContext(InvokationContext)} or
     142    {@link RendererFactory#prepareContext(InvokationContext)}
    142143    methods. Changes to the context after that will not be reflected
    143144    in the output.
     
    162163    <p>
    163164    Note 1! This method must be called from the {@link
    164     ActionFactory#prepareContext(Context, Extension)} or
    165     {@link RendererFactory#prepareContext(Context, Extension)}
     165    ActionFactory#prepareContext(InvokationContext)} or
     166    {@link RendererFactory#prepareContext(InvokationContext)}
    166167    methods. Changes to the context after that will not be reflected
    167168    in the output.
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/Settings.java

    r4202 r4207  
    5353  This class also implements the {@link ExtensionsFilter}
    5454  interface, and can be used on the
    55   {@link Registry#useExtensions(net.sf.basedb.util.extensions.Context, ExtensionsFilter, String...)}
     55  {@link Registry#useExtensions(net.sf.basedb.util.extensions.ClientContext, ExtensionsFilter, String...)}
    5656  method. This means that disabling/enabling extensions and extension points
    5757  will immediately be visible in the web interface. Sorting is delegated
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/menu/FixedMenuItemFactory.java

    r4198 r4207  
    2626import net.sf.basedb.clients.web.extensions.AbstractJspActionFactory;
    2727import net.sf.basedb.util.Values;
    28 import net.sf.basedb.util.extensions.Context;
    29 import net.sf.basedb.util.extensions.Extension;
     28import net.sf.basedb.util.extensions.InvokationContext;
    3029import net.sf.basedb.util.extensions.xml.PathSetter;
    3130import net.sf.basedb.util.extensions.xml.VariableSetter;
     
    4039  the properties. Changes to the properties are immediately
    4140  visible in the menu items returned from the
    42   {@link #getActions(Context, Extension)} method.
     41  {@link #getActions(InvokationContext)} method. 
    4342 
    4443  @author nicklas
     
    7877  */
    7978  @Override
    80   public MenuItemAction[] getActions(Context context,
    81     Extension<? super MenuItemAction> extension)
     79  public MenuItemAction[] getActions(InvokationContext<? super MenuItemAction> context)
    8280  {
    8381    return actions;
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/menu/PermissionMenuItemFactory.java

    r4198 r4207  
    2929import net.sf.basedb.core.Permission;
    3030import net.sf.basedb.core.SessionControl;
    31 import net.sf.basedb.util.extensions.Context;
    32 import net.sf.basedb.util.extensions.Extension;
     31import net.sf.basedb.util.extensions.InvokationContext;
    3332import net.sf.basedb.util.extensions.xml.PathSetter;
    3433import net.sf.basedb.util.extensions.xml.VariableSetter;
     
    5049 
    5150  If the menu item is hidden this is indicated by returning
    52   false from the {@link #prepareContext(Context, Extension)} method. Most
     51  false from the {@link #prepareContext(InvokationContext)} method. Most
    5352  properties can have different values for the enabled/disabled state.
    5453  For example:
     
    102101  */
    103102  @Override
    104   public MenuItemAction[] getActions(Context context, Extension<? super MenuItemAction> extension)
    105   {
    106     SessionControl sc = context.getSessionControl();
     103  public MenuItemAction[] getActions(InvokationContext<? super MenuItemAction> context)
     104  {
     105    SessionControl sc = context.getClientContext().getSessionControl();
    107106    MenuItemAction action = null;
    108107    if (!hasPermission(sc, visiblePermission))
     
    127126
    128127  @Override
    129   public boolean prepareContext(Context context, Extension<? super MenuItemAction> extension)
    130   {
    131     SessionControl sc = context.getSessionControl();
     128  public boolean prepareContext(InvokationContext<? super MenuItemAction> context)
     129  {
     130    SessionControl sc = context.getClientContext().getSessionControl();
    132131    boolean isEnabled = hasPermission(sc, visiblePermission);
    133     return isEnabled && super.prepareContext(context, extension);
     132    return isEnabled && super.prepareContext(context);
    134133  }
    135134  // ------------------------------------
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/toolbar/CompactButtonRendererFactory.java

    r4202 r4207  
    2626import net.sf.basedb.clients.web.extensions.AbstractJspRendererFactory;
    2727import net.sf.basedb.clients.web.extensions.JspContext;
    28 import net.sf.basedb.util.extensions.Context;
    29 import net.sf.basedb.util.extensions.Extension;
     28import net.sf.basedb.util.extensions.InvokationContext;
    3029
    3130/**
     
    4544 
    4645  @Override
    47   public CompactButtonRenderer getRenderer(Context context, Extension extension)
     46  public CompactButtonRenderer getRenderer(InvokationContext context)
    4847  {
    49     return new CompactButtonRenderer((JspContext)context);
     48    return new CompactButtonRenderer((JspContext)context.getClientContext());
    5049  }
    5150
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/toolbar/FixedButtonFactory.java

    r4202 r4207  
    2626import net.sf.basedb.clients.web.extensions.AbstractJspActionFactory;
    2727import net.sf.basedb.util.Values;
    28 import net.sf.basedb.util.extensions.Context;
    29 import net.sf.basedb.util.extensions.Extension;
     28import net.sf.basedb.util.extensions.InvokationContext;
    3029import net.sf.basedb.util.extensions.xml.PathSetter;
    3130import net.sf.basedb.util.extensions.xml.VariableSetter;
     
    3837  The button is by default both visible and enabled. Use the setter
    3938  method to change the properties. Changes to the properties are immediately
    40   visible in the menu items returned from the {@link #getActions(Context, Extension)}
     39  visible in the menu items returned from the {@link #getActions(InvokationContext)}
    4140  method.
    4241  <p>
     
    8483  */
    8584  @Override
    86   public ButtonAction[] getActions(Context context, Extension extension)
     85  public ButtonAction[] getActions(InvokationContext context)
    8786  {
    8887    return actions;
  • trunk/src/core/net/sf/basedb/util/extensions/ActionFactory.java

    r4198 r4207  
    6969    </ul>
    7070   
    71     @param context The current context to prepare
    72     @param extension The extension to use
     71    @param context The current invokation context
    7372    @return TRUE if the extension should be enabled,
    7473      FALSE if the extension should be disabled
    7574  */
    76   public boolean prepareContext(Context context, Extension<? super A> extension);
     75  public boolean prepareContext(InvokationContext<? super A> context);
    7776 
    7877  /**
     
    8584    the extension point, including the current item, if any.
    8685   
    87     @param context The current context
    88     @param extension The extension to create actions for
     86    @param context The current invokation context
    8987    @return An array of actions that should be added to the extension point.
    9088      Returns null or an empty array if there are no actions in the current context.
    9189  */
    92   public A[] getActions(Context context, Extension<? super A> extension);
     90  public A[] getActions(InvokationContext<? super A> context);
    9391 
    9492}
  • trunk/src/core/net/sf/basedb/util/extensions/ActionIterator.java

    r4198 r4207  
    2424package net.sf.basedb.util.extensions;
    2525
    26 import java.util.IdentityHashMap;
    2726import java.util.Iterator;
    28 import java.util.Map;
    2927import java.util.NoSuchElementException;
    3028
    31 import net.sf.basedb.util.extensions.Registry.RegisteredExtension;
    32 import net.sf.basedb.util.extensions.Registry.RegisteredExtensionPoint;
    3329
    3430/**
    3531  Iterator for iterating over all actions that <b>will be
    3632  created</b> by extensions after a call to {@link
    37   Registry#useExtensions(Context, ExtensionsFilter, String...)}.
     33  Registry#useExtensions(ClientContext, ExtensionsFilter, String...)}.
    3834  That method returns an {@link ExtensionsInvoker} object which
    3935  in it's turn uses this iterator.
     
    4440  next item. This happens in the {@link #hasNext()} method, which,
    4541  for each extension, calls {@link Extension#getActionFactory()}
    46   and then {@link ActionFactory#getActions(Context, Extension)}.
     42  and then {@link ActionFactory#getActions(InvokationContext)}.
    4743 
    4844  <p>
     
    6258
    6359  // The current context
    64   private final Context context;
     60  private InvokationContext<A> currentContext;
    6561 
    6662  // An iterator over all usable extensions
    67   private final Iterator<RegisteredExtension<A>> iterator;
     63  private final Iterator<InvokationContext<A>> iterator;
    6864 
    6965  // The actions created by the current extension
     
    7167  // The iterator's offset in the actions array
    7268  private int offset;
    73 
    74   // The currently active extension
    75   private RegisteredExtension<A> currentExtension;
    76  
    77   // The renderer for the current action
    78   private Renderer<? super A> currentRenderer;
    79  
    80   // Cache for created renderers
    81   private Map<Object, Renderer<? super A>> rendererCache;
    8269 
    8370  // Boolean flags to indicate if we have a next element and if
     
    8774 
    8875 
    89   ActionIterator(Context context, Iterator<RegisteredExtension<A>> iterator)
     76  ActionIterator(Iterator<InvokationContext<A>> iterator)
    9077  {
    91     this.context = context;
    9278    this.iterator = iterator;
    9379    this.checkNext = true;
    94     this.rendererCache = new IdentityHashMap<Object, Renderer<? super A>>();
     80//    this.rendererCache = new IdentityHashMap<Object, Renderer<? super A>>();
    9581  }
    9682  /*
     
    11298      {
    11399        // No more actions in the array, move on to the next extension
    114         currentExtension = null;
    115         currentRenderer = null;
     100        currentContext = null;
    116101        actions = null;
    117102        offset = 0;
     
    122107        while (iterator.hasNext())
    123108        {
    124           currentExtension = iterator.next();
     109          currentContext = iterator.next();
     110         
    125111          // Get the actions for the extension
    126           actions = currentExtension.getActionFactory().getActions(context, currentExtension);
     112          actions = currentContext.getActions();
    127113          if (actions != null && actions.length > 0)
    128114          {
     
    158144  public Extension<? extends A> getExtension()
    159145  {
    160     return currentExtension;
     146    return currentContext.getExtension();
    161147  }
    162148 
     
    166152  Renderer<? super A> getRenderer()
    167153  {
    168     if (currentRenderer == null)
    169     {
    170       RegisteredExtensionPoint<? super A> ep = currentExtension.getExtensionPoint();
    171       RendererFactory<? super A> rf = currentExtension.getRendererFactory();
    172       if (ep.allowRendererOverride() && rf != null)
    173       {
    174         // Use the extension's renderer factory if it is
    175         // allowed and if one is provided
    176         currentRenderer = rf.getRenderer(context, currentExtension);
    177       }
    178       else
    179       {
    180         // We must use the extensions points renderer factory
    181         // First, check the cache if we already have a renderer
    182         currentRenderer = rendererCache.get(ep);
    183         if (currentRenderer == null)
    184         {
    185           currentRenderer = ep.getRendererFactory().getRenderer(context, currentExtension);
    186           rendererCache.put(ep, currentRenderer);
    187         }
    188       }
    189     }
    190     return currentRenderer;
     154    return currentContext.getRenderer();
    191155  }
    192156}
  • trunk/src/core/net/sf/basedb/util/extensions/ClientContext.java

    r4205 r4207  
    3030
    3131/**
    32   Keeps information about the current context that
    33   extensions can use to decide what actions to generate.
    34   It is, for example, possible to check the permissions
     32  Keeps information about the current context in the client
     33  application that extensions can use to decide what actions to
     34  generate. It is, for example, possible to check the permissions
    3535  of logged in user and enable/disable certain actions
    3636  if a condition is not met. Or, the extension may inspect
     
    4141  The current context is passed to an {@link ActionFactory} twice, first
    4242  to check if an extension should be enabled or not
    43   with the {@link ActionFactory#prepareContext(Context, Extension)}
     43  with the {@link ActionFactory#prepareContext(InvokationContext)}
    4444  method. This method also allows an extension to write
    4545  back information to the context. This may, for example,
     
    5050  <p>
    5151  The second time is when calling the {@link
    52   ActionFactory#getActions(Context, Extension)} method. This method can
     52  ActionFactory#getActions(InvokationContext)} method. This method can
    5353  be called multiple times. For example, if an extension point
    5454  is in a list context, the <code>getActions</code> method may
     
    6565  @base.modified $Date:2008-03-20 12:15:25 +0100 (Thu, 20 Mar 2008) $
    6666*/
    67 public class Context
     67public class ClientContext
    6868{
    6969
     
    7777    @param sc The current session
    7878  */
    79   public Context(SessionControl sc)
     79  public ClientContext(SessionControl sc)
    8080  {
    8181    this.sc = sc;
     
    8989    @param item The current item
    9090  */
    91   public Context(SessionControl sc, Object item)
     91  public ClientContext(SessionControl sc, Object item)
    9292  {
    9393    this.sc = sc;
  • trunk/src/core/net/sf/basedb/util/extensions/DefaultFilter.java

    r4198 r4207  
    4343
    4444  /**
    45     Comparator used to order extensions by their index value.
     45    Comparator used to order a list of invokation contexts by
     46    the index value of the extension.
    4647    @see Extension#getIndex()
    4748  */
    48   public static final Comparator<Extension<?>> INDEX_COMPARATOR =
     49  public static final Comparator<InvokationContext<?>> INDEX_COMPARATOR_CTX =
     50    new Comparator<InvokationContext<?>>()
     51    {
     52      @Override
     53      public int compare(InvokationContext<?> o1, InvokationContext<?> o2)
     54      {
     55        return Float.compare(o1.getExtension().getIndex(), o2.getExtension().getIndex());
     56      }
     57    };
     58
     59  /**
     60    Comparator used to order a list of extensions by
     61    the index value of the extension.
     62    @see Extension#getIndex()
     63  */
     64  public static final Comparator<Extension<?>> INDEX_COMPARATOR_EXT =
    4965    new Comparator<Extension<?>>()
    5066    {
     
    5571      }
    5672    };
    57  
     73   
    5874  /**
    5975    Create a new default filter.
     
    7995
    8096  @Override
    81   public void sort(List<? extends Extension<?>> extensions)
     97  public void sort(List<? extends InvokationContext<?>> extensions)
    8298  {
    83     Collections.sort(extensions, INDEX_COMPARATOR);
     99    Collections.sort(extensions, INDEX_COMPARATOR_CTX);
    84100  }
    85101  // --------------------------------------------------
  • trunk/src/core/net/sf/basedb/util/extensions/ExtensionPoint.java

    r4187 r4207  
    11/**
    2   $Id$
     2  $Id:ExtensionPoint.java 4187 2008-03-20 11:15:25Z nicklas $
    33
    44  Copyright (C) Authors contributing to this file.
     
    5151  {@link Registry#registerExtension(Extension)}. To load and use all
    5252  registered extensions use
    53   {@link Registry#useExtensions(Context, ExtensionsFilter, String...)}.
     53  {@link Registry#useExtensions(ClientContext, ExtensionsFilter, String...)}.
    5454
    5555  @author nicklas
    5656  @version 2.7
    57   @base.modified $Date$
     57  @base.modified $Date:2008-03-20 12:15:25 +0100 (Thu, 20 Mar 2008) $
    5858  @see ExtensionPointBean
    5959  @see XmlLoader
  • trunk/src/core/net/sf/basedb/util/extensions/ExtensionsFilter.java

    r4187 r4207  
    2929  Allows extensions and extension points to be enabled/disabled
    3030  and sorted externally. An object of this class is used by the
    31   {@link Registry#useExtensions(Context, ExtensionsFilter, String...)}
     31  {@link Registry#useExtensions(ClientContext, ExtensionsFilter, String...)}
    3232  method.
    3333
    3434  @author nicklas
    3535  @version 2.7
    36   @base.modified $Date$
     36  @base.modified $Date:2008-03-20 12:15:25 +0100 (Thu, 20 Mar 2008) $
    3737*/
    3838public interface ExtensionsFilter
     
    5656 
    5757  /**
    58     Sort a list of extensions according to some property.
     58    Sort a list of invoked extensions according to some property.
    5959    @param extensions The list of extensions to sort
    6060  */
    61   public void sort(List<? extends Extension<?>> extensions);
     61  public void sort(List<? extends InvokationContext<?>> extensions);
    6262 
    6363}
  • trunk/src/core/net/sf/basedb/util/extensions/ExtensionsInvoker.java

    r4187 r4207  
    11/**
    2   $Id$
     2  $Id:ExtensionsInvoker.java 4187 2008-03-20 11:15:25Z nicklas $
    33
    44  Copyright (C) Authors contributing to this file.
     
    2727import java.util.Iterator;
    2828
    29 import net.sf.basedb.util.extensions.Registry.RegisteredExtension;
    30 
    31 
    3229/**
    3330  Object of this class handles a single invokation of the extensions
    3431  for one or several extension points. Call
    35   {@link Registry#useExtensions(Context, ExtensionsFilter, String...)}
     32  {@link Registry#useExtensions(ClientContext, ExtensionsFilter, String...)}
    3633  to create an invoker object. With this object you can
    3734  {@link #iterate()} over all actions created by the extensions, or
     
    5552  @author nicklas
    5653  @version 2.7
    57   @base.modified $Date$
     54  @base.modified $Date:2008-03-20 12:15:25 +0100 (Thu, 20 Mar 2008) $
    5855*/
    5956public class ExtensionsInvoker<A extends Action>
    6057{
    6158
    62   final Collection<RegisteredExtension<A>> extensions;
    63   final Context context;
    64   private RendererFactory<A> currentRenderFactory;
     59  final Collection<InvokationContext<A>> contexts;
    6560 
    6661  /**
    6762    Creates a new invoker object.
    6863  */
    69   ExtensionsInvoker(Collection<RegisteredExtension<A>> extensions, Context context)
     64  ExtensionsInvoker(Collection<InvokationContext<A>> contexts)
    7065  {
    71     this.extensions = extensions;
    72     this.context = context;
     66    this.contexts = contexts;
    7367  }
    7468 
     
    8175  public ActionIterator<A> iterate()
    8276  {
    83     return new ActionIterator<A>(context, extensions.iterator());
     77    return new ActionIterator<A>(contexts.iterator());
    8478  }
    8579 
  • trunk/src/core/net/sf/basedb/util/extensions/Registry.java

    r4202 r4207  
    319319  /**
    320320    Get an iterator returning all registered extensions
    321     for a given extension point.  If the extension point is not found
     321    for a given extension point. If the extension point is not found
    322322    an empty iterator is returned. The returned iterator doesn't
    323323    support removal and will not reflect changes made to the registry
     
    341341      List<Extension<?>> copy =
    342342        new ArrayList<Extension<?>>(rep.getExtensions());
    343       Collections.sort(copy, DefaultFilter.INDEX_COMPARATOR);
     343      Collections.sort(copy, DefaultFilter.INDEX_COMPARATOR_EXT);
    344344      return Collections.unmodifiableList(copy).iterator();
    345345    }
     
    358358    get a chance to check the context object and to further initialise it
    359359    with extension-dependent information. This is a task for the
    360     {@link ActionFactory#prepareContext(Context, Extension)} method. If this method
     360    {@link ActionFactory#prepareContext(InvokationContext)} method. If this method
    361361    returns false the extension will not be included in the invoker. Extensions
    362362    may for example use this to check if the logged in user has enough permissions
     
    365365    <p>
    366366    If the extension points and/or extensions also provide renderer factories,
    367     the {@link RendererFactory#prepareContext(Context, Extension)} is called.
     367    the {@link RendererFactory#prepareContext(InvokationContext)} is called.
    368368    For renderer factories that are attached to extension points the method
    369369    is only called if at least one enabled extension exists. If the method is
     
    378378    an extension point should call this method to get a new invoker object.
    379379   
    380     @param context Information about the current context
     380    @param clientContext Information about the current context
    381381    @param filter A filter object that can be used to filter out
    382382      disabled extensions and sort the extensions in a particular order.
     
    390390  */
    391391  @SuppressWarnings("unchecked")
    392   public ExtensionsInvoker<?> useExtensions(Context context, ExtensionsFilter filter,
     392  public ExtensionsInvoker<?> useExtensions(ClientContext clientContext, ExtensionsFilter filter,
    393393    String... extensionPointIds)
    394394  {
    395395    if (filter == null) filter = DEFAULT_FILTER;
    396     List<RegisteredExtension<Action>> use = new LinkedList<RegisteredExtension<Action>>();
     396
     397    List<InvokationContext<Action>> contexts = new LinkedList<InvokationContext<Action>>();
    397398    for (String id : extensionPointIds)
    398399    {
     
    400401      RegisteredExtensionPoint<Action> rep =
    401402        (RegisteredExtensionPoint<Action>)extensionPoints.get(id);
    402       if (rep != null && filter.isEnabled(rep))
     403     
     404      // Is there an enabled extension point?
     405      if (rep == null || !filter.isEnabled(rep)) continue;
     406
     407      // YES! ...
     408      ExtensionPointContext<Action> mainContext =
     409        new ExtensionPointContext<Action>(this, clientContext, rep);
     410      boolean allowRenderOverride = rep.allowRendererOverride();
     411      int enabledExtensions = 0;
     412     
     413      // ... find the extensions for it
     414      for (RegisteredExtension<Action> ext : rep.getExtensions())
    403415      {
    404         // The extension point is enabled...
    405         boolean allowRenderOverride = rep.allowRendererOverride();
    406         int enabledExtensions = 0;
    407         // ... find the extensions for it
    408         for (RegisteredExtension<Action> ext : rep.getExtensions())
    409         {
    410           // Check with the filter if the extension is enabled...
    411           // ... and check with the action factory as well
    412           if (filter.isEnabled(ext) && ext.getActionFactory().prepareContext(context, ext))
    413           {
    414             use.add(ext);
    415             enabledExtensions++;
    416             // Prepare the renderer factory if it is allowed and there is one
    417             if (allowRenderOverride)
    418             {
    419               RendererFactory<? super Action> factory = ext.getRendererFactory();
    420               if (factory != null) factory.prepareContext(context, ext);
    421             }
    422           }
    423         }
    424         // Prepare the renderer factory if there is at least one extension
    425         RendererFactory<? super Action> factory = rep.getRendererFactory();
    426         if (enabledExtensions > 0 && factory != null)
    427         {
    428           factory.prepareContext(context, null);
    429         }
     416        // Check with the filter if the extension is enabled
     417        if (!filter.isEnabled(ext)) continue;
     418
     419        // Create invokation context for the extension
     420        ExtensionContext<Action> context =
     421          new ExtensionContext<Action>(mainContext, ext);
     422       
     423        // Check with the action factory as well
     424        if (!context.prepareActionFactory()) continue;
     425
     426        // Yippi, this extension is enabled!!!
     427        if (allowRenderOverride) context.prepareRendererFactory();
     428        contexts.add(context);
     429        enabledExtensions++;
    430430      }
    431     }
     431     
     432      // Prepare the renderer factory for the extension point
     433      // if there is at least one enabled extension
     434      if (enabledExtensions > 0) mainContext.prepareRendererFactory();
     435    }
     436   
    432437    // Sort the extensions
    433     filter.sort(use);
    434     return new ExtensionsInvoker<Action>(use, context);
     438    filter.sort(contexts);
     439    return new ExtensionsInvoker<Action>(contexts);
    435440  }
    436441 
    437442  /**
    438443    Default filter implementation for
    439     {@link #useExtensions(Context, ExtensionsFilter, String...)}
     444    {@link #useExtensions(ClientContext, ExtensionsFilter, String...)}
    440445  */
    441446  private static final ExtensionsFilter DEFAULT_FILTER = new DefaultFilter();
  • trunk/src/core/net/sf/basedb/util/extensions/RendererFactory.java

    r4198 r4207  
    6666    <p>
    6767    Note! This method has no return value as opposed to
    68     {@link ActionFactory#prepareContext(Context, Extension)}. The
     68    {@link ActionFactory#prepareContext(InvokationContext)}. The
    6969    simple reason is that once we get to the point of rendering it
    7070    is already known that the extension is enabled.
    7171   
    72     @param context The current context to prepare
    73     @param extension The extension to use, or null if this
    74       factory is used from an extension point
     72    @param context The current invokation context
    7573  */
    76   public void prepareContext(Context context, Extension<? extends A> extension);
     74  public void prepareContext(InvokationContext<? extends A> context);
    7775 
    7876  /**
     
    8280    multiple threads may use the same renderer.
    8381   
    84     @param context The current context
    85     @param extension The extension to create a renderer for
     82    @param context The current invokation context
    8683    @return A renderer instance
    8784  */
    88   public Renderer<? super A> getRenderer(Context context, Extension<? extends A> extension);
     85  public Renderer<? super A> getRenderer(InvokationContext<? extends A> context);
    8986 
    9087}
  • trunk/src/core/net/sf/basedb/util/extensions/xml/XmlLoader.java

    r4202 r4207  
    9191</pre>
    9292
    93   The setter methods must be public and accept a single <code>String</code> parameter.
     93  The setter methods must be public and accept a single <code>String</code>
     94  parameter.
     95  <p>
     96 
     97  The loader also looks for the <code>setParameter(String, String)</code>
     98  method signature. If the method exists it will be called for each
     99  parameter found with the tagname as the first parameter and the
     100  value as the second parameter. Ccontinuing the above example:
     101 
     102  <pre class="code">
     103factory.setParameter("image", "button.png");
     104factory.setParameter("title", "Click button");
     105</pre>
     106 
     107  <p>
    94108  Tags that doesn't have a corresponding setter method are simply ignored.
    95109  The XML file format allows any tags as parameters, but only the first level
     
    651665    factoryParameters.put(bean, xmlOut.outputString(root));
    652666   
     667    // Check for generic setParameter(String, String) method
     668    Method setParameter = getSetParameterMethod(beanClass);
     669   
    653670    // List all child tags
    654671    for (Element child : parameters)
     
    661678      if (value == null) continue;
    662679
     680      // Call generic setParmeter(String, String) method
     681      if (setParameter != null)
     682      {
     683        try
     684        {
     685          setParameter.invoke(bean, childName, value);
     686        }
     687        catch (IllegalAccessException ex)
     688        {}
     689        catch (InvocationTargetException ex)
     690        {}
     691      }
     692     
    663693      Method setter = getSetterMethod(beanClass, childName);
    664694      if (setter == null) continue;
     
    689719    @param beanClass The class to look for the setter method in
    690720    @param tagName The tag name in the XML file
    691     @return A Method object or null, if no method is found
     721    @return A Method object, or null if no method is found
    692722  */
    693723  protected Method getSetterMethod(Class<?> beanClass, String tagName)
     
    705735 
    706736  /**
     737    Check if the bean class has a <code>setParameter(String, String)</code>
     738    method and return it's reference if it has.
     739    @param beanClass The class to look for the method in
     740    @return A Method object, or null if no method is found
     741  */
     742  protected Method getSetParameterMethod(Class<?> beanClass)
     743  {
     744    Method setParameter = null;
     745    try
     746    {
     747      setParameter = beanClass.getMethod("setParameter", String.class, String.class);
     748    }
     749    catch (NoSuchMethodException ex)
     750    {}
     751    return setParameter;
     752   
     753  }
     754 
     755  /**
    707756    Convert the tag name to a setter method name.
    708757    @param tagName The tag name
  • trunk/src/test/TestExtensions.java

    r4198 r4207  
    2626
    2727import net.sf.basedb.core.BaseException;
     28import net.sf.basedb.util.Values;
    2829import net.sf.basedb.util.extensions.Action;
    2930import net.sf.basedb.util.extensions.ActionFactory;
    30 import net.sf.basedb.util.extensions.Context;
     31import net.sf.basedb.util.extensions.ClientContext;
    3132import net.sf.basedb.util.extensions.Extension;
    3233import net.sf.basedb.util.extensions.ExtensionPoint;
    3334import net.sf.basedb.util.extensions.ExtensionsInvoker;
     35import net.sf.basedb.util.extensions.InvokationContext;
    3436import net.sf.basedb.util.extensions.Registry;
    3537import net.sf.basedb.util.extensions.Renderer;
    3638import net.sf.basedb.util.extensions.RendererFactory;
     39import net.sf.basedb.util.extensions.xml.PathSetter;
    3740import net.sf.basedb.util.extensions.xml.VariableConverter;
    3841import net.sf.basedb.util.extensions.xml.VariableSetter;
     
    6063   
    6164    test_load_extension_points_from_xml(registry, "data/test.extensions.xml", 1);
    62     test_load_extensions_from_xml(registry, "data/test.extensions.xml", 2);
     65    test_load_extensions_from_xml(registry, "data/test.extensions.xml", 3);
    6366   
    6467    test_render_default(registry, "test.tools");
     
    164167    try
    165168    {
    166       Context context = new Context(TestUtil.getSessionControl());
     169      ClientContext clientContext = new ClientContext(TestUtil.getSessionControl());
    167170      ExtensionsInvoker<ActionButton> manager =
    168         (ExtensionsInvoker<ActionButton>)registry.useExtensions(context, null, extensionPoint);
     171        (ExtensionsInvoker<ActionButton>)registry.useExtensions(clientContext, null, extensionPoint);
    169172     
    170173      manager.renderDefault();
     
    181184  }
    182185 
     186  public interface IActionButton
     187    extends Action
     188  {
     189   
     190    public String getTitle();
     191   
     192    public String getIcon();
     193   
     194    public int getType();
     195   
     196    public boolean isDisabled();
     197   
     198  }
     199 
    183200  public static class ActionButton
    184     implements Action
     201    implements IActionButton
    185202  {
    186203    private final String title;
    187204    private final String icon;
    188    
    189     public ActionButton(String title, String icon)
     205    private final int type;
     206    private final boolean disabled;
     207   
     208    public ActionButton(String title, String icon, int type, boolean disabled)
    190209    {
    191210      this.title = title;
    192211      this.icon = icon;
     212      this.type = type;
     213      this.disabled = disabled;
    193214    }
    194215   
     
    202223      return icon;
    203224    }
     225   
     226    public int getType()
     227    {
     228      return type;
     229    }
     230   
     231    public boolean isDisabled()
     232    {
     233      return disabled;
     234    }
    204235  }
    205236
    206237  public static class ActionButtonFactory
    207     implements ActionFactory<ActionButton>
     238    implements ActionFactory<IActionButton>
    208239  {
    209240
    210241    private String title;
    211242    private String icon;
    212     private ActionButton button;
     243    private int type;
     244    private boolean disabled;
     245   
     246    private IActionButton button;
    213247   
    214248    public ActionButtonFactory()
     
    216250   
    217251    @Override
    218     public ActionButton[] getActions(Context context, Extension<? super ActionButton> extension)
     252    public IActionButton[] getActions(InvokationContext<? super IActionButton> context)
    219253    {
    220254      if (button == null)
    221255      {
    222         button = new ActionButton(title, icon);
    223       }
    224       return new ActionButton[] { button };
    225     }
    226 
    227     @Override
    228     public boolean prepareContext(Context context, Extension<? super ActionButton> extension)
     256        button = new ActionButton(title, icon, type, disabled);
     257      }
     258      return new IActionButton[] { button };
     259    }
     260
     261    @Override
     262    public boolean prepareContext(InvokationContext<? super IActionButton> context)
    229263    {
    230264      return true;
     
    237271   
    238272    @VariableSetter
     273    @PathSetter
    239274    public void setIcon(String icon)
    240275    {
     
    242277    }
    243278   
     279    public void setType(String type)
     280    {
     281      this.type = Values.getInt(type);
     282    }
     283   
     284    public void setDisabled(String disabled)
     285    {
     286      this.disabled = Values.getBoolean(disabled);
     287    }
     288       
    244289  }
    245290 
    246291  public static class ActionButtonRendererFactory
    247     implements RendererFactory<ActionButton>, Renderer<ActionButton>
     292    implements RendererFactory<IActionButton>, Renderer<IActionButton>
    248293  {
    249294   
     
    259304
    260305    @Override
    261     public void prepareContext(Context context, Extension<? extends ActionButton> extension)
    262     {
    263     }
    264    
    265     @Override
    266     public Renderer<ActionButton> getRenderer(Context context, Extension<? extends ActionButton> extension)
     306    public void prepareContext(InvokationContext<? extends IActionButton> context)
     307    {
     308    }
     309   
     310    @Override
     311    public Renderer<IActionButton> getRenderer(InvokationContext<? extends IActionButton> context)
    267312    {
    268313      return this;
     
    270315
    271316    @Override
    272     public void render(ActionButton action)
    273     {
    274       if (!TestUtil.getSilent())
     317    public void render(IActionButton action)
     318    {
     319      if (!TestUtil.getSilent() && !action.isDisabled())
    275320      {
    276321        System.out.println("<div class=\"actionbutton\" style=\"color: " +
    277322            color + ";\"><img src=\"" + action.getIcon() + "\">" +
    278             action.getTitle() + "</div>");
     323            action.getTitle() + " (type=" + action.getType() + ")</div>");
    279324      }
    280325    }
  • trunk/src/test/data/test.extensions.xml

    r4187 r4207  
    3030    id="test.tools"
    3131    >
    32     <action-class>TestExtensions$ActionButton</action-class>
     32    <action-class>TestExtensions$IActionButton</action-class>
    3333    <renderer-factory override="true">
    3434      <factory-class>TestExtensions$ActionButtonRendererFactory</factory-class>
     
    4949        <title>Launch MeV</title>
    5050        <icon>$HOME$/images/mev.png</icon>
     51        <type>11</type>
    5152      </parameters>
    5253    </action-factory>
     
    7374  </extension>
    7475
     76  <extension
     77    id="test.tools.proxy"
     78    extends="test.tools" 
     79    >
     80    <index>15</index>
     81    <action-factory>
     82      <factory-class>net.sf.basedb.util.extensions.debug.ProxyActionFactory</factory-class>
     83      <parameters>
     84        <title>Using proxy</title>
     85        <icon>~/proxy.png</icon>
     86        <type>2</type>
     87        <disabled>false</disabled>
     88      </parameters>
     89    </action-factory>
     90  </extension>
     91
    7592</extensions>
  • trunk/www/admin/extensions/tree.jsp

    r4202 r4207  
    5151  String icon = ec.isEnabled(ep) ? "ExtensionPoint" : "ExtensionPointDisabled";
    5252  ExtensionsFile f = ec.getFileByExtensionId(id);
    53   if (f.hasError()) icon = "ExtensionPointError";
     53  if (f == null || f.hasError()) icon = "ExtensionPointError";
    5454  String joust = "ep = JoustMenu.addChildItem(" + parentNode +", '" + icon + "', " +
    5555      "'" + HTML.javaScriptEncode(name) + "', 'extensionPointOnClick(\"" + id + "\")', " +
     
    6464  String icon = ec.isEnabled(ext) ? "Extension" : "ExtensionDisabled";
    6565  ExtensionsFile f = ec.getFileByExtensionId(id);
    66   if (f.hasError()) icon = "ExtensionError";
     66  if (f == null || f.hasError()) icon = "ExtensionError";
    6767  String joust = "ext = JoustMenu.addChildItem(" + parentNode + ", '" + icon + "', " +
    6868      "'" + HTML.javaScriptEncode(name) + "', 'extensionOnClick(\"" + id + "\")', " +
Note: See TracChangeset for help on using the changeset viewer.