Changeset 5640


Ignore:
Timestamp:
May 24, 2011, 12:09:09 PM (10 years ago)
Author:
Nicklas Nordborg
Message:

References #1590: Documentation cleanup

Checked and changed the following chapters in Part IV: Developer documentation:

  • Plug-in developer sections 7-9. (section 6 is not yet done since there are tickets that will affect lots of information in this section)
  • Extensions developer + added a new section with more information about extension points shipped with BASE.
Location:
trunk/doc/src/docbook/developerdoc
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/src/docbook/developerdoc/extensions.xml

    r5520 r5640  
    3232    <title>Overview</title>
    3333    <para>
    34       The BASE web client includes an extensions mechanism that makes it possible
     34      The BASE application includes an extensions mechanism that makes it possible
    3535      to dynamically add functions to the GUI without having to edit the JSP code.
    3636      It is, for example, possible to add menu items in the menu and toolbar buttons
     
    4141      Go to the
    4242        <menuchoice>
    43           <guimenu>Extensions</guimenu>
    44           <guimenuitem>Installed extensions</guimenuitem>
     43          <guimenu>Administrate</guimenu>
     44          <guimenuitem>Plug-ins &amp; extensions</guimenuitem>
     45          <guimenuitem>Overview</guimenuitem>
    4546        </menuchoice>
    4647      menu to display a list of possible extension points and all installed
     
    5354      Extensions can come in two forms, either as an XML file in the
    5455      <emphasis>BASE Extensions XML</emphasis> format or as a JAR file.
    55       A JAR file is needed when the extension needs to execute custom-made
     56      A JAR file is required when the extension needs to execute custom-made
    5657      code or use custom resources such as icons, css stylesheets, or
    5758      JSP files.
     
    7778
    7879      <para>
    79         The code examples in this chapter can be downloaded from
    80         <ulink url="http://baseplugins.thep.lu.se/wiki/net.sf.basedb.examples.extensions">The
    81         BASE plug-ins site</ulink>.
     80        The code examples in this chapter can be downloaded from the
     81        BASE plug-ins site:
     82        <ulink url="http://baseplugins.thep.lu.se/wiki/net.sf.basedb.examples.extensions"
     83        >http://baseplugins.thep.lu.se/wiki/net.sf.basedb.examples.extensions</ulink>
    8284      </para>
    8385    </sect2>
     
    9193        <listitem>
    9294          <para>
    93           An extensions point is a place in the BASE web client interface
    94           where it is possible to extend the GUI with custom extensions. An
     95          An extensions point is a place in the BASE core or web client interface
     96          where it is possible to extend the functionality with custom extensions. An
    9597          extension point has an ID which must be unique among all existing
    9698          extension points. Extension points registered by the BASE web client all
    97           starts with <code>net.sf.basedb.clients.web</code>. The
     99          starts with <code>net.sf.basedb.clients.web</code> prefix. The
    98100          extension point also defines an
    99101          <interfacename docapi="net.sf.basedb.util.extensions">Action</interfacename>
    100           class that all extensions must "implement".
     102          subclass that all extensions must implement.
    101103          </para>
    102104        </listitem>
     
    108110          <para>
    109111          An extensions is a custom addition to the BASE web client
    110           interface. This can mean a new menu item in the menu or a
     112          interface or core API. This can mean a new menu item in the menu or a
    111113          new button in a toolbar. An extension must provide an
    112114          <interfacename docapi="net.sf.basedb.util.extensions">ActionFactory</interfacename>
     
    156158          Some extension points uses a locked renderer, while other extension
    157159          points provides a default renderer, but allows extensions to supply their
    158           own if they want to.
     160          own if they want to. Renderers are mostly used by the web client extensions,
     161          not so much by the core extensions.
    159162          </para>
    160163        </listitem>
     
    174177
    175178      <varlistentry>
    176         <term>Errro handler factory</term>
     179        <term>Error handler factory</term>
    177180        <listitem>
    178181          <para>
    179182          An <interfacename docapi="net.sf.basedb.util.extensions">ErrorHandlerFactory</interfacename>
    180183          is an object that knows how to handle error that occur when executing extensions.
    181           An error handler factory is part of an extension point and handles all errors
    182           related to the extensions of that extension point. In most other aspects
     184          An error handler factory is defined as part of an extension point and handles all
     185          errors related to the extensions of that extension point. In most other aspects
    183186          error handler factories are similar to renderer and action factories. If the
    184187          extension point doesn't define an error handler factory, the system will
     
    204207          Wherever a <classname>ClientContext</classname> object is provided as a
    205208          parameter it is always safe to cast it to a <classname>JspContext</classname>
    206           object.
     209          object. Extension points in the core usually use a
     210          <classname>ClientContext</classname>.
    207211          </para>
    208212         
     
    228232      menu which displays a popup with the text "Hello world!" when
    229233      selected. Copy the XML code below and save it to a file in
    230       the <filename>/WEB-INF/extensions</filename>
     234      the <filename>plugins.dir</filename>
    231235      directory. The filename must end with <filename>.xml</filename>.
    232       If you have enabled automatic installation just wait a few seconds and the
    233       extension will be installed automatically. Otherwise you may have to do a manual scan:
    234       (<menuchoice>
    235         <guimenu>Extensions</guimenu>
    236         <guimenuitem>Manual scan&hellip;</guimenuitem>
    237       </menuchoice>).
     236      Install the extension by going through the installation wizard
     237      at <menuchoice>
     238          <guimenu>Administrate</guimenu>
     239          <guimenuitem>Plug-ins &amp; extensions</guimenuitem>
     240          <guimenuitem>Overview</guimenuitem>
     241        </menuchoice>.
    238242    </para>
    239243   
     
    299303      attribute we recommend using the same naming conventions as for java
    300304      packages. See <ulink
    301       url="http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html">Java naming
    302       conventions from Sun</ulink>.
     305      url="http://www.oracle.com/technetwork/java/codeconventions-135099.html">Java naming
     306      conventions from Oracle</ulink>.
    303307    </para>
    304308   
     
    771775      are located in the extension's JAR file. The reason is that the
    772776      JAR file is not known to Tomcat and Tomcat will not look in the
    773       <filename>WEB-INF/extensions</filename> folder to
     777      <filename>plugins.dir</filename> folder to
    774778      try to find classes. There are currently two possible workarounds:
    775779      </para>
     
    874878        use classes from the extension's JAR file in the JSP code. The reason
    875879        is that the JAR file is not known to Tomcat and Tomcat will not look
    876         in the <filename>WEB-INF/extensions</filename> folder to try to find
     880        in the <filename>plugins.dir</filename> folder to try to find
    877881        classes.
    878882      </para>
     
    10981102      is unique among all installed extension points. We recommend using
    10991103      the same naming conventions as for java packages. See <ulink
    1100       url="http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html">Java naming
    1101       conventions from Sun</ulink>.
     1104      url="http://www.oracle.com/technetwork/java/codeconventions-135099.html">Java naming
     1105      conventions from Oracle</ulink>.
    11021106    </para>
    11031107   
     
    13971401      Invoking the servlet is done with a URL that is constructed like:
    13981402      <filename>$HOME$/[servlet-name].servlet</filename>, where <code>$HOME$</code>
    1399       is the home directory of the extension. Since BASE 2.13 an alternate URL
     1403      is the home directory of the extension. An alternate URL
    14001404      that doesn't require the <filename>.servlet</filename> extension is available:
    14011405      <filename>$SERVLET_HOME$/[servlet-name]</filename>, where <code>$SERVLET_HOME$</code>
     
    14041408    </para>
    14051409    <para>
    1406       Extra path information is supported (since BASE 2.10)
     1410      Extra path information is supported
    14071411      if it is inserted between the servlet name and the <filename>.servlet</filename>
    14081412      extension: <filename>$HOME$/[servlet-name][/extra/path/info].servlet</filename>,
     
    14591463  </sect1>
    14601464 
     1465  <sect1 id="extensions_developer.base_extension_points">
     1466    <title>Extension points defined by BASE</title>
     1467   
     1468    <para>
     1469      In this section, we will give an overview of the extension points defined
     1470      by BASE. Most extension points are used in the web client to add
     1471      buttons and menu items, but there are a few for the core API as well.
     1472    </para>
     1473   
     1474    <sect2 id="extensions_developer.menuitems">
     1475      <title>Menu: extensions</title>
     1476     
     1477      <para>
     1478        Menu items can be added to the top-level
     1479        <menuchoice><guimenu>Extensions</guimenu></menuchoice>
     1480        menu. Actions should implement the interface: <interfacename
     1481        docapi="net.sf.basedb.clients.web.extensions.menu">net.sf.basedb.clients.web.extensions.menu.MenuItemAction</interfacename>
     1482      </para>
     1483     
     1484      <para>
     1485        The <methodname>MenuItemAction.getMenuType()</methodname> provides support
     1486        for <constant>MENUITEM</constant>, <constant>SUBMENU</constant> and
     1487        <constant>SEPARATOR</constant> menus. Which of the other properties that
     1488        are needed depend on the menu type. Read the javadoc for more information.
     1489        This extension point doesn't support custom javascripts or stylesheets and
     1490        the rendering is internal (eg. extensions can't provide their own renderers).
     1491      </para>
     1492     
     1493      <para>
     1494        BASE ships with two action factories:
     1495        <classname docapi="net.sf.basedb.clients.web.extensions.menu">
     1496          net.sf.basedb.clients.web.extensions.menu.FixedMenuItemFactory
     1497        </classname> and
     1498        <classname docapi="net.sf.basedb.clients.web.extensions.menu">
     1499          net.sf.basedb.clients.web.extensions.menu.PermissionMenuItemFactory
     1500        </classname>.
     1501       
     1502        The fixed factory provides a menu that is the same for all users.
     1503        The permission factory can disable or hide a menu depending on the
     1504        logged in user's role-based permissions. The title, icon, etc. can have
     1505        different values depending on if the menu item is disabled or enabled.
     1506      </para>
     1507    </sect2>
     1508   
     1509    <sect2 id="extensions_developer.toolbars">
     1510      <title>Toolbars</title>
     1511      <para>
     1512        Most toolbars on all list and single-item view pages can
     1513        be extended with extra buttons. Actions should implement
     1514        the interface: <interfacename
     1515          docapi="net.sf.basedb.clients.web.extensions.toolbar">
     1516          net.sf.basedb.clients.web.extensions.toolbar.ButtonAction
     1517        </interfacename>.
     1518        Button actions are very simple and only need to provide things like
     1519        a title, tooltip, on-click script, etc. This extension point has
     1520        support for custom javascript, stylesheets and renderers. The
     1521        default renderer is <classname
     1522        docapi="net.sf.basedb.clients.web.extensions.toolbar">ToolbarButtonRendererFactory</classname>.
     1523      </para>
     1524
     1525      <para>
     1526        BASE ships with two action factories:
     1527        <classname docapi="net.sf.basedb.clients.web.extensions.toolbar">
     1528          net.sf.basedb.clients.web.extensions.toolbar.FixedButtonFactory
     1529        </classname> and
     1530        <classname docapi="net.sf.basedb.clients.web.extensions.toolbar">
     1531          net.sf.basedb.clients.web.extensions.toolbar.PermissionButtonFactory
     1532        </classname>.
     1533       
     1534        The fixed factory provides a toolbar button that is the same for all users.
     1535        The permission factory can disable or hide a buton depending on the
     1536        logged in user's role-based permissions. The title, icon, etc. can have
     1537        different values depending on if the menu item is disabled or enabled.
     1538      </para>
     1539    </sect2>
     1540
     1541    <sect2 id="extensions_developer.edit_dialogs">
     1542      <title>Edit dialogs</title>
     1543     
     1544      <para>
     1545        Most item edit dialogs can be extended with additional tabs.
     1546        Actions should implement the interface: <interfacename
     1547          docapi="net.sf.basedb.clients.web.extensions.tabcontrol">
     1548          net.sf.basedb.clients.web.extensions.tabcontrol.TabAction
     1549        </interfacename>.
     1550        The actions are, in principle, simple and only need to
     1551        provide a title and content (HTML). The action may also provide
     1552        javascripts for validation, etc. This extension point has support
     1553        for custom stylesheets and javascript. Rendering is fixed and can't
     1554        be overridden.
     1555      </para>
     1556     
     1557      <para>
     1558        BASE ships with two action factories:
     1559        <classname docapi="net.sf.basedb.clients.web.extensions.tabcontrol">
     1560          net.sf.basedb.clients.web.extensions.tabcontrol.FixedTabFactory
     1561        </classname> and
     1562        <classname docapi="net.sf.basedb.clients.web.extensions.tabcontrol">
     1563          net.sf.basedb.clients.web.extensions.tabcontrol.IncludeContentTabFactory
     1564        </classname>.
     1565       
     1566        The fixed factory provides a tab with fixed content that same for all users
     1567        and the same for all items. This factory is not very useful in a real scenario.
     1568        The other factory provides content by including the output from another resource,
     1569        eg. a JSP page, a servlet, etc. The current context is stored in a request-scoped
     1570        attribute under the key given by <code>JspContext.ATTRIBUTE_KEY</code>.
     1571        A JSP or servlet should use this to hook into the current flow. Here is a code example:
     1572      </para>
     1573     
     1574      <programlisting language="java">
     1575<![CDATA[
     1576// Get the JspContext that was created on the main edit page
     1577final JspContext jspContext = (JspContext)request.getAttribute(JspContext.ATTRIBUTE_KEY);
     1578
     1579// The current item is found in the context. NOTE! Can be null if a new item
     1580final BasicItem item = (BasicItem)jspContext.getCurrentItem();
     1581
     1582// Get the DbControl and SessionControl used to handle the request (do not close!)
     1583final DbControl dc = jspContext.getDbControl();
     1584final SessionControl sc = dc.getSessionControl();
     1585]]>
     1586</programlisting>
     1587
     1588      <para>
     1589        The extra tab need to be paired with an extensions that is invoked when
     1590        the edit form is saved. Each edit-dialog extension point has a corresponding
     1591        on-save extension point. Actions should implement the interface: <interfacename
     1592          docapi="net.sf.basedb.clients.web.extensions.edit">
     1593          net.sf.basedb.clients.web.extensions.edit.OnSaveAction
     1594        </interfacename>.
     1595       
     1596        This interface define three callback methods that BASE will call when
     1597        saving an item. The <methodname>OnSaveAction.onSave()</methodname>
     1598        method is called first, but not until all regular properties have been
     1599        updated. If the transaction is committed the <methodname>OnSaveAction.onCommit()</methodname>
     1600        method is also called, otherwise the <methodname>OnSaveAction.onRollback()</methodname>
     1601        is called. The <methodname>onSave()</methodname> method can throw an exception that
     1602        will be displayed to the user. The other callback method should not throw exceptions
     1603        at all, since that may result in undefined behaviour and can be confusing for the user.
     1604      </para>
     1605    </sect2>
     1606   
     1607    <sect2 id="extensions_developer.bioassayset_tools">
     1608      <title>Bioassay set: Tools</title>
     1609      <para>
     1610        The bioassay set listing for an experiment has a <guilabel>Tools</guilabel>
     1611        column which can be extended by extensions. This extension point is similar
     1612        to the toolbar extension points and actions should implement
     1613        the interface: <interfacename
     1614          docapi="net.sf.basedb.clients.web.extensions.toolbar">
     1615          net.sf.basedb.clients.web.extensions.toolbar.ButtonAction
     1616        </interfacename>.
     1617      </para>
     1618     
     1619      <para>
     1620        Note that the list can contain
     1621        <classname docapi="net.sf.basedb.core">BioAssaySet</classname>,
     1622        <classname docapi="net.sf.basedb.core">Transformation</classname> and
     1623        <classname docapi="net.sf.basedb.core">ExtraValue</classname> items.
     1624        The factory implementation need to be aware of this if it uses
     1625        the <methodname>JspContext.getItem()</methodname> method to examine the
     1626        current item.
     1627      </para>
     1628    </sect2>
     1629
     1630    <sect2 id="extensions_developer.bioassayset_plots">
     1631      <title>Bioassay set: Overview plots</title>
     1632      <para>
     1633        The bioassay set page has a tab <guilabel>Overview plots</guilabel>.
     1634        The contents of this tab is supposed to be some kind of images
     1635        that have been generated from the data in the current bioassay set.
     1636        What kind of plots that can be generated typically depends on the
     1637        kind of data you have. BASE ships with an extension
     1638        (<classname docapi="net.sf.basedb.clients.web.extensions">MAPlotFactory</classname>)
     1639        that creates
     1640        MA plots and Correction factor plots for 2-channel bioassays.
     1641        Actions should implement
     1642        the interface: <interfacename
     1643          docapi="net.sf.basedb.clients.web.extensions.plot">
     1644          net.sf.basedb.clients.web.extensions.plot.OverviewPlotAction
     1645        </interfacename>. A single action generates a sub-tab in the
     1646        <guilabel>Overview plots</guilabel> tab. The sub-tab may contain
     1647        one or more images. Each image is defined by a
     1648        <interfacename docapi="net.sf.basedb.clients.web.extensions.plot">PlotGenerator</interfacename>
     1649        which sets the size of the image and provides an URL to a servlet that generates
     1650        the actual image.
     1651      </para>
     1652     
     1653    </sect2>
     1654
     1655    <sect2 id="extensions_developer.services">
     1656      <title>Services</title>
     1657      <para>
     1658        A service is a piece of code that is loaded when the BASE web
     1659        server starts up. The service is then running as long as the BASE web
     1660        server is running. It is possible to manually stop and start services.
     1661        This extension point is different from most others in that it doesn't
     1662        affects the visible interface. Since services are loaded at startup time,
     1663        this also means that the context passed to ActionFactory methods will
     1664        not have any <classname>ClientContext</classname> associated with it
     1665        (eg. the <methodname>InvokationContext.getClientContext()</methodname>
     1666        always return null). There is also no meaning for extensions to specify
     1667        a <interfacename>RendererFactory</interfacename>. Service actions should
     1668        implement the interface: <interfacename
     1669          docapi="net.sf.basedb.clients.web.extensions.service">
     1670          net.sf.basedb.clients.web.extensions.service.ServiceControllerAction
     1671        </interfacename>.
     1672       
     1673        The interface provides <methodname>start()</methodname> and
     1674        <methodname>stop()</methodname> methods for controlling the service.
     1675        BASE doesn't ship with any service, but there is an FTP service
     1676        available at the BASE plug-ins site: <ulink
     1677        url="http://baseplugins.thep.lu.se/wiki/net.sf.basedb.ftp">
     1678        http://baseplugins.thep.lu.se/wiki/net.sf.basedb.ftp</ulink>
     1679      </para>
     1680     
     1681    </sect2>
     1682
     1683    <sect2 id="extensions_developer.connection_manager">
     1684      <title>Connection managers</title>
     1685      <para>
     1686        This extension point adds support for using external files
     1687        in BASE. This is a core extension point and is available
     1688        independently of the web client. Actions should implement
     1689        the interface: <interfacename
     1690          docapi="net.sf.basedb.util.uri">
     1691          net.sf.basedb.util.uri.ConnectionManagerFactory
     1692        </interfacename>.
     1693      </para>
     1694     
     1695      <para>
     1696        The <methodname>getDisplayName()</methodname> and <methodname>getDescription()</methodname>
     1697        methods are used in the gui when a user manually selects which connection
     1698        manager to use. The <methodname>supports()</methodname> is used when auto-selecting
     1699        a connection manager base on the URI of the file.
     1700      </para>
     1701     
     1702      <para>
     1703        BASE ships with factory that supports HTTP and HTTPS file
     1704        references: <classname
     1705        docapi="net.sf.basedb.util.uri.http">HttpConnectionManagerFactory</classname>.
     1706       
     1707        The BASE plug-ins site has an connection manager that support
     1708        the Hadoop distributed file system (HDFS): <ulink
     1709        url="http://baseplugins.thep.lu.se/wiki/net.sf.basedb.hdfs">
     1710        http://baseplugins.thep.lu.se/wiki/net.sf.basedb.hdfs</ulink>
     1711      </para>
     1712     
     1713    </sect2>
     1714
     1715    <sect2 id="extensions_developer.fileset_validator">
     1716      <title>Fileset validators</title>
     1717     
     1718      <para>
     1719     
     1720      </para>
     1721     
     1722    </sect2>
     1723   
     1724  </sect1>
     1725 
    14611726</chapter>
  • trunk/doc/src/docbook/developerdoc/migrate_2_3.xml

    r5634 r5640  
    7373      <ulink url="http://base2.thep.lu.se/base/jars/">http://base2.thep.lu.se/base/jars/</ulink>.
    7474    </para>
    75      
    76     <bridgehead>Other changes to the API</bridgehead>
     75  </sect1>
     76 
     77  <sect1 id="migrate_2_3.coreapi">
     78 
     79    <title>Core API changes</title>
    7780
    7881    <para>
     
    134137          <classname docapi="net.sf.basedb.core">DataFileType</classname>.
    135138          This feature is now implemented as extensions. The API is slightly
    136           different and classes have been moved around a bit. See <ulink
     139          different and classes have been moved around a bit. See
     140          <xref linkend="extensions_developer.fileset_validator"/> and
     141          <ulink
    137142          url="http://base.thep.lu.se/ticket/1598">ticket #1598 (Use
    138143          the extensions system for data file validators and metadata readers)</ulink> for more information.
  • trunk/doc/src/docbook/developerdoc/plugin_developer.xml

    r5633 r5640  
    47724772   
    47734773    <para>
    4774       We recommend that plug-in JAR files are installed outside the web server's
    4775       classpath. If you are using Tomcat this means that you should not
    4776       install the plug-in in the <filename>&lt;base-dir&gt;/www/WEB-INF/lib</filename>
    4777       directory or any other directory where the web server keeps it's classes.
    4778       The rest of the information in this section only applies to plug-ins that
    4779       have been installed following this restriction.
     4774      All plug-ins should be installed in the location specified by the
     4775      <varname>plugins.dir</varname> setting in <filename>base.config</filename>.
     4776      While it is possible to also install them in a location that is on the
     4777      classpath, for example <filename>&lt;base-dir&gt;/www/WEB-INF/lib</filename>,
     4778      it is nothing that we recommend. The rest of the information in this section
     4779      only applies to plug-ins that have been installed in the <varname>plugins.dir</varname>
     4780      location.
    47804781    </para>
    47814782   
     
    48424843
    48434844// Ok
    4844 Plugin other = def.newInstance(Plugin.class, null, sc, null, null);
     4845Plugin other = def.newInstance();
    48454846
    48464847// Not ok; fails with ClassCastException
    4847 MyOtherPlugin other = def.newInstance(MyOtherPlugin.class, null, sc, null, null);
     4848MyOtherPlugin other = (MyOtherPlugin)def.newInstance();
     4849
     4850// Ok; since now we are using the correct class loader
     4851MyOtherPlugin other = def.newInstance(MyOtherPlugin.class);
    48484852</programlisting>
    48494853     
    48504854      <para>
    4851       The reason that the second call fails is that BASE uses a different
    4852       classloader to load the <classname>ex.MyOtherPlugin</classname> class. This
     4855      The first call succeeds because it uses the <interfacename
     4856      docapi="net.sf.basedb.core.plugin">Plugin</interfacename>
     4857      interface which is defined by BASE. This class is loaded by the web servers
     4858      class loader and is the same for all plug-ins.
     4859      </para>
     4860     
     4861      <para>
     4862      The second call fails because BASE uses a different classloader to load the
     4863      <classname>ex.MyOtherPlugin</classname> class. This
    48534864      class is not (in Java terms) the same as the <classname>ex.MyOtherPlugin</classname>
    48544865      class loaded by the classloader that loaded the <classname>ex.MyPlugin</classname>
     
    48584869     
    48594870      <para>
    4860       The first call always succeeds because it uses the <interface>Plugin</interface>
    4861       interface which is defined by BASE. This class is loaded by the web servers class
    4862       loader and is the same for all plug-ins.
     4871      The third call succeeds because now that we specify the class as an argument,
     4872      BASE uses that classloader instead.
    48634873      </para>
    48644874     
    48654875      <para>
    4866       A third option is that the <classname>ex.MyPlugin</classname>
     4876      Another option is that the <classname>ex.MyPlugin</classname>
    48674877      lists the JAR file where <classname>ex.MyOtherPlugin</classname> is
    48684878      located in it's <filename>MANIFEST.MF</filename> file. Then, the following
     
    48754885    <para>
    48764886      Tomcat includes a good document describing how classloading is implemented
    4877       in Tomcat: <ulink url="http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html"
     4887      in Tomcat: <ulink url="http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html"
    48784888        >http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html</ulink>.
    48794889     
     
    49114921      can ask a user for one or more parameters.
    49124922   
    4913       You can <ulink url="http://baseplugins.thep.lu.se/wiki/net.sf.basedb.examples.plugins">download
    4914       a tar file with the source and compiled plug-in code</ulink> from the BASE plug-ins website.
     4923      You can download
     4924      a tar file with the source and compiled plug-in code from the BASE plug-ins website:
     4925      <ulink url="http://baseplugins.thep.lu.se/wiki/net.sf.basedb.examples.extensions"
     4926      >http://baseplugins.thep.lu.se/wiki/net.sf.basedb.examples.extensions</ulink>
    49154927    </para>
    49164928   
Note: See TracChangeset for help on using the changeset viewer.