doc/src/docbook/developer/extensions.xml

Code
Comments
Other
Rev Date Author Line
4184 20 Mar 08 nicklas 1 <?xml version="1.0" encoding="UTF-8"?>
4184 20 Mar 08 nicklas 2 <!DOCTYPE chapter PUBLIC 
4184 20 Mar 08 nicklas 3     "-//Dawid Weiss//DTD DocBook V3.1-Based Extension for XML and graphics inclusion//EN" 
4184 20 Mar 08 nicklas 4     "../../../../lib/docbook/preprocess/dweiss-docbook-extensions.dtd">
4184 20 Mar 08 nicklas 5 <!--
4223 15 Apr 08 nicklas 6   $Id$
4184 20 Mar 08 nicklas 7   
4184 20 Mar 08 nicklas 8   Copyright (C) 2008
4184 20 Mar 08 nicklas 9   
4184 20 Mar 08 nicklas 10   This file is part of BASE - BioArray Software Environment.
4184 20 Mar 08 nicklas 11   Available at http://base.thep.lu.se/
4184 20 Mar 08 nicklas 12   
4184 20 Mar 08 nicklas 13   BASE is free software; you can redistribute it and/or
4184 20 Mar 08 nicklas 14   modify it under the terms of the GNU General Public License
4477 05 Sep 08 jari 15   as published by the Free Software Foundation; either version 3
4184 20 Mar 08 nicklas 16   of the License, or (at your option) any later version.
4184 20 Mar 08 nicklas 17   
4184 20 Mar 08 nicklas 18   BASE is distributed in the hope that it will be useful,
4184 20 Mar 08 nicklas 19   but WITHOUT ANY WARRANTY; without even the implied warranty of
4184 20 Mar 08 nicklas 20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4184 20 Mar 08 nicklas 21   GNU General Public License for more details.
4184 20 Mar 08 nicklas 22   
4184 20 Mar 08 nicklas 23   You should have received a copy of the GNU General Public License
4509 11 Sep 08 jari 24   along with BASE. If not, see <http://www.gnu.org/licenses/>.
4184 20 Mar 08 nicklas 25 -->
4184 20 Mar 08 nicklas 26
4206 04 Apr 08 nicklas 27 <chapter id="extensions_developer">
5782 04 Oct 11 nicklas 28   <?dbhtml dir="extensions" filename="index.html" ?>
4206 04 Apr 08 nicklas 29   <title>Extensions developer</title>
4184 20 Mar 08 nicklas 30
4206 04 Apr 08 nicklas 31   <sect1 id="extensions_developer.overview">
5782 04 Oct 11 nicklas 32     <?dbhtml filename="overview.html" ?>
4184 20 Mar 08 nicklas 33     <title>Overview</title>
4184 20 Mar 08 nicklas 34     <para>
5640 24 May 11 nicklas 35       The BASE application includes an extensions mechanism that makes it possible 
4184 20 Mar 08 nicklas 36       to dynamically add functions to the GUI without having to edit the JSP code. 
4184 20 Mar 08 nicklas 37       It is, for example, possible to add menu items in the menu and toolbar buttons 
4184 20 Mar 08 nicklas 38       in selected toolbars. 
4184 20 Mar 08 nicklas 39     </para>
4184 20 Mar 08 nicklas 40     
4184 20 Mar 08 nicklas 41     <para>
4184 20 Mar 08 nicklas 42       Go to the 
4184 20 Mar 08 nicklas 43         <menuchoice>
5640 24 May 11 nicklas 44           <guimenu>Administrate</guimenu>
5640 24 May 11 nicklas 45           <guimenuitem>Plug-ins &amp; extensions</guimenuitem>
5640 24 May 11 nicklas 46           <guimenuitem>Overview</guimenuitem>
4184 20 Mar 08 nicklas 47         </menuchoice>
4184 20 Mar 08 nicklas 48       menu to display a list of possible extension points and all installed 
4184 20 Mar 08 nicklas 49       extensions. From this page, if you are logged in with enough permissions, 
4184 20 Mar 08 nicklas 50       it is also possible to configure the extensions system, enable/disable
5737 14 Sep 11 nicklas 51       extensions, etc. Read more about this in <xref linkend="plugins" />.
4184 20 Mar 08 nicklas 52     </para>
4184 20 Mar 08 nicklas 53
4184 20 Mar 08 nicklas 54     <para>
4184 20 Mar 08 nicklas 55       Extensions can come in two forms, either as an XML file in the
4184 20 Mar 08 nicklas 56       <emphasis>BASE Extensions XML</emphasis> format or as a JAR file. 
5640 24 May 11 nicklas 57       A JAR file is required when the extension needs to execute custom-made
4184 20 Mar 08 nicklas 58       code or use custom resources such as icons, css stylesheets, or 
4184 20 Mar 08 nicklas 59       JSP files.
4184 20 Mar 08 nicklas 60     </para>
4184 20 Mar 08 nicklas 61
4223 15 Apr 08 nicklas 62     <itemizedlist>
4223 15 Apr 08 nicklas 63       <title>More reading</title>
4223 15 Apr 08 nicklas 64       <listitem>
4223 15 Apr 08 nicklas 65         <para>
5737 14 Sep 11 nicklas 66         <xref linkend="plugins" />.
4223 15 Apr 08 nicklas 67         </para>
4223 15 Apr 08 nicklas 68       </listitem>
4223 15 Apr 08 nicklas 69       
4223 15 Apr 08 nicklas 70       <listitem>
4223 15 Apr 08 nicklas 71         <para>
5781 04 Oct 11 nicklas 72         <xref linkend="core_api.extensions" />.
4223 15 Apr 08 nicklas 73         </para>
4223 15 Apr 08 nicklas 74       </listitem>
4223 15 Apr 08 nicklas 75     </itemizedlist>
4223 15 Apr 08 nicklas 76
4206 04 Apr 08 nicklas 77     <sect2 id="extensions_developer.examplecode">
4184 20 Mar 08 nicklas 78       <title>Download code examples</title>
4184 20 Mar 08 nicklas 79
4184 20 Mar 08 nicklas 80       <para>
5640 24 May 11 nicklas 81         The code examples in this chapter can be downloaded from the
5640 24 May 11 nicklas 82         BASE plug-ins site: 
7982 14 Jun 21 nicklas 83         <ulink url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.examplecode"
7982 14 Jun 21 nicklas 84         >https://baseplugins.thep.lu.se/wiki/net.sf.basedb.examplecode</ulink>
4184 20 Mar 08 nicklas 85       </para>
4184 20 Mar 08 nicklas 86     </sect2>
4184 20 Mar 08 nicklas 87
4206 04 Apr 08 nicklas 88     <sect2 id="extensions_developer.terminology">
4184 20 Mar 08 nicklas 89       <title>Terminology</title>
4184 20 Mar 08 nicklas 90       
4184 20 Mar 08 nicklas 91       <variablelist>
4184 20 Mar 08 nicklas 92       <varlistentry>
4184 20 Mar 08 nicklas 93         <term>Extension point</term>
4184 20 Mar 08 nicklas 94         <listitem>
4184 20 Mar 08 nicklas 95           <para>
5640 24 May 11 nicklas 96           An extensions point is a place in the BASE core or web client interface
5640 24 May 11 nicklas 97           where it is possible to extend the functionality with custom extensions. An 
4184 20 Mar 08 nicklas 98           extension point has an ID which must be unique among all existing
4184 20 Mar 08 nicklas 99           extension points. Extension points registered by the BASE web client all 
5640 24 May 11 nicklas 100           starts with <code>net.sf.basedb.clients.web</code> prefix. The
4184 20 Mar 08 nicklas 101           extension point also defines an 
4184 20 Mar 08 nicklas 102           <interfacename docapi="net.sf.basedb.util.extensions">Action</interfacename>
5640 24 May 11 nicklas 103           subclass that all extensions must implement.
4184 20 Mar 08 nicklas 104           </para>
4184 20 Mar 08 nicklas 105         </listitem>
4184 20 Mar 08 nicklas 106       </varlistentry>
4184 20 Mar 08 nicklas 107       
4184 20 Mar 08 nicklas 108       <varlistentry>
4184 20 Mar 08 nicklas 109         <term>Extension</term>
4184 20 Mar 08 nicklas 110         <listitem>
4184 20 Mar 08 nicklas 111           <para>
4184 20 Mar 08 nicklas 112           An extensions is a custom addition to the BASE web client 
5640 24 May 11 nicklas 113           interface or core API. This can mean a new menu item in the menu or a
4184 20 Mar 08 nicklas 114           new button in a toolbar. An extension must provide an
4184 20 Mar 08 nicklas 115           <interfacename docapi="net.sf.basedb.util.extensions">ActionFactory</interfacename>
4184 20 Mar 08 nicklas 116           that knows how to create actions that fits the requirements
4184 20 Mar 08 nicklas 117           from the extension point the extension is extending.
4184 20 Mar 08 nicklas 118           </para>
4184 20 Mar 08 nicklas 119         </listitem>
4184 20 Mar 08 nicklas 120       </varlistentry>
4184 20 Mar 08 nicklas 121       
4184 20 Mar 08 nicklas 122       <varlistentry>
4184 20 Mar 08 nicklas 123         <term>Action</term>
4184 20 Mar 08 nicklas 124         <listitem>
4184 20 Mar 08 nicklas 125           <para>
4184 20 Mar 08 nicklas 126           An <interfacename docapi="net.sf.basedb.util.extensions">Action</interfacename>
4184 20 Mar 08 nicklas 127           is an interface definition which provides an extension point enough 
4184 20 Mar 08 nicklas 128           information to make it possible to render the action as HTML.
4184 20 Mar 08 nicklas 129           An action typically has methods such as, <code>getTitle()</code>,
4184 20 Mar 08 nicklas 130           <code>getIcon()</code> and <code>getOnClick()</code>. 
4184 20 Mar 08 nicklas 131           </para>
4184 20 Mar 08 nicklas 132         </listitem>
4184 20 Mar 08 nicklas 133       </varlistentry>
4184 20 Mar 08 nicklas 134       
4184 20 Mar 08 nicklas 135       <varlistentry>
4184 20 Mar 08 nicklas 136         <term>Action factory</term>
4184 20 Mar 08 nicklas 137         <listitem>
4184 20 Mar 08 nicklas 138           <para>
4184 20 Mar 08 nicklas 139           An <interfacename docapi="net.sf.basedb.util.extensions">ActionFactory</interfacename>
4184 20 Mar 08 nicklas 140           is an object that knows how to create actions of some specific type, for
4184 20 Mar 08 nicklas 141           example menu item actions. Action factories are part of an
4184 20 Mar 08 nicklas 142           extension definition and can usually be configured with parameters
4184 20 Mar 08 nicklas 143           from the XML file. BASE ships with several implementations of
4184 20 Mar 08 nicklas 144           action factories for all defined extension points. Still, if your
4184 20 Mar 08 nicklas 145           extension needs a different implementation you can easily create your
4184 20 Mar 08 nicklas 146           own factory.
4184 20 Mar 08 nicklas 147           </para>
4184 20 Mar 08 nicklas 148         </listitem>
4184 20 Mar 08 nicklas 149       </varlistentry>
4184 20 Mar 08 nicklas 150       
4184 20 Mar 08 nicklas 151       <varlistentry>
4184 20 Mar 08 nicklas 152         <term>Renderer</term>
4184 20 Mar 08 nicklas 153         <listitem>
4184 20 Mar 08 nicklas 154           <para>
4184 20 Mar 08 nicklas 155           A <interfacename docapi="net.sf.basedb.util.extensions">Renderer</interfacename>
4184 20 Mar 08 nicklas 156           is an object that knows how to convert the information in an action to
4184 20 Mar 08 nicklas 157           HTML. The use of renderers are optional. Some extension points use a
4223 15 Apr 08 nicklas 158           "hard-coded" approach that renders the actions directly on the JSP file.
4184 20 Mar 08 nicklas 159           Some extension points uses a locked renderer, while other extension
4184 20 Mar 08 nicklas 160           points provides a default renderer, but allows extensions to supply their
5640 24 May 11 nicklas 161           own if they want to. Renderers are mostly used by the web client extensions,
5640 24 May 11 nicklas 162           not so much by the core extensions.
4184 20 Mar 08 nicklas 163           </para>
4184 20 Mar 08 nicklas 164         </listitem>
4184 20 Mar 08 nicklas 165       </varlistentry>
4184 20 Mar 08 nicklas 166   
4184 20 Mar 08 nicklas 167       <varlistentry>
4184 20 Mar 08 nicklas 168         <term>Renderer factory</term>
4184 20 Mar 08 nicklas 169         <listitem>
4184 20 Mar 08 nicklas 170           <para>
4184 20 Mar 08 nicklas 171           A <interfacename docapi="net.sf.basedb.util.extensions">RendererFactory</interfacename>
4184 20 Mar 08 nicklas 172           is an object that knows how to create renderers. Renderer factories can
4184 20 Mar 08 nicklas 173           be part of both extension points and extensions. In most other aspects
4184 20 Mar 08 nicklas 174           renderer factories are very similar to action factories.
4184 20 Mar 08 nicklas 175           </para>
4184 20 Mar 08 nicklas 176         </listitem>
4184 20 Mar 08 nicklas 177       </varlistentry>
5487 15 Nov 10 nicklas 178
5487 15 Nov 10 nicklas 179       <varlistentry>
5640 24 May 11 nicklas 180         <term>Error handler factory</term>
5487 15 Nov 10 nicklas 181         <listitem>
5487 15 Nov 10 nicklas 182           <para>
5487 15 Nov 10 nicklas 183           An <interfacename docapi="net.sf.basedb.util.extensions">ErrorHandlerFactory</interfacename>
5487 15 Nov 10 nicklas 184           is an object that knows how to handle error that occur when executing extensions. 
5640 24 May 11 nicklas 185           An error handler factory is defined as part of an extension point and handles all
5640 24 May 11 nicklas 186           errors related to the extensions of that extension point. In most other aspects
5487 15 Nov 10 nicklas 187           error handler factories are similar to renderer and action factories. If the 
5487 15 Nov 10 nicklas 188           extension point doesn't define an error handler factory, the system will 
5487 15 Nov 10 nicklas 189           select a default that only writes a message to the log file
5487 15 Nov 10 nicklas 190           <classname docapi="net.sf.basedb.util.extensions">LoggingErrorHandlerFactory</classname>
5487 15 Nov 10 nicklas 191           </para>
5487 15 Nov 10 nicklas 192         </listitem>
5487 15 Nov 10 nicklas 193       </varlistentry>
4184 20 Mar 08 nicklas 194       
4184 20 Mar 08 nicklas 195       <varlistentry>
4208 07 Apr 08 nicklas 196         <term>Client context</term>
4184 20 Mar 08 nicklas 197         <listitem>
4184 20 Mar 08 nicklas 198           <para>
4208 07 Apr 08 nicklas 199           A <classname docapi="net.sf.basedb.util.extensions">ClientContext</classname>
4208 07 Apr 08 nicklas 200           is an object which contains information about the current user session.
4184 20 Mar 08 nicklas 201           It is for example, possible to get information about the logged in
4184 20 Mar 08 nicklas 202           user, the currently active item, etc.
4184 20 Mar 08 nicklas 203           </para>
4184 20 Mar 08 nicklas 204           
4184 20 Mar 08 nicklas 205           <para>
4184 20 Mar 08 nicklas 206           In the BASE web client the context is always a 
4184 20 Mar 08 nicklas 207           <classname docapi="net.sf.basedb.clients.web.extensions">JspContext</classname>.
4208 07 Apr 08 nicklas 208           Wherever a <classname>ClientContext</classname> object is provided as a 
4208 07 Apr 08 nicklas 209           parameter it is always safe to cast it to a <classname>JspContext</classname> 
5640 24 May 11 nicklas 210           object. Extension points in the core usually use a 
5640 24 May 11 nicklas 211           <classname>ClientContext</classname>.
4184 20 Mar 08 nicklas 212           </para>
4184 20 Mar 08 nicklas 213           
4184 20 Mar 08 nicklas 214           <para>
4184 20 Mar 08 nicklas 215           The context can also be used by an extension to request that a specific
4184 20 Mar 08 nicklas 216           javascript or stylesheet file should be included in the HTML code.
4184 20 Mar 08 nicklas 217           </para>
4184 20 Mar 08 nicklas 218         </listitem>
4184 20 Mar 08 nicklas 219       </varlistentry>
4184 20 Mar 08 nicklas 220       
4184 20 Mar 08 nicklas 221       </variablelist>
4184 20 Mar 08 nicklas 222       
4184 20 Mar 08 nicklas 223       
4184 20 Mar 08 nicklas 224     </sect2>
4184 20 Mar 08 nicklas 225   </sect1>
4184 20 Mar 08 nicklas 226   
4206 04 Apr 08 nicklas 227   <sect1 id="extensions_developer.helloworld">
5782 04 Oct 11 nicklas 228     <?dbhtml filename="helloworld.html" ?>
4184 20 Mar 08 nicklas 229     <title>Hello world as an extension</title>
4184 20 Mar 08 nicklas 230     
4184 20 Mar 08 nicklas 231     <para>
4184 20 Mar 08 nicklas 232       We will use the classical Hello world as the first simple example
4184 20 Mar 08 nicklas 233       of an extension. This extension will add a new menu item in the
4184 20 Mar 08 nicklas 234       menu which displays a popup with the text "Hello world!" when 
6812 30 Mar 15 nicklas 235       selected. 
4184 20 Mar 08 nicklas 236     </para>
4184 20 Mar 08 nicklas 237     
6812 30 Mar 15 nicklas 238     <orderedlist>
6812 30 Mar 15 nicklas 239       <listitem>
4184 20 Mar 08 nicklas 240       <para>
6812 30 Mar 15 nicklas 241       Start by creating an empty directory in some suitable
6812 30 Mar 15 nicklas 242       location on your hard disk. Inside this directory, create two more
6812 30 Mar 15 nicklas 243       directories <filename>META-INF</filename> and 
6812 30 Mar 15 nicklas 244       <filename>resources</filename>. 
4184 20 Mar 08 nicklas 245       </para>
6812 30 Mar 15 nicklas 246       </listitem>
6812 30 Mar 15 nicklas 247       
6812 30 Mar 15 nicklas 248       <listitem>
6812 30 Mar 15 nicklas 249       <para>
6812 30 Mar 15 nicklas 250       Copy the XML code below and save it to <filename>META-INF/extensions.xml</filename>
6812 30 Mar 15 nicklas 251       in your newly created directory. It is important that you get the filename
6812 30 Mar 15 nicklas 252       correct.
6812 30 Mar 15 nicklas 253       </para>
6812 30 Mar 15 nicklas 254       
6812 30 Mar 15 nicklas 255       <programlisting language="xml">
4184 20 Mar 08 nicklas 256 <![CDATA[
4184 20 Mar 08 nicklas 257 <?xml version="1.0" encoding="UTF-8" ?>
4184 20 Mar 08 nicklas 258 <extensions xmlns="http://base.thep.lu.se/extensions.xsd">
4184 20 Mar 08 nicklas 259    <extension
4184 20 Mar 08 nicklas 260       id="net.sf.basedb.clients.web.menu.extensions.helloworld"
4184 20 Mar 08 nicklas 261       extends="net.sf.basedb.clients.web.menu.extensions"
4184 20 Mar 08 nicklas 262       >
4184 20 Mar 08 nicklas 263       <index>1</index>
6812 30 Mar 15 nicklas 264       <about safe-scripts="1">
4184 20 Mar 08 nicklas 265          <name>Hello world</name>
4184 20 Mar 08 nicklas 266          <description>
4208 07 Apr 08 nicklas 267             The very first extensions example. Adds a "Hello world"
4208 07 Apr 08 nicklas 268             menu item that displays "Hello world" in a javascript
4208 07 Apr 08 nicklas 269             popup when selected.
4184 20 Mar 08 nicklas 270          </description>
4184 20 Mar 08 nicklas 271       </about>
4184 20 Mar 08 nicklas 272       <action-factory>
4208 07 Apr 08 nicklas 273          <factory-class>  
4184 20 Mar 08 nicklas 274             net.sf.basedb.clients.web.extensions.menu.FixedMenuItemFactory
4184 20 Mar 08 nicklas 275          </factory-class>
4184 20 Mar 08 nicklas 276          <parameters>
6812 30 Mar 15 nicklas 277            <id>hello-world</id>
4184 20 Mar 08 nicklas 278             <title>Hello world!</title>
4184 20 Mar 08 nicklas 279             <tooltip>This is to test the extensions system</tooltip>
5971 17 Feb 12 nicklas 280             <icon>/images/info.png</icon>
6812 30 Mar 15 nicklas 281             <script>~/hello.js</script>
4184 20 Mar 08 nicklas 282          </parameters>
4184 20 Mar 08 nicklas 283       </action-factory>
4184 20 Mar 08 nicklas 284    </extension>
4184 20 Mar 08 nicklas 285 </extensions>
4184 20 Mar 08 nicklas 286 ]]>
4184 20 Mar 08 nicklas 287 </programlisting>
6812 30 Mar 15 nicklas 288       <para>
6812 30 Mar 15 nicklas 289         This file is the most important one when creating extensions
6812 30 Mar 15 nicklas 290         since it is used to tell BASE about the extensions (and
6812 30 Mar 15 nicklas 291         plug-ins) in the package. See below for more information.
6812 30 Mar 15 nicklas 292       </para>
6812 30 Mar 15 nicklas 293       </listitem>
6812 30 Mar 15 nicklas 294       
6812 30 Mar 15 nicklas 295       <listitem>
6812 30 Mar 15 nicklas 296       <para>
6812 30 Mar 15 nicklas 297       Copy the javascript code below and save it to <filename>resources/hello.js</filename>
6812 30 Mar 15 nicklas 298       in your newly created directory. Once again, it is important that the filename
6812 30 Mar 15 nicklas 299       is correct.
6812 30 Mar 15 nicklas 300       </para>
6812 30 Mar 15 nicklas 301       <programlisting language="javascript">
6812 30 Mar 15 nicklas 302 <![CDATA[
6812 30 Mar 15 nicklas 303 var HelloWorld = function()  
6812 30 Mar 15 nicklas 304 {  
6812 30 Mar 15 nicklas 305    var hello = {};  
6812 30 Mar 15 nicklas 306     
6812 30 Mar 15 nicklas 307     /** 
6812 30 Mar 15 nicklas 308        Executed once when the page is loaded. Typically 
6812 30 Mar 15 nicklas 309        used to bind events to fixed control elements. 
6812 30 Mar 15 nicklas 310     */  
6812 30 Mar 15 nicklas 311     hello.initMenuItems = function()  
6812 30 Mar 15 nicklas 312     {  
6812 30 Mar 15 nicklas 313        // Bind event handlers the menu items.   
6812 30 Mar 15 nicklas 314        // First parameter is the ID of the menu item  
6812 30 Mar 15 nicklas 315        // Second parameter is the event to react to (=click)  
6812 30 Mar 15 nicklas 316        // Last parameter is the function to execute  
6812 30 Mar 15 nicklas 317        Events.addEventHandler('hello-world', 'click', hello.helloWorld);  
6812 30 Mar 15 nicklas 318     }  
6812 30 Mar 15 nicklas 319       
6812 30 Mar 15 nicklas 320     // Show 'Hello world' message
6812 30 Mar 15 nicklas 321     hello.helloWorld = function(event)  
6812 30 Mar 15 nicklas 322     {  
6812 30 Mar 15 nicklas 323        alert('Hello world');
6812 30 Mar 15 nicklas 324     }  
6812 30 Mar 15 nicklas 325      
6812 30 Mar 15 nicklas 326     return hello;  
6812 30 Mar 15 nicklas 327 }();  
6812 30 Mar 15 nicklas 328       
6812 30 Mar 15 nicklas 329 //Register the page initializer method with the BASE core  
6812 30 Mar 15 nicklas 330 Doc.onLoad(HelloWorld.initMenuItems);  
6812 30 Mar 15 nicklas 331 ]]>
6812 30 Mar 15 nicklas 332 </programlisting>
6812 30 Mar 15 nicklas 333       </listitem>
4184 20 Mar 08 nicklas 334     
6812 30 Mar 15 nicklas 335       <listitem>
6812 30 Mar 15 nicklas 336       <para>
6812 30 Mar 15 nicklas 337       Create a JAR package containing the two directories and files
6812 30 Mar 15 nicklas 338       you have created. It is important the the subdirectory structure
6812 30 Mar 15 nicklas 339       inside the JAR file is rooted at the first empty directory you created.
6812 30 Mar 15 nicklas 340       </para>
6812 30 Mar 15 nicklas 341       
6812 30 Mar 15 nicklas 342         <literallayout>
6812 30 Mar 15 nicklas 343 <filename class="directory">META-INF/</filename>
6812 30 Mar 15 nicklas 344 <filename>META-INF/extensions.xml</filename>
6812 30 Mar 15 nicklas 345 <filename class="directory">resources/</filename>
6812 30 Mar 15 nicklas 346 <filename>resources/hello.js</filename>
6812 30 Mar 15 nicklas 347         </literallayout>
6812 30 Mar 15 nicklas 348       
6812 30 Mar 15 nicklas 349       <para>
6812 30 Mar 15 nicklas 350         Copy the JAR file to the the <filename>plugins.dir</filename>
6812 30 Mar 15 nicklas 351         directory for your BASE installation.
6812 30 Mar 15 nicklas 352       </para>
6812 30 Mar 15 nicklas 353       </listitem>
6812 30 Mar 15 nicklas 354     
6812 30 Mar 15 nicklas 355       <listitem>
6812 30 Mar 15 nicklas 356       <para>
6812 30 Mar 15 nicklas 357         Log in to BASE and install the extension by going through the 
6812 30 Mar 15 nicklas 358         installation wizard at <menuchoice>
6812 30 Mar 15 nicklas 359             <guimenu>Administrate</guimenu>
6812 30 Mar 15 nicklas 360             <guimenuitem>Plug-ins &amp; extensions</guimenuitem>
6812 30 Mar 15 nicklas 361             <guimenuitem>Overview</guimenuitem>
6812 30 Mar 15 nicklas 362           </menuchoice>.
6812 30 Mar 15 nicklas 363         When the extension has been installed you should have a new 
6812 30 Mar 15 nicklas 364         menu item:
6812 30 Mar 15 nicklas 365         <menuchoice>
6812 30 Mar 15 nicklas 366           <guimenu>Extensions</guimenu>
6812 30 Mar 15 nicklas 367           <guimenuitem>Hello world!</guimenuitem>
6812 30 Mar 15 nicklas 368         </menuchoice>
6812 30 Mar 15 nicklas 369         which pops up a message in a Javascript window.
6812 30 Mar 15 nicklas 370         
6812 30 Mar 15 nicklas 371       </para>
6812 30 Mar 15 nicklas 372       <note>
6812 30 Mar 15 nicklas 373         <para>
6812 30 Mar 15 nicklas 374         You may have to logout and login again to see the new menu item.
6812 30 Mar 15 nicklas 375         </para>
6812 30 Mar 15 nicklas 376       </note>
6812 30 Mar 15 nicklas 377       </listitem>
6812 30 Mar 15 nicklas 378     
6812 30 Mar 15 nicklas 379     </orderedlist>
6812 30 Mar 15 nicklas 380     
6812 30 Mar 15 nicklas 381     <sect2 id="extensions_developer.extensions.xml">
6812 30 Mar 15 nicklas 382       <title>The extensions.xml file</title>
6812 30 Mar 15 nicklas 383     
4184 20 Mar 08 nicklas 384     <para>
4184 20 Mar 08 nicklas 385       The <sgmltag class="starttag">extensions</sgmltag> tag is the root
4184 20 Mar 08 nicklas 386       tag and is needed to set up the namespace and schema validation.
4184 20 Mar 08 nicklas 387     </para>
4184 20 Mar 08 nicklas 388     
4184 20 Mar 08 nicklas 389     <para>
4184 20 Mar 08 nicklas 390       The <sgmltag class="starttag">extension</sgmltag> defines a new
4184 20 Mar 08 nicklas 391       extension. It must have an <sgmltag>id</sgmltag> attribute that
4184 20 Mar 08 nicklas 392       is unique among all installed extensions and an <sgmltag>extends</sgmltag> 
4184 20 Mar 08 nicklas 393       attribute which id the ID of the extension point. For the <sgmltag>id</sgmltag>
4184 20 Mar 08 nicklas 394       attribute we recommend using the same naming conventions as for java
4184 20 Mar 08 nicklas 395       packages. See <ulink 
5640 24 May 11 nicklas 396       url="http://www.oracle.com/technetwork/java/codeconventions-135099.html">Java naming
5640 24 May 11 nicklas 397       conventions from Oracle</ulink>.
4184 20 Mar 08 nicklas 398     </para>
4184 20 Mar 08 nicklas 399     
4184 20 Mar 08 nicklas 400     <para>
4184 20 Mar 08 nicklas 401       The <sgmltag class="starttag">about</sgmltag> tag is optional and
4184 20 Mar 08 nicklas 402       can be used to provide meta information about the extension. We
4184 20 Mar 08 nicklas 403       recommend that all extensions are given at least a
4184 20 Mar 08 nicklas 404       <sgmltag class="starttag">name</sgmltag>. Other supported subtags are:
4184 20 Mar 08 nicklas 405       
4184 20 Mar 08 nicklas 406       <itemizedlist>
4184 20 Mar 08 nicklas 407         <listitem><sgmltag class="starttag">description</sgmltag></listitem>
4184 20 Mar 08 nicklas 408         <listitem><sgmltag class="starttag">version</sgmltag></listitem>
4184 20 Mar 08 nicklas 409         <listitem><sgmltag class="starttag">copyright</sgmltag></listitem>
4184 20 Mar 08 nicklas 410         <listitem><sgmltag class="starttag">contact</sgmltag></listitem>
4184 20 Mar 08 nicklas 411         <listitem><sgmltag class="starttag">email</sgmltag></listitem>
4184 20 Mar 08 nicklas 412         <listitem><sgmltag class="starttag">url</sgmltag></listitem>
4184 20 Mar 08 nicklas 413       </itemizedlist>
4184 20 Mar 08 nicklas 414       
4184 20 Mar 08 nicklas 415       <tip>
4184 20 Mar 08 nicklas 416         <title>Global about tag</title>
4184 20 Mar 08 nicklas 417         
4184 20 Mar 08 nicklas 418         <para>
4184 20 Mar 08 nicklas 419           <sgmltag class="starttag">about</sgmltag> tag can also be specified as a
4184 20 Mar 08 nicklas 420           first-level tag (eq. as a child to <sgmltag class="starttag">extensions</sgmltag>).
4208 07 Apr 08 nicklas 421           This can be useful when an XML file defines more than one extension
4184 20 Mar 08 nicklas 422           and you don't want to repeat the same information for every extension.
4184 20 Mar 08 nicklas 423           You can still override the information for specific extensions by including
4184 20 Mar 08 nicklas 424           new values in the extension's <sgmltag class="starttag">about</sgmltag>
4184 20 Mar 08 nicklas 425           tag.
4184 20 Mar 08 nicklas 426         </para>
4184 20 Mar 08 nicklas 427       </tip>
6595 14 Nov 14 nicklas 428       
6595 14 Nov 14 nicklas 429       <tip>
6595 14 Nov 14 nicklas 430         <title>Start out in disabled state</title>
6595 14 Nov 14 nicklas 431         
6595 14 Nov 14 nicklas 432         <para>
6595 14 Nov 14 nicklas 433           The <sgmltag class="starttag">about</sgmltag> tag can be used to specify
6595 14 Nov 14 nicklas 434           that an extension should start out in disabled state. This can be useful
6595 14 Nov 14 nicklas 435           if there are multiple variants of an extension or if some extensions
6595 14 Nov 14 nicklas 436           are considered "advanced mode" and only should be enabled after some
6595 14 Nov 14 nicklas 437           serious thinking. To use this feature, simply set <code>&lt;about disabled="1"&gt;</code>
6595 14 Nov 14 nicklas 438           in the XML file.
6595 14 Nov 14 nicklas 439         </para>
6595 14 Nov 14 nicklas 440       </tip>
4184 20 Mar 08 nicklas 441     </para>
4184 20 Mar 08 nicklas 442     
4184 20 Mar 08 nicklas 443     <para>
4184 20 Mar 08 nicklas 444       The <sgmltag class="starttag">action-factory</sgmltag> tag is required and
4184 20 Mar 08 nicklas 445       so is the <sgmltag class="starttag">factory-class</sgmltag> subtag. It tells
4208 07 Apr 08 nicklas 446       the extension system which factory to use for creating actions. The
4184 20 Mar 08 nicklas 447       <classname docapi="net.sf.basedb.clients.web.extensions.menu">FixedMenuItemFactory</classname>
4184 20 Mar 08 nicklas 448       is a very simple factory that is shipped with BASE. This factory always creates the same
4184 20 Mar 08 nicklas 449       menu item, no matter what. Another factory for menu items is the 
4184 20 Mar 08 nicklas 450       <classname docapi="net.sf.basedb.clients.web.extensions.menu">PermissionMenuItemFactory</classname>
4184 20 Mar 08 nicklas 451       which can create menu items that depends on the logged in user's permissions. It is
4184 20 Mar 08 nicklas 452       for example, possible to hide or disable the menu item if the user doesn't have enough
4184 20 Mar 08 nicklas 453       permissions. If none of the supplied factories suits you it is possible to 
4184 20 Mar 08 nicklas 454       supply your own implementation. More about this later.
4184 20 Mar 08 nicklas 455     </para>
4184 20 Mar 08 nicklas 456     
4184 20 Mar 08 nicklas 457     <para>
4184 20 Mar 08 nicklas 458       The <sgmltag class="starttag">parameters</sgmltag> subtag is used to
4184 20 Mar 08 nicklas 459       provide initialisation parameters to the factory. Different factories 
4184 20 Mar 08 nicklas 460       supports different parameters and you will have to check the javadoc documentation
4184 20 Mar 08 nicklas 461       for each factory to get information about which parameters that are supported.
4184 20 Mar 08 nicklas 462     </para>
4184 20 Mar 08 nicklas 463     
4184 20 Mar 08 nicklas 464     <tip>
4184 20 Mar 08 nicklas 465       <para>
4184 20 Mar 08 nicklas 466         In case the factory is poorly documented you can always assume that public
4184 20 Mar 08 nicklas 467         methods the start with <code>set</code> and take a single <classname>String</classname>
4184 20 Mar 08 nicklas 468         as an argument can be used as a parameter. The parameter tag to use should
4184 20 Mar 08 nicklas 469         be the same as the method name, minus the <code>set</code> prefix and with
4184 20 Mar 08 nicklas 470         the first letter in lowercase. For example, the method 
4184 20 Mar 08 nicklas 471         <methodname>setIcon(String icon)</methodname> corresponds to the 
4184 20 Mar 08 nicklas 472         <sgmltag class="starttag">icon</sgmltag> parameter.
4184 20 Mar 08 nicklas 473       </para>
4184 20 Mar 08 nicklas 474     </tip>
5519 23 Nov 10 nicklas 475     
6403 29 Jan 14 nicklas 476     <note>
6410 31 Jan 14 nicklas 477       <title>Content security policy and inline javascript</title>
6403 29 Jan 14 nicklas 478       <para>
6812 30 Mar 15 nicklas 479         The Hello World example requires quite a lot of code and it
6812 30 Mar 15 nicklas 480         would have been tempting to skip the <filename>hello.js</filename>
6812 30 Mar 15 nicklas 481         file and simply add 
6812 30 Mar 15 nicklas 482         
6812 30 Mar 15 nicklas 483         <code><sgmltag class="starttag">onclick</sgmltag>alert('Hello world')<sgmltag class="endtag">onclick</sgmltag></code>
6812 30 Mar 15 nicklas 484         
6812 30 Mar 15 nicklas 485         to the <sgmltag class="starttag">parameters</sgmltag> section in the
6812 30 Mar 15 nicklas 486         <filename>extensions.xml</filename> file. However, BASE is by default
6812 30 Mar 15 nicklas 487         configured to block all inline JavaScript since it opens up for
6812 30 Mar 15 nicklas 488         cross-site scripting attacks. It is possible to relax this policy
6812 30 Mar 15 nicklas 489         but it is nothing we recommend. See
6410 31 Jan 14 nicklas 490         <xref linkend="appendix.web.xml.csp-filter" /> for more information.
6403 29 Jan 14 nicklas 491       </para>
6410 31 Jan 14 nicklas 492       
6410 31 Jan 14 nicklas 493       <para>
6410 31 Jan 14 nicklas 494         The real code examples uses a different design with pure HTML that is 
6410 31 Jan 14 nicklas 495         generated dynamically and a fixed javascript file that attaches event
6410 31 Jan 14 nicklas 496         handlers when the page has been loaded and should be compatible with the
6410 31 Jan 14 nicklas 497         stricter security policy.
6410 31 Jan 14 nicklas 498       </para>
6403 29 Jan 14 nicklas 499     </note>
6403 29 Jan 14 nicklas 500     
6812 30 Mar 15 nicklas 501     </sect2>
6812 30 Mar 15 nicklas 502     
5519 23 Nov 10 nicklas 503     <sect2 id="extensions_developer.extend_multiple">
5519 23 Nov 10 nicklas 504       <title>Extending multiple extension points with a single extension</title>
5519 23 Nov 10 nicklas 505       
5519 23 Nov 10 nicklas 506       <para>
5519 23 Nov 10 nicklas 507         A single extension can extend multiple extension points as long as their
5519 23 Nov 10 nicklas 508         action classes are compatible. This is for, for example, the case when 
5519 23 Nov 10 nicklas 509         you want to add a button to more than one toolbar.         
5519 23 Nov 10 nicklas 510         To do this use the <sgmltag class="starttag">extends</sgmltag>
5519 23 Nov 10 nicklas 511         tag with multiple <sgmltag class="starttag">ref</sgmltag> tags. 
5519 23 Nov 10 nicklas 512         You can skip the <sgmltag class="attribute">extends</sgmltag> 
5519 23 Nov 10 nicklas 513         attribute in the main tag.
5519 23 Nov 10 nicklas 514       </para>
5519 23 Nov 10 nicklas 515     <programlisting language="xml">
5519 23 Nov 10 nicklas 516 <![CDATA[
5519 23 Nov 10 nicklas 517 <extension
5519 23 Nov 10 nicklas 518    id="net.sf.basedb.clients.web.menu.extensions.history-edit"
5519 23 Nov 10 nicklas 519    >
5519 23 Nov 10 nicklas 520    <extends>
5519 23 Nov 10 nicklas 521       <ref index="2">net.sf.basedb.clients.web.tabcontrol.edit.sample</ref>
5519 23 Nov 10 nicklas 522       <ref index="2">net.sf.basedb.clients.web.tabcontrol.edit.extract</ref>
5519 23 Nov 10 nicklas 523    </extends>
5519 23 Nov 10 nicklas 524    ...
5519 23 Nov 10 nicklas 525 </extension>
5519 23 Nov 10 nicklas 526 ]]>
5519 23 Nov 10 nicklas 527 </programlisting>
5519 23 Nov 10 nicklas 528       
5519 23 Nov 10 nicklas 529       <para>
5519 23 Nov 10 nicklas 530         This is a feature of the XML format only. Behind the scenes two extensions will
5519 23 Nov 10 nicklas 531         be created (one for each extension point). The extensions will share the same
5519 23 Nov 10 nicklas 532         action and renderer factory instances. Since the id for an extension must be unique
5519 23 Nov 10 nicklas 533         a new id will be generated by combining the original id with the parts of the id's from 
5519 23 Nov 10 nicklas 534         the extension points. 
5519 23 Nov 10 nicklas 535       </para>
5519 23 Nov 10 nicklas 536       
5519 23 Nov 10 nicklas 537     </sect2>
4184 20 Mar 08 nicklas 538   </sect1>
4184 20 Mar 08 nicklas 539
4184 20 Mar 08 nicklas 540
4206 04 Apr 08 nicklas 541   <sect1 id="extensions_developer.factories">
5782 04 Oct 11 nicklas 542     <?dbhtml filename="factories.html" ?>
4184 20 Mar 08 nicklas 543     <title>Custom action factories</title>
4184 20 Mar 08 nicklas 544
4184 20 Mar 08 nicklas 545     <para>
4184 20 Mar 08 nicklas 546       Some times the factories shipped with BASE are not enough, and you
4184 20 Mar 08 nicklas 547       may want to provide your own factory implementation. In this case you will
4184 20 Mar 08 nicklas 548       have to create a class that implements the 
4184 20 Mar 08 nicklas 549       <interfacename docapi="net.sf.basedb.util.extensions">ActionFactory</interfacename>
4208 07 Apr 08 nicklas 550       interface. Here is a very simple example that does the same as the 
4208 07 Apr 08 nicklas 551       previous "Hello world" example.
4184 20 Mar 08 nicklas 552     </para>
4184 20 Mar 08 nicklas 553     
4184 20 Mar 08 nicklas 554     <programlisting language="java">
4184 20 Mar 08 nicklas 555 <![CDATA[
4184 20 Mar 08 nicklas 556 package net.sf.basedb.examples.extensions;
4184 20 Mar 08 nicklas 557
4184 20 Mar 08 nicklas 558 import net.sf.basedb.clients.web.extensions.JspContext;
4184 20 Mar 08 nicklas 559 import net.sf.basedb.clients.web.extensions.menu.MenuItemAction;
4184 20 Mar 08 nicklas 560 import net.sf.basedb.clients.web.extensions.menu.MenuItemBean;
4184 20 Mar 08 nicklas 561 import net.sf.basedb.util.extensions.ActionFactory;
4208 07 Apr 08 nicklas 562 import net.sf.basedb.util.extensions.InvokationContext;
4184 20 Mar 08 nicklas 563
4184 20 Mar 08 nicklas 564 /**
4184 20 Mar 08 nicklas 565    First example of an action factory where eveything is hardcoded.
4184 20 Mar 08 nicklas 566    @author nicklas
4184 20 Mar 08 nicklas 567 */
4184 20 Mar 08 nicklas 568 public class HelloWorldFactory
4184 20 Mar 08 nicklas 569    implements ActionFactory<MenuItemAction>
4184 20 Mar 08 nicklas 570 {
4184 20 Mar 08 nicklas 571
4184 20 Mar 08 nicklas 572    private MenuItemAction[] helloWorld;
4184 20 Mar 08 nicklas 573
4184 20 Mar 08 nicklas 574    // A public, no-argument constructor is required
4184 20 Mar 08 nicklas 575    public HelloWorldFactory()
4184 20 Mar 08 nicklas 576    {
4184 20 Mar 08 nicklas 577       helloWorld = new MenuItemAction[1];
4184 20 Mar 08 nicklas 578    }
4184 20 Mar 08 nicklas 579    
4184 20 Mar 08 nicklas 580    // Return true enable the extension, false to disable it
4208 07 Apr 08 nicklas 581    public boolean prepareContext(
4208 07 Apr 08 nicklas 582       InvokationContext<? super MenuItemAction> context) 
4184 20 Mar 08 nicklas 583    {
6812 30 Mar 15 nicklas 584       JspContext jspContext = (JspContext)context.getClientContext();
6812 30 Mar 15 nicklas 585       String home = jspContext.getHome(context.getExtension());
6812 30 Mar 15 nicklas 586       jspContext.addScript(home + "/hello.js");
4184 20 Mar 08 nicklas 587       return true;
4184 20 Mar 08 nicklas 588    }
4184 20 Mar 08 nicklas 589
4184 20 Mar 08 nicklas 590    // An extension may create one or more actions
4208 07 Apr 08 nicklas 591    public MenuItemAction[] getActions(
4208 07 Apr 08 nicklas 592       InvokationContext<? super MenuItemAction> context) 
4184 20 Mar 08 nicklas 593    {
4184 20 Mar 08 nicklas 594       // This cast is always safe with the web client
4208 07 Apr 08 nicklas 595       JspContext jspContext = (JspContext)context.getClientContext();
4184 20 Mar 08 nicklas 596       if (helloWorld[0] == null)
4184 20 Mar 08 nicklas 597       {
4184 20 Mar 08 nicklas 598          MenuItemBean bean = new MenuItemBean();
6812 30 Mar 15 nicklas 599          bean.setId("hello-factory");
4184 20 Mar 08 nicklas 600          bean.setTitle("Hello factory world!");
4184 20 Mar 08 nicklas 601          bean.setIcon(jspContext.getRoot() + "/images/info.gif");
4184 20 Mar 08 nicklas 602          helloWorld[0] = bean;
4184 20 Mar 08 nicklas 603       }
4184 20 Mar 08 nicklas 604       return helloWorld;
4184 20 Mar 08 nicklas 605    }
4184 20 Mar 08 nicklas 606 }
4184 20 Mar 08 nicklas 607 ]]>
4184 20 Mar 08 nicklas 608 </programlisting>
4184 20 Mar 08 nicklas 609
4184 20 Mar 08 nicklas 610     <para>
6812 30 Mar 15 nicklas 611       And here are the XML and JavaScript files that goes with it.
4184 20 Mar 08 nicklas 612     </para>
4184 20 Mar 08 nicklas 613
4184 20 Mar 08 nicklas 614     <programlisting language="xml">
4184 20 Mar 08 nicklas 615 <![CDATA[
4184 20 Mar 08 nicklas 616 <?xml version="1.0" encoding="UTF-8" ?>
4184 20 Mar 08 nicklas 617 <extensions xmlns="http://base.thep.lu.se/extensions.xsd">
4184 20 Mar 08 nicklas 618    <extension
4184 20 Mar 08 nicklas 619       id="net.sf.basedb.clients.web.menu.extensions.helloworldfactory"
4184 20 Mar 08 nicklas 620       extends="net.sf.basedb.clients.web.menu.extensions"
4184 20 Mar 08 nicklas 621       >
4184 20 Mar 08 nicklas 622       <index>2</index>
4184 20 Mar 08 nicklas 623       <about>
4184 20 Mar 08 nicklas 624          <name>Hello factory world</name>
4184 20 Mar 08 nicklas 625          <description>
4184 20 Mar 08 nicklas 626             A "Hello world" variant with a custom action factory.
4184 20 Mar 08 nicklas 627             Everything is hard-coded into the factory.
4184 20 Mar 08 nicklas 628          </description>
4184 20 Mar 08 nicklas 629       </about>
4184 20 Mar 08 nicklas 630       <action-factory>
4184 20 Mar 08 nicklas 631          <factory-class>
4184 20 Mar 08 nicklas 632             net.sf.basedb.examples.extensions.HelloWorldFactory
4184 20 Mar 08 nicklas 633          </factory-class>
4184 20 Mar 08 nicklas 634       </action-factory>
4184 20 Mar 08 nicklas 635    </extension>
4184 20 Mar 08 nicklas 636 </extensions>
4184 20 Mar 08 nicklas 637 ]]>
4184 20 Mar 08 nicklas 638 </programlisting>
6812 30 Mar 15 nicklas 639     <programlisting language="javascript">
6812 30 Mar 15 nicklas 640 <![CDATA[
6812 30 Mar 15 nicklas 641 var HelloWorldFactory = function()  
6812 30 Mar 15 nicklas 642 {  
6812 30 Mar 15 nicklas 643    var hello = {};  
6812 30 Mar 15 nicklas 644     
6812 30 Mar 15 nicklas 645     /** 
6812 30 Mar 15 nicklas 646        Executed once when the page is loaded. Typically 
6812 30 Mar 15 nicklas 647        used to bind events to fixed control elements. 
6812 30 Mar 15 nicklas 648     */  
6812 30 Mar 15 nicklas 649     hello.initMenuItems = function()  
6812 30 Mar 15 nicklas 650     {  
6812 30 Mar 15 nicklas 651        // Bind event handlers the menu items.   
6812 30 Mar 15 nicklas 652        // First parameter is the ID of the menu item  
6812 30 Mar 15 nicklas 653        // Second parameter is the event to react to (=click)  
6812 30 Mar 15 nicklas 654        // Last parameter is the function to execute  
6812 30 Mar 15 nicklas 655        Events.addEventHandler('hello-factory', 'click', hello.helloFactoryWorld);  
6812 30 Mar 15 nicklas 656     }  
6812 30 Mar 15 nicklas 657       
6812 30 Mar 15 nicklas 658     // Show 'Hello factory world' message
6812 30 Mar 15 nicklas 659     hello.helloFactoryWorld = function(event)  
6812 30 Mar 15 nicklas 660     {  
6812 30 Mar 15 nicklas 661        alert('Hello factory world');
6812 30 Mar 15 nicklas 662     }  
6812 30 Mar 15 nicklas 663      
6812 30 Mar 15 nicklas 664     return hello;  
6812 30 Mar 15 nicklas 665 }();  
6812 30 Mar 15 nicklas 666       
6812 30 Mar 15 nicklas 667 //Register the page initializer method with the BASE core  
6812 30 Mar 15 nicklas 668 Doc.onLoad(HelloWorldFactory.initMenuItems);  
6812 30 Mar 15 nicklas 669 ]]>
6812 30 Mar 15 nicklas 670 </programlisting>
4184 20 Mar 08 nicklas 671     
4184 20 Mar 08 nicklas 672     <para>
4184 20 Mar 08 nicklas 673       To install this extension you need to put the compiled 
6812 30 Mar 15 nicklas 674       <filename>HelloWorldFactory.class</filename>, the XML 
6812 30 Mar 15 nicklas 675       and JavaScript files inside a JAR file. The XML file must be located at
6812 30 Mar 15 nicklas 676       <filename>META-INF/extensions.xml</filename> the JavScript file
6812 30 Mar 15 nicklas 677       at <filename>resources/hello.js</filename>, and the class
4184 20 Mar 08 nicklas 678       file at <filename>net/sf/basedb/examples/extensions/HelloWorldFactory.class</filename>.
4184 20 Mar 08 nicklas 679     </para>
4184 20 Mar 08 nicklas 680     
4184 20 Mar 08 nicklas 681     <para>
4184 20 Mar 08 nicklas 682       The above example is a bit artificial and we have not gained anything.
4184 20 Mar 08 nicklas 683       Instead, we have lost the ability to easily change the menu since everything is 
4208 07 Apr 08 nicklas 684       now hardcoded into the factory. To change, for example the title, requires that 
4208 07 Apr 08 nicklas 685       we recompile the java code. It would be more useful if we could make the factory
4184 20 Mar 08 nicklas 686       configurable with parameters. The next example will make the icon
4208 07 Apr 08 nicklas 687       and message configurable, and also include the name
4184 20 Mar 08 nicklas 688       of the currently logged in user. For example: "Greetings &lt;name of 
6403 29 Jan 14 nicklas 689       logged in user&gt;!". We'll also get rid of the onclick event handler
6403 29 Jan 14 nicklas 690       and use proper event binding using javascript.
4184 20 Mar 08 nicklas 691     </para>
4184 20 Mar 08 nicklas 692     
4184 20 Mar 08 nicklas 693     <programlisting language="java">
4184 20 Mar 08 nicklas 694 <![CDATA[
4184 20 Mar 08 nicklas 695 package net.sf.basedb.examples.extensions;
4184 20 Mar 08 nicklas 696
4184 20 Mar 08 nicklas 697 import net.sf.basedb.clients.web.extensions.AbstractJspActionFactory;
4184 20 Mar 08 nicklas 698 import net.sf.basedb.clients.web.extensions.menu.MenuItemAction;
4184 20 Mar 08 nicklas 699 import net.sf.basedb.clients.web.extensions.menu.MenuItemBean;
4184 20 Mar 08 nicklas 700 import net.sf.basedb.core.DbControl;
4184 20 Mar 08 nicklas 701 import net.sf.basedb.core.SessionControl;
4184 20 Mar 08 nicklas 702 import net.sf.basedb.core.User;
4208 07 Apr 08 nicklas 703 import net.sf.basedb.util.extensions.ClientContext;
4208 07 Apr 08 nicklas 704 import net.sf.basedb.util.extensions.InvokationContext;
4184 20 Mar 08 nicklas 705 import net.sf.basedb.util.extensions.xml.PathSetter;
4184 20 Mar 08 nicklas 706 import net.sf.basedb.util.extensions.xml.VariableSetter;
4184 20 Mar 08 nicklas 707
4184 20 Mar 08 nicklas 708 /**
4184 20 Mar 08 nicklas 709    Example menu item factory that creates a "Hello world" menu item
4184 20 Mar 08 nicklas 710    where the "Hello" part can be changed by the "prefix" setting in the
4184 20 Mar 08 nicklas 711    XML file, and the "world" part is dynamically replaced with the name
4184 20 Mar 08 nicklas 712    of the logged in user.
4184 20 Mar 08 nicklas 713    
4184 20 Mar 08 nicklas 714    @author nicklas
4184 20 Mar 08 nicklas 715 */
4184 20 Mar 08 nicklas 716 public class HelloUserFactory 
4184 20 Mar 08 nicklas 717    extends AbstractJspActionFactory<MenuItemAction>
4184 20 Mar 08 nicklas 718 {
6403 29 Jan 14 nicklas 719    // The ID attribute of the <div> tag in the final HTML
6403 29 Jan 14 nicklas 720    private String id;
6403 29 Jan 14 nicklas 721  
4184 20 Mar 08 nicklas 722    // To store the URL to the icon
4184 20 Mar 08 nicklas 723    private String icon;
4184 20 Mar 08 nicklas 724    
4184 20 Mar 08 nicklas 725    // The default prefix is Hello
4184 20 Mar 08 nicklas 726    private String prefix = "Hello";
4184 20 Mar 08 nicklas 727    
4184 20 Mar 08 nicklas 728    // A public, no-argument constructor is required
4184 20 Mar 08 nicklas 729    public HelloUserFactory()
4184 20 Mar 08 nicklas 730    {}
4184 20 Mar 08 nicklas 731    
4184 20 Mar 08 nicklas 732    /**
4184 20 Mar 08 nicklas 733       Creates a menu item that displays: {prefix} {name of user}!
4184 20 Mar 08 nicklas 734    */
4208 07 Apr 08 nicklas 735    public MenuItemAction[] getActions( 
4208 07 Apr 08 nicklas 736       InvokationContext<? super MenuItemAction> context) 
4184 20 Mar 08 nicklas 737    {
4208 07 Apr 08 nicklas 738       String userName = getUserName(context.getClientContext());
4184 20 Mar 08 nicklas 739       MenuItemBean helloUser = new MenuItemBean();
6403 29 Jan 14 nicklas 740       helloUser.setId(id);
4184 20 Mar 08 nicklas 741       helloUser.setTitle(prefix + " " + userName + "!");
4184 20 Mar 08 nicklas 742       helloUser.setIcon(icon);
6403 29 Jan 14 nicklas 743       // Use 'dynamic' attributes for extra info that needs to be included
6403 29 Jan 14 nicklas 744       // in the HTML
6403 29 Jan 14 nicklas 745       setParameter("data-user-name", userName);
6403 29 Jan 14 nicklas 746       setParameter("data-prefix", prefix);
6403 29 Jan 14 nicklas 747       helloUser.setDynamicActionAttributesSource(this);
4184 20 Mar 08 nicklas 748       return new MenuItemAction[] { helloUser };
4184 20 Mar 08 nicklas 749    }
4184 20 Mar 08 nicklas 750
4184 20 Mar 08 nicklas 751    /**
4184 20 Mar 08 nicklas 752       Get the name of the logged in user.
4184 20 Mar 08 nicklas 753    */
4208 07 Apr 08 nicklas 754    private String getUserName(ClientContext context)
4184 20 Mar 08 nicklas 755    {
4237 18 Apr 08 nicklas 756       SessionControl sc = context.getSessionControl();
4237 18 Apr 08 nicklas 757       DbControl dc = context.getDbControl();
4237 18 Apr 08 nicklas 758       User current = User.getById(dc, sc.getLoggedInUserId());
4237 18 Apr 08 nicklas 759       return current.getName();
4184 20 Mar 08 nicklas 760    }
4184 20 Mar 08 nicklas 761    
6403 29 Jan 14 nicklas 762      /**
6403 29 Jan 14 nicklas 763       Set the ID to use for the <div> tag. This is needed
6403 29 Jan 14 nicklas 764       so that we can attach a 'click' handler to the menu item
6403 29 Jan 14 nicklas 765       with JavaScript.
6403 29 Jan 14 nicklas 766    */
6403 29 Jan 14 nicklas 767    public void setId(String id)
6403 29 Jan 14 nicklas 768    {
6403 29 Jan 14 nicklas 769       this.id = id;
6403 29 Jan 14 nicklas 770    }
6403 29 Jan 14 nicklas 771    
4184 20 Mar 08 nicklas 772    /**
4184 20 Mar 08 nicklas 773       Sets the icon to use. Path conversion is enabled.
4184 20 Mar 08 nicklas 774    */
4184 20 Mar 08 nicklas 775    @VariableSetter
4184 20 Mar 08 nicklas 776    @PathSetter
4184 20 Mar 08 nicklas 777    public void setIcon(String icon)
4184 20 Mar 08 nicklas 778    {
4184 20 Mar 08 nicklas 779       this.icon = icon;
4184 20 Mar 08 nicklas 780    }
4184 20 Mar 08 nicklas 781    
4184 20 Mar 08 nicklas 782    /**
4184 20 Mar 08 nicklas 783       Sets the prefix to use. If not set, the
4184 20 Mar 08 nicklas 784       default value is "Hello".
4184 20 Mar 08 nicklas 785    */
4184 20 Mar 08 nicklas 786    public void setPrefix(String prefix)
4184 20 Mar 08 nicklas 787    {
4184 20 Mar 08 nicklas 788       this.prefix = prefix == null ? "Hello" : prefix;
4184 20 Mar 08 nicklas 789    }
4184 20 Mar 08 nicklas 790 }
4184 20 Mar 08 nicklas 791 ]]>
4184 20 Mar 08 nicklas 792 </programlisting>
4184 20 Mar 08 nicklas 793     
4184 20 Mar 08 nicklas 794     <para>
6403 29 Jan 14 nicklas 795       The are several new parts in this factory. The first is the <methodname>getUserName()</methodname>
4184 20 Mar 08 nicklas 796       method which is called from <methodname>getActions()</methodname>. Note
4184 20 Mar 08 nicklas 797       that the <methodname>getActions()</methodname> method always create
4184 20 Mar 08 nicklas 798       a new <classname docapi="net.sf.basedb.clients.web.extensions.menu">MenuItemBean</classname>.
4184 20 Mar 08 nicklas 799       It can no longer be cached since the title and javascript code depends on
4184 20 Mar 08 nicklas 800       which user is logged in. 
4184 20 Mar 08 nicklas 801     </para>
4184 20 Mar 08 nicklas 802     
4184 20 Mar 08 nicklas 803     <para>
6403 29 Jan 14 nicklas 804       The second new part is the <methodname>setId()</methodname>, 
6403 29 Jan 14 nicklas 805       <methodname>setIcon()</methodname> and
4184 20 Mar 08 nicklas 806       <methodname>setPrefix()</methodname> methods.
4184 20 Mar 08 nicklas 807       The extensions system uses java reflection to find the existance of
6403 29 Jan 14 nicklas 808       the methods if <sgmltag class="starttag">id</sgmltag>,
6403 29 Jan 14 nicklas 809       <sgmltag class="starttag">icon</sgmltag> and/or 
4184 20 Mar 08 nicklas 810       <sgmltag class="starttag">prefix</sgmltag> tags are present
4184 20 Mar 08 nicklas 811       in the <sgmltag class="starttag">parameters</sgmltag> tag for a factory,
4184 20 Mar 08 nicklas 812       the methods are automatically called with the value inside the tag 
4184 20 Mar 08 nicklas 813       as it's argument.
4184 20 Mar 08 nicklas 814     </para>
4184 20 Mar 08 nicklas 815     
4184 20 Mar 08 nicklas 816     <para>
4184 20 Mar 08 nicklas 817       The <classname docapi="net.sf.basedb.util.extensions.xml">VariableSetter</classname> 
4184 20 Mar 08 nicklas 818       and <classname docapi="net.sf.basedb.util.extensions.xml">PathSetter</classname> 
4184 20 Mar 08 nicklas 819       annotations on the <methodname>setIcon()</methodname> are used to enable 
4184 20 Mar 08 nicklas 820       "smart" convertions of the value. Note that in the 
5971 17 Feb 12 nicklas 821       XML file you only have to specify <filename>/images/info.png</filename>
4184 20 Mar 08 nicklas 822       as the URL to the icon, but in the hardcoded factory you have to 
5971 17 Feb 12 nicklas 823       do: <code>jspContext.getRoot() + "/images/info.png"</code>. In this case, 
4184 20 Mar 08 nicklas 824       it is the <classname>PathSetter</classname> which automatically adds the 
4184 20 Mar 08 nicklas 825       the JSP root directory to all URL:s starting with /. The 
4184 20 Mar 08 nicklas 826       <classname>VariableSetter</classname> can do the same thing but you would have to use
5971 17 Feb 12 nicklas 827       <code>$ROOT$</code> instead. Eg. <code>$ROOT$/images/info.png</code>. The
4208 07 Apr 08 nicklas 828       <classname>PathSetter</classname> only looks at the first characteer,
4208 07 Apr 08 nicklas 829       while the <classname>VariableSetter</classname> looks in the entire string.
4184 20 Mar 08 nicklas 830     </para>
4184 20 Mar 08 nicklas 831     
4184 20 Mar 08 nicklas 832     <para>
6812 30 Mar 15 nicklas 833       The third new part is the use of dynamic action attributes. These
6812 30 Mar 15 nicklas 834       are extra attributes that have not been defined by the <classname>Action</classname>
6812 30 Mar 15 nicklas 835       interface. To set a dynamic attribute we call the
6812 30 Mar 15 nicklas 836       <methodname>setParameter()</methodname> method and then 
6403 29 Jan 14 nicklas 837       <methodname>MenuItemBean.setDynamicActionAttributesSource()</methodname>
6812 30 Mar 15 nicklas 838       The dynamic attributes are a simple way to output data to
6403 29 Jan 14 nicklas 839       the HTML that is later needed by scripts. In this case, the generated
6403 29 Jan 14 nicklas 840       HTML may look something like this:
6403 29 Jan 14 nicklas 841     </para>
6403 29 Jan 14 nicklas 842     
6403 29 Jan 14 nicklas 843     <programlisting language="html">
6403 29 Jan 14 nicklas 844 <![CDATA[
6403 29 Jan 14 nicklas 845 <div id="greetings-user" data-user-name="..." data-prefix="Greetings" ... >
6403 29 Jan 14 nicklas 846 ...
6403 29 Jan 14 nicklas 847 </div>
6403 29 Jan 14 nicklas 848 ]]>
6403 29 Jan 14 nicklas 849 </programlisting>
6403 29 Jan 14 nicklas 850     
6403 29 Jan 14 nicklas 851     <para>
4184 20 Mar 08 nicklas 852       Here is an example of an extension configuration that can be used
6410 31 Jan 14 nicklas 853       with the new factory. Notice that the <sgmltag class="starttag">about</sgmltag>
6410 31 Jan 14 nicklas 854       tag now include <code>safe-scripts="1"</code> attribute. This is a way
6410 31 Jan 14 nicklas 855       for the devloper to tell the extensions installation wizard that the extensions
6410 31 Jan 14 nicklas 856       doesn't use any unsafe code and no warning will be displayed when installing the
6410 31 Jan 14 nicklas 857       extensions.
4184 20 Mar 08 nicklas 858     </para>
4184 20 Mar 08 nicklas 859     
4184 20 Mar 08 nicklas 860     <programlisting language="xml">
4184 20 Mar 08 nicklas 861 <![CDATA[
4184 20 Mar 08 nicklas 862 <extensions xmlns="http://base.thep.lu.se/extensions.xsd">
4184 20 Mar 08 nicklas 863    <extension
4184 20 Mar 08 nicklas 864       id="net.sf.basedb.clients.web.menu.extensions.hellouser"
4184 20 Mar 08 nicklas 865       extends="net.sf.basedb.clients.web.menu.extensions"
4184 20 Mar 08 nicklas 866       >
4184 20 Mar 08 nicklas 867       <index>3</index>
6410 31 Jan 14 nicklas 868       <about safe-scripts="1">
4184 20 Mar 08 nicklas 869          <name>Greetings user</name>
4184 20 Mar 08 nicklas 870          <description>
4184 20 Mar 08 nicklas 871             A "Hello world" variant with a custom action factory
4184 20 Mar 08 nicklas 872             that displays "Greetings {name of user}" instead. We also
4184 20 Mar 08 nicklas 873             make the icon configurable.
4184 20 Mar 08 nicklas 874          </description>
4184 20 Mar 08 nicklas 875       </about>
4184 20 Mar 08 nicklas 876       <action-factory>
4184 20 Mar 08 nicklas 877          <factory-class>
4184 20 Mar 08 nicklas 878             net.sf.basedb.examples.extensions.HelloUserFactory
4184 20 Mar 08 nicklas 879          </factory-class>
4184 20 Mar 08 nicklas 880          <parameters>
6403 29 Jan 14 nicklas 881           <id>greetings-user</id>
4184 20 Mar 08 nicklas 882             <prefix>Greetings</prefix>
4184 20 Mar 08 nicklas 883             <icon>/images/take_ownership.png</icon>
6403 29 Jan 14 nicklas 884             <script>~/scripts/menu-items.js</script>
4184 20 Mar 08 nicklas 885          </parameters>
4184 20 Mar 08 nicklas 886       </action-factory>
4184 20 Mar 08 nicklas 887    </extension>
4184 20 Mar 08 nicklas 888 </extensions>
4184 20 Mar 08 nicklas 889 ]]>
4184 20 Mar 08 nicklas 890 </programlisting>
4184 20 Mar 08 nicklas 891     
6403 29 Jan 14 nicklas 892     <para>
6403 29 Jan 14 nicklas 893     And the <filename>menu-items.js</filename> JavaScript file:
6403 29 Jan 14 nicklas 894     </para>
6403 29 Jan 14 nicklas 895     <programlisting language="javascript">
6403 29 Jan 14 nicklas 896 <![CDATA[
6403 29 Jan 14 nicklas 897 var HelloWorldMenu = function()
6403 29 Jan 14 nicklas 898 {
6403 29 Jan 14 nicklas 899    var menu = {};
6403 29 Jan 14 nicklas 900
6403 29 Jan 14 nicklas 901    /**
6403 29 Jan 14 nicklas 902       Executed once when the page is loaded. Typically
6403 29 Jan 14 nicklas 903       used to bind events to fixed control elements.
6403 29 Jan 14 nicklas 904    */
6403 29 Jan 14 nicklas 905    menu.initMenuItems = function()
6403 29 Jan 14 nicklas 906    {
6403 29 Jan 14 nicklas 907       // Bind event handlers the menu items. 
6403 29 Jan 14 nicklas 908       // First parameter is the ID of the menu item
6403 29 Jan 14 nicklas 909       // Second parameter is the event to react to (=click)
6403 29 Jan 14 nicklas 910       // Last parameter is the function to execute
6403 29 Jan 14 nicklas 911       Events.addEventHandler('greetings-user', 'click', menu.greetingsUser);
6403 29 Jan 14 nicklas 912    }
6403 29 Jan 14 nicklas 913
6403 29 Jan 14 nicklas 914    // Get the dynamic attributes defined in extensions.xml 
6403 29 Jan 14 nicklas 915    // and generate an alert message
6403 29 Jan 14 nicklas 916    menu.greetingsUser = function(event)
6403 29 Jan 14 nicklas 917    {
6403 29 Jan 14 nicklas 918       var userName = Data.get(event.currentTarget, 'user-name');
6403 29 Jan 14 nicklas 919       var prefix = Data.get(event.currentTarget, 'prefix');
6403 29 Jan 14 nicklas 920       alert(prefix + ' ' + userName + '!');
6403 29 Jan 14 nicklas 921    }
6403 29 Jan 14 nicklas 922
6403 29 Jan 14 nicklas 923    return menu;
6403 29 Jan 14 nicklas 924 }();
6403 29 Jan 14 nicklas 925
6403 29 Jan 14 nicklas 926 //Register the page initializer method with the BASE core
6403 29 Jan 14 nicklas 927 Doc.onLoad(HelloWorldMenu.initMenuItems);
6403 29 Jan 14 nicklas 928 ]]>
6403 29 Jan 14 nicklas 929 </programlisting>
6403 29 Jan 14 nicklas 930     
4206 04 Apr 08 nicklas 931     <note>
4206 04 Apr 08 nicklas 932       <title>Be aware of multi-threading issues</title>
4206 04 Apr 08 nicklas 933       <para>
4206 04 Apr 08 nicklas 934         When you are creating custom action and renderer factories be 
4206 04 Apr 08 nicklas 935         aware that multiple threads may use a single factory instance 
4206 04 Apr 08 nicklas 936         at the same time. Action and renderer objects only needs to 
4206 04 Apr 08 nicklas 937         be thread-safe if the factories re-use the same objects.
4206 04 Apr 08 nicklas 938       </para>
4206 04 Apr 08 nicklas 939     </note>
4206 04 Apr 08 nicklas 940     
4184 20 Mar 08 nicklas 941   </sect1>
4184 20 Mar 08 nicklas 942
4206 04 Apr 08 nicklas 943   <sect1 id="extensions_developer.resources">
5782 04 Oct 11 nicklas 944     <?dbhtml filename="resources.html" ?>
4184 20 Mar 08 nicklas 945     <title>Custom images, JSP files, and other resources</title>
4184 20 Mar 08 nicklas 946
4184 20 Mar 08 nicklas 947     <para>
4184 20 Mar 08 nicklas 948       Some times your extension may need other resources. It can for
4184 20 Mar 08 nicklas 949       for example be an icon, a javascript file, a JSP file or something
4184 20 Mar 08 nicklas 950       else. Fortunately this is very easy. You need to put the extension
4184 20 Mar 08 nicklas 951       in a JAR file. As usual the extension definition XML file should be
4184 20 Mar 08 nicklas 952       at <filename>META-INF/extensions.xml</filename>. Everything you put in
4184 20 Mar 08 nicklas 953       the JAR file inside the <filename>resources/</filename> directory
4184 20 Mar 08 nicklas 954       will automatically be extracted by the extension system to a directory
4184 20 Mar 08 nicklas 955       on the web server. Here is another "Hello world" example which uses a
4223 15 Apr 08 nicklas 956       custom JSP file to display the message. There is also a custom icon.
4184 20 Mar 08 nicklas 957     </para>
4184 20 Mar 08 nicklas 958     
4184 20 Mar 08 nicklas 959     <programlisting language="xml">
4184 20 Mar 08 nicklas 960 <![CDATA[
4184 20 Mar 08 nicklas 961 <extensions xmlns="http://base.thep.lu.se/extensions.xsd">
4184 20 Mar 08 nicklas 962    <extension
4184 20 Mar 08 nicklas 963       id="net.sf.basedb.clients.web.menu.extensions.hellojspworld"
4184 20 Mar 08 nicklas 964       extends="net.sf.basedb.clients.web.menu.extensions"
4184 20 Mar 08 nicklas 965       >
4184 20 Mar 08 nicklas 966       <index>4</index>
6417 06 Feb 14 nicklas 967       <about safe-scripts="1" safe-resources="1">
4184 20 Mar 08 nicklas 968          <name>Hello JSP world</name>
4184 20 Mar 08 nicklas 969          <description>
4223 15 Apr 08 nicklas 970             This example uses a custom JSP file to display the
4184 20 Mar 08 nicklas 971             "Hello world" message instead of a javascript popup.
4184 20 Mar 08 nicklas 972          </description>
4184 20 Mar 08 nicklas 973       </about>
4184 20 Mar 08 nicklas 974       <action-factory>
4184 20 Mar 08 nicklas 975          <factory-class>
4184 20 Mar 08 nicklas 976             net.sf.basedb.clients.web.extensions.menu.FixedMenuItemFactory
4184 20 Mar 08 nicklas 977          </factory-class>
4184 20 Mar 08 nicklas 978          <parameters>
4184 20 Mar 08 nicklas 979             <title>Hello JSP world!</title>
4223 15 Apr 08 nicklas 980             <tooltip>Opens a JSP file with the message</tooltip>
6403 29 Jan 14 nicklas 981             <data-url>$HOME$/hello_world.jsp?ID=$SESSION-ID$</data-url>
6403 29 Jan 14 nicklas 982             <data-popup>HelloJspWorld, 400, 300</data-popup>
4184 20 Mar 08 nicklas 983             <icon>~/images/world.png</icon>
4184 20 Mar 08 nicklas 984          </parameters>
4184 20 Mar 08 nicklas 985       </action-factory>
4184 20 Mar 08 nicklas 986    </extension>
4184 20 Mar 08 nicklas 987 </extensions>
4184 20 Mar 08 nicklas 988 ]]>
4184 20 Mar 08 nicklas 989 </programlisting>
4184 20 Mar 08 nicklas 990     
4184 20 Mar 08 nicklas 991     <para>
4184 20 Mar 08 nicklas 992       The JAR file should have have the following contents:
4184 20 Mar 08 nicklas 993     </para>
4184 20 Mar 08 nicklas 994     
4184 20 Mar 08 nicklas 995     <programlisting>
4184 20 Mar 08 nicklas 996 META-INF/extensions.XML
4184 20 Mar 08 nicklas 997 resources/hello_world.jsp
4184 20 Mar 08 nicklas 998 resources/images/world.png
4184 20 Mar 08 nicklas 999 </programlisting>
4184 20 Mar 08 nicklas 1000     
4184 20 Mar 08 nicklas 1001     <para>
4184 20 Mar 08 nicklas 1002       When this extension is installed the <filename>hello_world.jsp</filename>
4184 20 Mar 08 nicklas 1003       and <filename>world.png</filename> files are automatically extracted
4184 20 Mar 08 nicklas 1004       to the web servers file system. Each extension is given a unique 
4184 20 Mar 08 nicklas 1005       <code>HOME</code> directory to make sure that extensions doesn't interfere
4184 20 Mar 08 nicklas 1006       with each other. The URL to the home directory is made available in the
4184 20 Mar 08 nicklas 1007       <varname>$HOME$</varname> variable. All factory settings that have
4184 20 Mar 08 nicklas 1008       been annotated with the <interfacename 
4184 20 Mar 08 nicklas 1009       docapi="net.sf.basedb.util.extensions.xml">VariableSetter</interfacename>
4184 20 Mar 08 nicklas 1010       will have their values scanned for <code>$HOME$</code> which is replaced
4184 20 Mar 08 nicklas 1011       with the real URL. It is also possible to use the <varname>$ROOT$</varname>
4184 20 Mar 08 nicklas 1012       variable to get the root URL for the BASE web application. Never use
4184 20 Mar 08 nicklas 1013       <code>/base/...</code> since users may install BASE into another 
4184 20 Mar 08 nicklas 1014       path.
4184 20 Mar 08 nicklas 1015     </para>
4184 20 Mar 08 nicklas 1016     
4184 20 Mar 08 nicklas 1017     <para>
4184 20 Mar 08 nicklas 1018       The tilde (~) in the <sgmltag class="starttag">icon</sgmltag> tag value
4184 20 Mar 08 nicklas 1019       is also replaced with the <code>HOME</code> path. Note that this kind of
4184 20 Mar 08 nicklas 1020       replacement is only done on factory settings that have been annotated
4184 20 Mar 08 nicklas 1021       with the <classname docapi="net.sf.basedb.util.extensions.xml">PathSetter</classname>
4184 20 Mar 08 nicklas 1022       annotation and is only done on the first character.
4184 20 Mar 08 nicklas 1023     </para>
4184 20 Mar 08 nicklas 1024     
6417 06 Feb 14 nicklas 1025     <para>
6417 06 Feb 14 nicklas 1026       The <code>safe-resources="1"</code> attribute in the <sgmltag class="starttag">about</sgmltag>
6417 06 Feb 14 nicklas 1027       tag is used to tell BASE that all resource files doesn't use inline scripts or event handlers.
6417 06 Feb 14 nicklas 1028       This is the default setting and don't have to be included. On the other hand, 
6417 06 Feb 14 nicklas 1029       if <code>safe-resources="0"</code> is specified BASE uses a less restrictive content
6417 06 Feb 14 nicklas 1030       security policy for that extension that allows the use of inline scripts. This setting
6417 06 Feb 14 nicklas 1031       is not recommended but can be useful during a transition phase while the extensions code
6417 06 Feb 14 nicklas 1032       is being updated.
6417 06 Feb 14 nicklas 1033     </para>
6417 06 Feb 14 nicklas 1034     
4221 14 Apr 08 nicklas 1035     <note>
4221 14 Apr 08 nicklas 1036       <para>
4223 15 Apr 08 nicklas 1037       Unfortunately, the custom JSP file can't use classes that
4221 14 Apr 08 nicklas 1038       are located in the extension's JAR file. The reason is that the
4223 15 Apr 08 nicklas 1039       JAR file is not known to Tomcat and Tomcat will not look in the
5640 24 May 11 nicklas 1040       <filename>plugins.dir</filename> folder to
4223 15 Apr 08 nicklas 1041       try to find classes. There are currently two possible workarounds:
4221 14 Apr 08 nicklas 1042       </para>
4223 15 Apr 08 nicklas 1043       
4223 15 Apr 08 nicklas 1044       <itemizedlist>
4223 15 Apr 08 nicklas 1045       <listitem>
4223 15 Apr 08 nicklas 1046         <para>
4223 15 Apr 08 nicklas 1047         Place classes needed by JSP files in a separate JAR file that
4223 15 Apr 08 nicklas 1048         is installed into the <filename>WEB-INF/lib</filename> folder. 
4223 15 Apr 08 nicklas 1049         The drawback is that this requires a restart of Tomcat.
4223 15 Apr 08 nicklas 1050         </para>
4223 15 Apr 08 nicklas 1051       </listitem>
4223 15 Apr 08 nicklas 1052       
4223 15 Apr 08 nicklas 1053       <listitem>
4223 15 Apr 08 nicklas 1054         <para>
4223 15 Apr 08 nicklas 1055         Use an X-JSP file instead. This is an experimental feature. See
4223 15 Apr 08 nicklas 1056         <xref linkend="extensions_developer.resources.xjsp" /> for more 
4223 15 Apr 08 nicklas 1057         information.
4223 15 Apr 08 nicklas 1058         </para>
4223 15 Apr 08 nicklas 1059       </listitem>
4223 15 Apr 08 nicklas 1060       </itemizedlist>
4221 14 Apr 08 nicklas 1061     </note>
4221 14 Apr 08 nicklas 1062     
4206 04 Apr 08 nicklas 1063     <sect2 id="extensions_developer.resources.scripts">
4184 20 Mar 08 nicklas 1064       <title>Javascript and stylesheets</title>
4184 20 Mar 08 nicklas 1065       
4184 20 Mar 08 nicklas 1066       <para>
4184 20 Mar 08 nicklas 1067         It is possible for an extension to use a custom javascript or stylesheet.
4184 20 Mar 08 nicklas 1068         However, this doesn't happen automatically and may not be enabled
4184 20 Mar 08 nicklas 1069         for all extension points. If an extension needs this functionality
4184 20 Mar 08 nicklas 1070         the action factory or renderer factory must call 
4184 20 Mar 08 nicklas 1071         <methodname>JspContext.addScript()</methodname> or 
4184 20 Mar 08 nicklas 1072         <methodname>JspContext.addStylesheet()</methodname> from the 
4184 20 Mar 08 nicklas 1073         <methodname>prepareContext()</methodname> method.
4184 20 Mar 08 nicklas 1074       </para>
4184 20 Mar 08 nicklas 1075       
4184 20 Mar 08 nicklas 1076       <para>
4184 20 Mar 08 nicklas 1077         The <classname 
4184 20 Mar 08 nicklas 1078         docapi="net.sf.basedb.clients.web.extensions">AbstractJspActionFactory</classname>
4184 20 Mar 08 nicklas 1079         and <classname 
4184 20 Mar 08 nicklas 1080         docapi="net.sf.basedb.clients.web.extensions">AbstractJspRendererFactory</classname>
4184 20 Mar 08 nicklas 1081         factory can do this. All factories shipped with BASE extends one of those
4184 20 Mar 08 nicklas 1082         classes and we recommend that custom-made factories also does this.
4184 20 Mar 08 nicklas 1083       </para>
4184 20 Mar 08 nicklas 1084       
4184 20 Mar 08 nicklas 1085       <para>
4184 20 Mar 08 nicklas 1086         Factories that are extending one of those two classes can use
4184 20 Mar 08 nicklas 1087         <sgmltag class="starttag">script</sgmltag> and 
4184 20 Mar 08 nicklas 1088         <sgmltag class="starttag">stylesheet</sgmltag> tags in the 
4184 20 Mar 08 nicklas 1089         <sgmltag class="starttag">parameters</sgmltag> section for an
4184 20 Mar 08 nicklas 1090         extensions. Each tag may be used more than one time. The
4184 20 Mar 08 nicklas 1091         values are subject to path and variable substitution.
4184 20 Mar 08 nicklas 1092       </para>
4184 20 Mar 08 nicklas 1093       
4184 20 Mar 08 nicklas 1094       <programlisting language="xml">
4184 20 Mar 08 nicklas 1095 <![CDATA[
4184 20 Mar 08 nicklas 1096 <action-factory>
4184 20 Mar 08 nicklas 1097    <factory-class>
4184 20 Mar 08 nicklas 1098       ... some factory class ...
4184 20 Mar 08 nicklas 1099    </factory-class>
4184 20 Mar 08 nicklas 1100    <parameters>
4184 20 Mar 08 nicklas 1101       <script>~/scripts/custom.js</script>
4184 20 Mar 08 nicklas 1102       <stylesheet>~/css/custom.css</stylesheet>
4184 20 Mar 08 nicklas 1103       ... other parameters ...
4184 20 Mar 08 nicklas 1104    </parameters>
4184 20 Mar 08 nicklas 1105 </action-factory>
4184 20 Mar 08 nicklas 1106 ]]>
4184 20 Mar 08 nicklas 1107 </programlisting>
4184 20 Mar 08 nicklas 1108       
4184 20 Mar 08 nicklas 1109       <para>
4184 20 Mar 08 nicklas 1110         If scripts and stylesheets has been added to the JSP context
4184 20 Mar 08 nicklas 1111         the extension system will, <emphasis>in most cases</emphasis>, 
4184 20 Mar 08 nicklas 1112         include the proper HTML to link in the requested scripts and/or 
4184 20 Mar 08 nicklas 1113         stylesheet.
4184 20 Mar 08 nicklas 1114       </para>
4184 20 Mar 08 nicklas 1115       
4184 20 Mar 08 nicklas 1116       <note>
5426 24 Sep 10 nicklas 1117         <title>Use UTF-8 character encoding</title>
5426 24 Sep 10 nicklas 1118         <para>
5426 24 Sep 10 nicklas 1119           The script and stylesheet files should use use UTF-8 character encoding.
5426 24 Sep 10 nicklas 1120           Otherwise they may not work as expected in BASE.
5426 24 Sep 10 nicklas 1121         </para>
5426 24 Sep 10 nicklas 1122       </note>
5426 24 Sep 10 nicklas 1123       
5426 24 Sep 10 nicklas 1124       <note>
4184 20 Mar 08 nicklas 1125         <title>All extension points doesn't support custom scripts/stylesheets</title>
4184 20 Mar 08 nicklas 1126         <para>
4184 20 Mar 08 nicklas 1127           In some cases the rendering of the HTML page has gone to far
4184 20 Mar 08 nicklas 1128           to make is possible to include custom scripts and stylesheets.
4184 20 Mar 08 nicklas 1129           This is for example the case with the extensions menu. Always
4184 20 Mar 08 nicklas 1130           check the documentation for the extension point if scripts
4184 20 Mar 08 nicklas 1131           and stylesheets are supported or not.
4184 20 Mar 08 nicklas 1132         </para>
4184 20 Mar 08 nicklas 1133       </note>
4184 20 Mar 08 nicklas 1134     </sect2>
4223 15 Apr 08 nicklas 1135     
4223 15 Apr 08 nicklas 1136     <sect2 id="extensions_developer.resources.xjsp">
4223 15 Apr 08 nicklas 1137       <title>X-JSP files</title>
4223 15 Apr 08 nicklas 1138       
4223 15 Apr 08 nicklas 1139       <para>
4223 15 Apr 08 nicklas 1140         The drawback with a custom JSP file is that it is not possible to
4223 15 Apr 08 nicklas 1141         use classes from the extension's JAR file in the JSP code. The reason 
4223 15 Apr 08 nicklas 1142         is that the JAR file is not known to Tomcat and Tomcat will not look 
5640 24 May 11 nicklas 1143         in the <filename>plugins.dir</filename> folder to try to find 
4223 15 Apr 08 nicklas 1144         classes.
4223 15 Apr 08 nicklas 1145       </para>
4223 15 Apr 08 nicklas 1146       
4223 15 Apr 08 nicklas 1147       <para>
4223 15 Apr 08 nicklas 1148         One workaround is to place classes that are needed by the JSP files
4223 15 Apr 08 nicklas 1149         in a separate JAR file that is placed in <filename>WEB-INF/lib</filename>.
4223 15 Apr 08 nicklas 1150         The drawback with this is that it requires a restart of Tomcat. It is
4223 15 Apr 08 nicklas 1151         also a second step that has to be performed manually by the person 
4223 15 Apr 08 nicklas 1152         installing the extension and is maybe forgotten when doing an update.
4223 15 Apr 08 nicklas 1153       </para>
4223 15 Apr 08 nicklas 1154       
4223 15 Apr 08 nicklas 1155       <para>
4223 15 Apr 08 nicklas 1156         Another workaround is to use an X-JSP file. This is simply a regular
4223 15 Apr 08 nicklas 1157         JSP file that has a <code>.xjsp</code> extension instead of <code>.jsp</code>.
4223 15 Apr 08 nicklas 1158         The <code>.xjsp</code> extension will trigger the use of a different
4223 15 Apr 08 nicklas 1159         compiler that knows how to include the extension's JAR file in the class
4223 15 Apr 08 nicklas 1160         path.
4223 15 Apr 08 nicklas 1161       </para>
4223 15 Apr 08 nicklas 1162       
4223 15 Apr 08 nicklas 1163       <note>
4223 15 Apr 08 nicklas 1164         <title>X-JSP is experimental</title>
4223 15 Apr 08 nicklas 1165         <para>
4223 15 Apr 08 nicklas 1166           The X-JSP compiler depends on functionality that is internal to
4223 15 Apr 08 nicklas 1167           Tomcat. The JSP compiler is not part of any open specification
4223 15 Apr 08 nicklas 1168           and the implementation details may change at any time. This means
4223 15 Apr 08 nicklas 1169           that the X-JSP compiler may or may not work with future versions
6864 15 Apr 15 nicklas 1170           of Tomcat. We have currently tested it with Tomcat 8.0.21 only.
4223 15 Apr 08 nicklas 1171           It will most likely not work with other servlet containers.
4223 15 Apr 08 nicklas 1172         </para>
4223 15 Apr 08 nicklas 1173         
4223 15 Apr 08 nicklas 1174         <para>
4223 15 Apr 08 nicklas 1175           Adding support for X-JSP requires that a JAR file with the 
4223 15 Apr 08 nicklas 1176           X-JSP compiler is installed into Tomcat's internal <filename>/lib</filename>
4223 15 Apr 08 nicklas 1177           directory. It is an optional step and not all BASE installations
5737 14 Sep 11 nicklas 1178           may have the compiler installed. See <xref linkend="plugins.installation.xjspcompiler" />.
4223 15 Apr 08 nicklas 1179         </para>
4223 15 Apr 08 nicklas 1180       </note>
4223 15 Apr 08 nicklas 1181       
4223 15 Apr 08 nicklas 1182     </sect2>
4184 20 Mar 08 nicklas 1183   </sect1>
4184 20 Mar 08 nicklas 1184   
4206 04 Apr 08 nicklas 1185   <sect1 id="extensions_developer.renderer">
5782 04 Oct 11 nicklas 1186     <?dbhtml filename="renderer.html" ?>
4184 20 Mar 08 nicklas 1187     <title>Custom renderers and renderer factories</title>
4184 20 Mar 08 nicklas 1188
4184 20 Mar 08 nicklas 1189     <para>
4206 04 Apr 08 nicklas 1190       It is always the responsibility of the extension point to
4206 04 Apr 08 nicklas 1191       render an action. The need for custom renderers is typically
4206 04 Apr 08 nicklas 1192       very small, at least if you want your extensions to blend into
4206 04 Apr 08 nicklas 1193       the look and feel of the BASE web client. Most customizations can
4206 04 Apr 08 nicklas 1194       be probably be handled by stylesheets and images. That said,
4206 04 Apr 08 nicklas 1195       you may still have a reason for using a custom renderer.
4184 20 Mar 08 nicklas 1196     </para>
4206 04 Apr 08 nicklas 1197     
4206 04 Apr 08 nicklas 1198     <para>
4206 04 Apr 08 nicklas 1199       Renderer factories are not very different from action factories.
4206 04 Apr 08 nicklas 1200       They are specified in the same way in the XML file and uses the
4206 04 Apr 08 nicklas 1201       same method for initialisation, including support for path
4206 04 Apr 08 nicklas 1202       conversion, etc. The difference is that you use a
4206 04 Apr 08 nicklas 1203       <sgmltag class="starttag">renderer-factory</sgmltag> tag
4206 04 Apr 08 nicklas 1204       instead of an <sgmltag class="starttag">action-factory</sgmltag>
4206 04 Apr 08 nicklas 1205       tag.
4206 04 Apr 08 nicklas 1206     </para>
4184 20 Mar 08 nicklas 1207
4206 04 Apr 08 nicklas 1208     <programlisting language="xml">
4206 04 Apr 08 nicklas 1209 <![CDATA[
4206 04 Apr 08 nicklas 1210 <renderer-factory>
4206 04 Apr 08 nicklas 1211    <factory-class>
4206 04 Apr 08 nicklas 1212       ... some factory class ...
4206 04 Apr 08 nicklas 1213    </factory-class>
4206 04 Apr 08 nicklas 1214    <parameters>
4206 04 Apr 08 nicklas 1215       ... some parameters ...
4206 04 Apr 08 nicklas 1216    </parameters>
4206 04 Apr 08 nicklas 1217 </renderer-factory>
4206 04 Apr 08 nicklas 1218 ]]>
4206 04 Apr 08 nicklas 1219 </programlisting>
4206 04 Apr 08 nicklas 1220
4206 04 Apr 08 nicklas 1221     <para>
4206 04 Apr 08 nicklas 1222       A <interfacename docapi="net.sf.basedb.util.extensions"
4206 04 Apr 08 nicklas 1223       >RendererFactory</interfacename> also has a <methodname>prepareContext()</methodname>
4206 04 Apr 08 nicklas 1224       method that can be used to tell the web client about any scripts or stylesheets
4206 04 Apr 08 nicklas 1225       the extension needs. If your renderer factory extends the <classname 
4206 04 Apr 08 nicklas 1226         docapi="net.sf.basedb.clients.web.extensions">AbstractJspRendererFactory</classname>
4206 04 Apr 08 nicklas 1227       class you will not have to worry about this since you can configure
4206 04 Apr 08 nicklas 1228       scripts and stylesheets in the XML file.
4206 04 Apr 08 nicklas 1229     </para>
4206 04 Apr 08 nicklas 1230     
4206 04 Apr 08 nicklas 1231     <para>
4206 04 Apr 08 nicklas 1232       A render factory must also implement the <methodname>getRenderer()</methodname> 
4206 04 Apr 08 nicklas 1233       which should return a <interfacename docapi="net.sf.basedb.util.extensions"
4206 04 Apr 08 nicklas 1234       >Renderer</interfacename> instance. The extension system will then call
4206 04 Apr 08 nicklas 1235       the <methodname>Renderer.render()</methodname> method to render an action.
4206 04 Apr 08 nicklas 1236       This method may be called multiple times if the extension created more than
4206 04 Apr 08 nicklas 1237       one action.
4206 04 Apr 08 nicklas 1238     </para>
4206 04 Apr 08 nicklas 1239     
4206 04 Apr 08 nicklas 1240     <para>
4206 04 Apr 08 nicklas 1241       The renderers responsibility is to generate the HTML
4206 04 Apr 08 nicklas 1242       that is going to be sent to the web client. To do this it needs
4206 04 Apr 08 nicklas 1243       access to the <classname 
4206 04 Apr 08 nicklas 1244       docapi="net.sf.basedb.clients.web.extensions">JspContext</classname> 
4206 04 Apr 08 nicklas 1245       object that was passed to the renderer factory. Here is a simple
4206 04 Apr 08 nicklas 1246       outline of both a renderer factory and renderer. 
4206 04 Apr 08 nicklas 1247     </para>
4206 04 Apr 08 nicklas 1248     
4206 04 Apr 08 nicklas 1249     <programlisting language="java">
4206 04 Apr 08 nicklas 1250 <![CDATA[
4206 04 Apr 08 nicklas 1251 // File: MyRendererFactory.java
4206 04 Apr 08 nicklas 1252 public class MyRendererFactory
4206 04 Apr 08 nicklas 1253    extends AbstractJspRendererFactory<MyAction>
4206 04 Apr 08 nicklas 1254 {
4206 04 Apr 08 nicklas 1255
4206 04 Apr 08 nicklas 1256    public MyRendererFactory()
4206 04 Apr 08 nicklas 1257    {}
4206 04 Apr 08 nicklas 1258
4206 04 Apr 08 nicklas 1259    @Override
4208 07 Apr 08 nicklas 1260    public MyRenderer getRenderer(InvokationContext context)
4206 04 Apr 08 nicklas 1261    {
4208 07 Apr 08 nicklas 1262       return new MyRenderer((JspContext)context.getClientContext());
4206 04 Apr 08 nicklas 1263    }
4206 04 Apr 08 nicklas 1264 }
4206 04 Apr 08 nicklas 1265
4206 04 Apr 08 nicklas 1266 // File: MyRenderer.java
4206 04 Apr 08 nicklas 1267 public class MyRenderer
4206 04 Apr 08 nicklas 1268    implements Renderer<MyAction>
4206 04 Apr 08 nicklas 1269 {
4206 04 Apr 08 nicklas 1270
4206 04 Apr 08 nicklas 1271    private final JspContext context;
4206 04 Apr 08 nicklas 1272    public MyRenderer(JspContext context)
4206 04 Apr 08 nicklas 1273    {
4206 04 Apr 08 nicklas 1274       this.context = context;
4206 04 Apr 08 nicklas 1275    }
4206 04 Apr 08 nicklas 1276
4206 04 Apr 08 nicklas 1277    /**
4206 04 Apr 08 nicklas 1278       Generates HTML (unless invisible): 
6403 29 Jan 14 nicklas 1279       <a class="[clazz]" style="[style]" href="[href]">[title]</a>
4206 04 Apr 08 nicklas 1280    */
4206 04 Apr 08 nicklas 1281    public void render(MyAction action)
4206 04 Apr 08 nicklas 1282    {
4206 04 Apr 08 nicklas 1283       if (!action.isVisible()) return;
4206 04 Apr 08 nicklas 1284       Writer out = context.getOut();
4206 04 Apr 08 nicklas 1285       try
4206 04 Apr 08 nicklas 1286       {
4206 04 Apr 08 nicklas 1287          out.write("<a");
4206 04 Apr 08 nicklas 1288          if (action.getClazz() != null) 
4206 04 Apr 08 nicklas 1289          {
4206 04 Apr 08 nicklas 1290             out.write(" class=\"" + action.getClazz() + "\"");
4206 04 Apr 08 nicklas 1291          }
4206 04 Apr 08 nicklas 1292          if (action.getStyle() != null) 
4206 04 Apr 08 nicklas 1293          {
4206 04 Apr 08 nicklas 1294             out.write(" style=\"" + action.getStyle() + "\"");
4206 04 Apr 08 nicklas 1295          }
6403 29 Jan 14 nicklas 1296          if (action.getHref() != null) 
4206 04 Apr 08 nicklas 1297          {
6403 29 Jan 14 nicklas 1298             out.write(" href=\"" + action.getHref() + "\"");
4206 04 Apr 08 nicklas 1299          }
4206 04 Apr 08 nicklas 1300          out.write(">");
4206 04 Apr 08 nicklas 1301          out.write(HTML.encodeTags(action.getTitle()));
4206 04 Apr 08 nicklas 1302          out.write("</a>\n");
4206 04 Apr 08 nicklas 1303       }
4206 04 Apr 08 nicklas 1304       catch (IOException ex)
4206 04 Apr 08 nicklas 1305       {
4206 04 Apr 08 nicklas 1306          throw new RuntimeException(ex);
4206 04 Apr 08 nicklas 1307       }
4206 04 Apr 08 nicklas 1308    }
4206 04 Apr 08 nicklas 1309 }
4206 04 Apr 08 nicklas 1310 ]]>
4206 04 Apr 08 nicklas 1311 </programlisting>
4184 20 Mar 08 nicklas 1312   </sect1>
4206 04 Apr 08 nicklas 1313   
4206 04 Apr 08 nicklas 1314   <sect1 id="extensions_developer.extension_points">
5782 04 Oct 11 nicklas 1315     <?dbhtml filename="extensionpoints.html" ?>
4206 04 Apr 08 nicklas 1316     <title>Extension points</title>
4206 04 Apr 08 nicklas 1317     
4206 04 Apr 08 nicklas 1318     <para>
4206 04 Apr 08 nicklas 1319       The BASE web client ships with a number of predefined extension
4206 04 Apr 08 nicklas 1320       points. Adding more extension points to the existing web client
4223 15 Apr 08 nicklas 1321       requires some minor modifications to the regular JSP files. But this
4206 04 Apr 08 nicklas 1322       is not what this chapter is about. This chapter is about defining new
4206 04 Apr 08 nicklas 1323       extension points as part of an extension. It is nothing magical about
4206 04 Apr 08 nicklas 1324       this and the process is the same as for the regular extension points in
4206 04 Apr 08 nicklas 1325       the web client.
4206 04 Apr 08 nicklas 1326     </para>
4206 04 Apr 08 nicklas 1327     
4206 04 Apr 08 nicklas 1328     <para>
4206 04 Apr 08 nicklas 1329       The first thing you need to do is to start writing the 
4206 04 Apr 08 nicklas 1330       XML definition of the extension point. Here is an example
4206 04 Apr 08 nicklas 1331       from the web client:
4206 04 Apr 08 nicklas 1332     </para>
4206 04 Apr 08 nicklas 1333     
5816 20 Oct 11 nicklas 1334     <programlisting language="xml">
4206 04 Apr 08 nicklas 1335 <![CDATA[
4206 04 Apr 08 nicklas 1336 <extensions
4206 04 Apr 08 nicklas 1337    xmlns="http://base.thep.lu.se/extensions.xsd"
4206 04 Apr 08 nicklas 1338    >
4206 04 Apr 08 nicklas 1339    <extension-point
4206 04 Apr 08 nicklas 1340       id="net.sf.basedb.clients.web.menu.extensions"
4206 04 Apr 08 nicklas 1341       >
4206 04 Apr 08 nicklas 1342       <action-class>net.sf.basedb.clients.web.extensions.menu.MenuItemAction</action-class>
4206 04 Apr 08 nicklas 1343       <name>Menu: extensions</name>
4206 04 Apr 08 nicklas 1344       <description>
4206 04 Apr 08 nicklas 1345          Extension point for adding extensions to the 'Extensions' menu.
4206 04 Apr 08 nicklas 1346          Extensions should provide MenuItemAction instances. The rendering
4206 04 Apr 08 nicklas 1347          is internal and extensions can't use their own rendering factories.
4206 04 Apr 08 nicklas 1348          The context will only include information about the currently logged
4206 04 Apr 08 nicklas 1349          in user, not information about the current page that is displayed.
4206 04 Apr 08 nicklas 1350          The reason for this is that the rendered menu is cached as a string
4206 04 Apr 08 nicklas 1351          in the user session. The menu is not updated on every page request.
6403 29 Jan 14 nicklas 1352          As of BASE 3.3, this extension point also support custom scripts and
6403 29 Jan 14 nicklas 1353          stylesheets.
4206 04 Apr 08 nicklas 1354       </description>
4206 04 Apr 08 nicklas 1355    </extension-point>
4206 04 Apr 08 nicklas 1356 </extensions>
4206 04 Apr 08 nicklas 1357 ]]>
4206 04 Apr 08 nicklas 1358 </programlisting>
4206 04 Apr 08 nicklas 1359     
4206 04 Apr 08 nicklas 1360     <para>
4206 04 Apr 08 nicklas 1361       The <sgmltag class="starttag">extensions</sgmltag> tag is the root tag and 
4206 04 Apr 08 nicklas 1362       is needed to set up the namespace and schema validation.
4206 04 Apr 08 nicklas 1363     </para>
4206 04 Apr 08 nicklas 1364     
4206 04 Apr 08 nicklas 1365     <para>
4206 04 Apr 08 nicklas 1366       The <sgmltag class="starttag">extension-point</sgmltag> defines a new
4206 04 Apr 08 nicklas 1367       extension point. It must have an <sgmltag>id</sgmltag> attribute that
4206 04 Apr 08 nicklas 1368       is unique among all installed extension points. We recommend using 
4206 04 Apr 08 nicklas 1369       the same naming conventions as for java packages. See <ulink 
5640 24 May 11 nicklas 1370       url="http://www.oracle.com/technetwork/java/codeconventions-135099.html">Java naming
5640 24 May 11 nicklas 1371       conventions from Oracle</ulink>.
4206 04 Apr 08 nicklas 1372     </para>
4206 04 Apr 08 nicklas 1373     
4206 04 Apr 08 nicklas 1374     <note>
4206 04 Apr 08 nicklas 1375       <title>Document the extension point!</title>
4206 04 Apr 08 nicklas 1376       <para>
4206 04 Apr 08 nicklas 1377         The <sgmltag class="starttag">name</sgmltag> and 
4208 07 Apr 08 nicklas 1378         <sgmltag class="starttag">description</sgmltag> tags are optional,
4208 07 Apr 08 nicklas 1379         but we strongly recommend that values are provided.
4208 07 Apr 08 nicklas 1380         The description tag should be used to document the extension
4206 04 Apr 08 nicklas 1381         point. Pay special attention to the support (or lack of
4206 04 Apr 08 nicklas 1382         support) for custom scripts, stylesheets and renderers.
4206 04 Apr 08 nicklas 1383       </para>
4206 04 Apr 08 nicklas 1384     </note>
4206 04 Apr 08 nicklas 1385     
4206 04 Apr 08 nicklas 1386     <para>
4206 04 Apr 08 nicklas 1387       The <sgmltag class="starttag">action-class</sgmltag> defines the
4206 04 Apr 08 nicklas 1388       interface or class that extensions must provide to the extension
4206 04 Apr 08 nicklas 1389       point. This must be a class or interface that is a subclass
4206 04 Apr 08 nicklas 1390       of the <interfacename 
4206 04 Apr 08 nicklas 1391       docapi="net.sf.basedb.util.extensions">Action</interfacename>
4206 04 Apr 08 nicklas 1392       interface. We generally recommend that interfaces are used since
4206 04 Apr 08 nicklas 1393       this gives more implementation flexibility for action factories, but
4206 04 Apr 08 nicklas 1394       a regular class may work just as well. 
4206 04 Apr 08 nicklas 1395     </para>
4206 04 Apr 08 nicklas 1396       
4206 04 Apr 08 nicklas 1397     <para>
4206 04 Apr 08 nicklas 1398       The action class is used to carry information about the action,
6403 29 Jan 14 nicklas 1399       such as a title, which icon to use, a tooltip text, etc. The action class may
4206 04 Apr 08 nicklas 1400       be as simple or complex as you like.
4206 04 Apr 08 nicklas 1401     </para>
4206 04 Apr 08 nicklas 1402       
4206 04 Apr 08 nicklas 1403     <note>
4206 04 Apr 08 nicklas 1404       <title>Web client extension points</title>
4206 04 Apr 08 nicklas 1405       <para>
4206 04 Apr 08 nicklas 1406         This is a note for the core developers. Extension points that
4206 04 Apr 08 nicklas 1407         are part of the web client should always define the action as
4206 04 Apr 08 nicklas 1408         an interface. We recommend that <code>getId()</code>, <code>getClazz()</code>
4206 04 Apr 08 nicklas 1409         and <code>getStyle()</code> attributes are always included if this makes 
4206 04 Apr 08 nicklas 1410         sense. It is usually also a good idea to include <code>isVisible()</code>
4206 04 Apr 08 nicklas 1411         and <code>isEnabled()</code> attributes.
4206 04 Apr 08 nicklas 1412       </para>
4206 04 Apr 08 nicklas 1413     </note>
4206 04 Apr 08 nicklas 1414       
4206 04 Apr 08 nicklas 1415     <para>
4206 04 Apr 08 nicklas 1416       Now, if you are a good citizen you should also provide at least
4206 04 Apr 08 nicklas 1417       one implementation of an action factory that can create the 
4206 04 Apr 08 nicklas 1418       objects of the desired type of action. The factory should
4206 04 Apr 08 nicklas 1419       of course be configurable from the XML file.
4206 04 Apr 08 nicklas 1420     </para>
4206 04 Apr 08 nicklas 1421     
4206 04 Apr 08 nicklas 1422     <para>
4206 04 Apr 08 nicklas 1423       If you are lazy or if you want to immediately start testing the JSP code
4206 04 Apr 08 nicklas 1424       for the extension point, it may be possible to use one of the debugger action
4206 04 Apr 08 nicklas 1425       factories in the <package>net.sf.basedb.util.extensions.debug</package>
4206 04 Apr 08 nicklas 1426       pacakge.
4206 04 Apr 08 nicklas 1427     </para>
4206 04 Apr 08 nicklas 1428     
4206 04 Apr 08 nicklas 1429     <itemizedlist>
4206 04 Apr 08 nicklas 1430     <listitem>
4206 04 Apr 08 nicklas 1431       <para>
4206 04 Apr 08 nicklas 1432       <classname 
4206 04 Apr 08 nicklas 1433       docapi="net.sf.basedb.util.extensions.debug">ProxyActionFactory</classname>:
4206 04 Apr 08 nicklas 1434       This action factory can only be used if your action class is an interface
4206 04 Apr 08 nicklas 1435       and all important methods starts with <code>get</code> or <code>is</code>.
4208 07 Apr 08 nicklas 1436       The proxy action factory uses Java reflection to create a dynamic
4208 07 Apr 08 nicklas 1437       proxy class in runtime. It will map all <code>getX()</code> and <code>isY()</code> 
4206 04 Apr 08 nicklas 1438       methods to retreive the values from the corresponding parameter in the XML file. 
4206 04 Apr 08 nicklas 1439       For example, <methodname>getIcon()</methodname> will retrieve the value
4206 04 Apr 08 nicklas 1440       of the <sgmltag class="starttag">icon</sgmltag> tag and 
4206 04 Apr 08 nicklas 1441       <methodname>isVisible()</methodname> from the <sgmltag 
4206 04 Apr 08 nicklas 1442       class="starttag">visible</sgmltag>. The factory is smart enough to convert
4206 04 Apr 08 nicklas 1443       the string to the correct return value for <type>int</type>, <type>long</type>, 
4206 04 Apr 08 nicklas 1444       <type>float</type>, <type>double</type> and <type>boolean</type> data types and 
4208 07 Apr 08 nicklas 1445       their corresponding object wrapper types, if this is needed.
4206 04 Apr 08 nicklas 1446       </para>
4206 04 Apr 08 nicklas 1447     </listitem>
4206 04 Apr 08 nicklas 1448     
4206 04 Apr 08 nicklas 1449     <listitem>
4206 04 Apr 08 nicklas 1450       <para>
4206 04 Apr 08 nicklas 1451       <classname 
4206 04 Apr 08 nicklas 1452       docapi="net.sf.basedb.util.extensions.debug">BeanActionFactory</classname>:
4206 04 Apr 08 nicklas 1453       This action factory can be used if you have created a bean-like 
4206 04 Apr 08 nicklas 1454       class that implements the desired action class. The factory will
4206 04 Apr 08 nicklas 1455       create an instance of the class specified by the 
4206 04 Apr 08 nicklas 1456       <sgmltag class="starttag">beanClass</sgmltag> parameter. The factory
4206 04 Apr 08 nicklas 1457       will then use Java reflection to find <code>set</code> method
4206 04 Apr 08 nicklas 1458       for the other parameters. If there is a parameter <sgmltag class="starttag">icon</sgmltag>
4206 04 Apr 08 nicklas 1459       the factory first looks for a <methodname>setIcon(String)</methodname>
4206 04 Apr 08 nicklas 1460       method. If it can't find that it will see if there is a <methodname>getIcon()</methodname>
4206 04 Apr 08 nicklas 1461       method which has a return type, T. If so, a second attempt is made to find
4206 04 Apr 08 nicklas 1462       a <methodname>setIcon(T)</methodname> method. The factory is smart enough 
4206 04 Apr 08 nicklas 1463       to convert the string value from the XML file to the correct return value
4206 04 Apr 08 nicklas 1464        for <type>int</type>, <type>long</type>, <type>float</type>, 
4206 04 Apr 08 nicklas 1465       <type>double</type> and <type>boolean</type> data types and their 
4208 07 Apr 08 nicklas 1466       corresponding object wrapper types, if this is needed.
4206 04 Apr 08 nicklas 1467       </para>
4206 04 Apr 08 nicklas 1468     </listitem>
4206 04 Apr 08 nicklas 1469     
4206 04 Apr 08 nicklas 1470     </itemizedlist>
4206 04 Apr 08 nicklas 1471
4206 04 Apr 08 nicklas 1472
4206 04 Apr 08 nicklas 1473     <para>
4206 04 Apr 08 nicklas 1474       It is finally time to write the JSP code that actually uses the
4206 04 Apr 08 nicklas 1475       extension point. It is usually not very complicated. Here is 
4223 15 Apr 08 nicklas 1476       an exemple which lists snippets from a JSP file:
4206 04 Apr 08 nicklas 1477     </para>
4206 04 Apr 08 nicklas 1478
4206 04 Apr 08 nicklas 1479     <programlisting>
4206 04 Apr 08 nicklas 1480 <![CDATA[
4208 07 Apr 08 nicklas 1481 // 1. We recommend using the extensions taglib (and the BASE core taglib)
4206 04 Apr 08 nicklas 1482 <%@ taglib prefix="ext" uri="/WEB-INF/extensions.tld" %>
4206 04 Apr 08 nicklas 1483 <%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
4206 04 Apr 08 nicklas 1484
4208 07 Apr 08 nicklas 1485 // 2. Prepare the extension point
4206 04 Apr 08 nicklas 1486 SessionControl sc = Base.getExistingSessionControl(pageContext, true);
4206 04 Apr 08 nicklas 1487 JspContext jspContext = ExtensionsControl.createContext(sc, pageContext);
4206 04 Apr 08 nicklas 1488 ExtensionsInvoker invoker = ExtensionsControl.useExtensions(jspContext, 
4206 04 Apr 08 nicklas 1489    "my.domain.name.extensionspoint");
4206 04 Apr 08 nicklas 1490
4208 07 Apr 08 nicklas 1491 // 3. Output scripts and stylesheets
4206 04 Apr 08 nicklas 1492 <base:page title="My new extension point">
4206 04 Apr 08 nicklas 1493    <base:head>
4206 04 Apr 08 nicklas 1494       <ext:scripts context="<%=jspContext%>" />
4206 04 Apr 08 nicklas 1495       <ext:stylesheets context="<%=jspContext%>" />
4206 04 Apr 08 nicklas 1496    </base:head>
4206 04 Apr 08 nicklas 1497    <base:body>
4206 04 Apr 08 nicklas 1498    ....
4206 04 Apr 08 nicklas 1499
4208 07 Apr 08 nicklas 1500 // 4a. Using a taglib for rendering with the default renderer
4206 04 Apr 08 nicklas 1501 <ext:render extensions="<%=invoker%>" context="<%=jspContext%>" />
4206 04 Apr 08 nicklas 1502
4208 07 Apr 08 nicklas 1503 // 4b. Or, use the iterator and a more hard-coded approach
4206 04 Apr 08 nicklas 1504 <%
4206 04 Apr 08 nicklas 1505 Iterator it = invoker.iterate();
4206 04 Apr 08 nicklas 1506 while (it.hasNext())
4206 04 Apr 08 nicklas 1507 {
4206 04 Apr 08 nicklas 1508    MyAction action = (MyAction)it.next();
4208 07 Apr 08 nicklas 1509    String html = action.getTitle() +
4208 07 Apr 08 nicklas 1510     ....
4206 04 Apr 08 nicklas 1511    out.write(html);
4206 04 Apr 08 nicklas 1512 }
4206 04 Apr 08 nicklas 1513 %>
4206 04 Apr 08 nicklas 1514 ]]>
4206 04 Apr 08 nicklas 1515 </programlisting>
4206 04 Apr 08 nicklas 1516
5487 15 Nov 10 nicklas 1517     <sect2 id="extensions_developer.error_handler">
5487 15 Nov 10 nicklas 1518       <title>Error handlers</title>
5487 15 Nov 10 nicklas 1519       
5487 15 Nov 10 nicklas 1520       <para>
5487 15 Nov 10 nicklas 1521         An extension points may define a custom error handler. If not, the
5487 15 Nov 10 nicklas 1522         default error handler is used which simply writes a message to the
5487 15 Nov 10 nicklas 1523         log file. If you want to use a different error handler, create
5487 15 Nov 10 nicklas 1524         a <sgmltag class="starttag">error-handler-factory</sgmltag> tag
5487 15 Nov 10 nicklas 1525         inside the extension point definition. The <sgmltag 
5487 15 Nov 10 nicklas 1526         class="starttag">factory-class</sgmltag> is a required subtag and
5487 15 Nov 10 nicklas 1527         must specify a class with a public no-argument constructor that
5487 15 Nov 10 nicklas 1528         implements the 
5487 15 Nov 10 nicklas 1529         <interfacename docapi="net.sf.basedb.util.extensions">ErrorHandlerFactory</interfacename>
5487 15 Nov 10 nicklas 1530         interface. The <sgmltag class="starttag">parameters</sgmltag> subtag is
5487 15 Nov 10 nicklas 1531         optional and can be used to specify initialization parameters for the
5487 15 Nov 10 nicklas 1532         factory just as for action and renderer factories.
5487 15 Nov 10 nicklas 1533       </para>
5487 15 Nov 10 nicklas 1534
5816 20 Oct 11 nicklas 1535       <programlisting language="xml">
5487 15 Nov 10 nicklas 1536 <![CDATA[
5487 15 Nov 10 nicklas 1537 <extensions
5487 15 Nov 10 nicklas 1538    xmlns="http://base.thep.lu.se/extensions.xsd"
5487 15 Nov 10 nicklas 1539    >
5487 15 Nov 10 nicklas 1540    <extension-point
5487 15 Nov 10 nicklas 1541       id="net.sf.basedb.clients.web.menu.extensions"
5487 15 Nov 10 nicklas 1542       >
5487 15 Nov 10 nicklas 1543       <action-class>net.sf.basedb.clients.web.extensions.menu.MenuItemAction</action-class>
5487 15 Nov 10 nicklas 1544       <name>Menu: extensions</name>
5520 23 Nov 10 nicklas 1545       <error-handler-factory>
5520 23 Nov 10 nicklas 1546          <factory-class>
5520 23 Nov 10 nicklas 1547             ... some factory class ...
5520 23 Nov 10 nicklas 1548          </factory-class>
5520 23 Nov 10 nicklas 1549          <parameters>
5520 23 Nov 10 nicklas 1550             ... initialization parameters ...
5520 23 Nov 10 nicklas 1551          </parameters>
5520 23 Nov 10 nicklas 1552       </error-handler-factory>
5487 15 Nov 10 nicklas 1553    </extension-point>
5487 15 Nov 10 nicklas 1554 </extensions>
5487 15 Nov 10 nicklas 1555 ]]>
5487 15 Nov 10 nicklas 1556 </programlisting>
5487 15 Nov 10 nicklas 1557     </sect2>
4206 04 Apr 08 nicklas 1558   </sect1>
4206 04 Apr 08 nicklas 1559   
4221 14 Apr 08 nicklas 1560   <sect1 id="extensions_developer.servlets">
5782 04 Oct 11 nicklas 1561     <?dbhtml filename="servlets.html" ?>
4221 14 Apr 08 nicklas 1562     <title>Custom servlets</title>
4221 14 Apr 08 nicklas 1563     <para>
4221 14 Apr 08 nicklas 1564       It is possible for an extension to include servlets without having
4221 14 Apr 08 nicklas 1565       to register those servlets in Tomcat's <filename>WEB-INF/web.xml</filename>
4221 14 Apr 08 nicklas 1566       file. The extension needs to be in a JAR file as usual. The servlet class
4221 14 Apr 08 nicklas 1567       should be located in the JAR file following regular Java conventions.
4221 14 Apr 08 nicklas 1568       Eg. The class <classname>my.domain.ServletClass</classname> should
4221 14 Apr 08 nicklas 1569       be located at <filename>my/domain/ServletClass.class</filename>. You 
4221 14 Apr 08 nicklas 1570       also need to create a second XML file that contains the servlet
4221 14 Apr 08 nicklas 1571       definitions at <filename>META-INF/servlets.xml</filename>. The format for
4221 14 Apr 08 nicklas 1572       defining servlets in this file is very similar to how servlets are
4221 14 Apr 08 nicklas 1573       defined in the <filename>web.xml</filename> file. Here is an example:
4221 14 Apr 08 nicklas 1574     </para>
4221 14 Apr 08 nicklas 1575     
4221 14 Apr 08 nicklas 1576     <programlisting language="xml">
4221 14 Apr 08 nicklas 1577 <![CDATA[
4221 14 Apr 08 nicklas 1578 <?xml version="1.0" encoding="UTF-8" ?>
4221 14 Apr 08 nicklas 1579 <servlets xmlns="http://base.thep.lu.se/servlets.xsd">
4221 14 Apr 08 nicklas 1580    <servlet>
4221 14 Apr 08 nicklas 1581       <servlet-name>HelloWorld</servlet-name>
4221 14 Apr 08 nicklas 1582       <servlet-class>net.sf.basedb.examples.extensions.HelloWorldServlet</servlet-class>
4221 14 Apr 08 nicklas 1583       <init-param>
4221 14 Apr 08 nicklas 1584          <param-name>template</param-name>
4221 14 Apr 08 nicklas 1585          <param-value>Hello {user}! Welcome to the Servlet world!</param-value>
4221 14 Apr 08 nicklas 1586       </init-param>
4221 14 Apr 08 nicklas 1587    </servlet>
4221 14 Apr 08 nicklas 1588 </servlets>
4221 14 Apr 08 nicklas 1589 ]]>
4221 14 Apr 08 nicklas 1590 </programlisting>
4221 14 Apr 08 nicklas 1591
4221 14 Apr 08 nicklas 1592     <para>
4221 14 Apr 08 nicklas 1593       The <sgmltag class="starttag">servlets</sgmltag> tag is the root tag and is 
4221 14 Apr 08 nicklas 1594       needed to set up the namespace and schema validation. This may contain
4221 14 Apr 08 nicklas 1595       any number of <sgmltag class="starttag">servlet</sgmltag> tags, each one
4221 14 Apr 08 nicklas 1596       defining a single servlet.
4221 14 Apr 08 nicklas 1597     </para>
4221 14 Apr 08 nicklas 1598     
4221 14 Apr 08 nicklas 1599     <para>
4221 14 Apr 08 nicklas 1600       The <sgmltag class="starttag">servlet-name</sgmltag> tag contains the name
4221 14 Apr 08 nicklas 1601       of the servlet. This is a required tag and must be unique among the servlets
4221 14 Apr 08 nicklas 1602       defined by this extension. Other extensions may use the same name without any
4221 14 Apr 08 nicklas 1603       problems.
4221 14 Apr 08 nicklas 1604     </para>
4221 14 Apr 08 nicklas 1605     
4221 14 Apr 08 nicklas 1606     <para>
4221 14 Apr 08 nicklas 1607       The <sgmltag class="starttag">servlet-class</sgmltag> tag contains the name
4221 14 Apr 08 nicklas 1608       of implementing class. This is required and the class must implement
4221 14 Apr 08 nicklas 1609       the <interfacename>Servlet</interfacename> interface and have a public,
4221 14 Apr 08 nicklas 1610       no-argument constructor. We recommend that servlet implementations instead 
4221 14 Apr 08 nicklas 1611       extends the <classname>HttpServlet</classname> class. This will make the 
4221 14 Apr 08 nicklas 1612       servlet programming easier.
4221 14 Apr 08 nicklas 1613     </para>
4221 14 Apr 08 nicklas 1614     
4221 14 Apr 08 nicklas 1615     <para>
4221 14 Apr 08 nicklas 1616       A servlet may have any number <sgmltag class="starttag">init-param</sgmltag>
4221 14 Apr 08 nicklas 1617       tags, containing initialisation parameters for the servlet. Here is the
4221 14 Apr 08 nicklas 1618       code for the servlet references in the above example.
4221 14 Apr 08 nicklas 1619     </para>
4221 14 Apr 08 nicklas 1620
4221 14 Apr 08 nicklas 1621     <programlisting language="java">
4221 14 Apr 08 nicklas 1622 <![CDATA[
4221 14 Apr 08 nicklas 1623 public class HelloWorldServlet 
4221 14 Apr 08 nicklas 1624    extends HttpServlet 
4221 14 Apr 08 nicklas 1625 {
4221 14 Apr 08 nicklas 1626    private String template;
4221 14 Apr 08 nicklas 1627    public HelloWorldServlet()
4221 14 Apr 08 nicklas 1628    {}
4221 14 Apr 08 nicklas 1629
4221 14 Apr 08 nicklas 1630    @Override
4221 14 Apr 08 nicklas 1631    public void init()
4221 14 Apr 08 nicklas 1632       throws ServletException
4221 14 Apr 08 nicklas 1633    {
4221 14 Apr 08 nicklas 1634       ServletConfig cfg = getServletConfig();
4221 14 Apr 08 nicklas 1635       template = cfg.getInitParameter("template");
4221 14 Apr 08 nicklas 1636       if (template == null) template = "Hello {user}.";
4221 14 Apr 08 nicklas 1637    }
4221 14 Apr 08 nicklas 1638
4221 14 Apr 08 nicklas 1639    @Override
4221 14 Apr 08 nicklas 1640    protected void doGet(HttpServletRequest request, HttpServletResponse response)
4221 14 Apr 08 nicklas 1641       throws ServletException, IOException
4221 14 Apr 08 nicklas 1642    {
4221 14 Apr 08 nicklas 1643       final SessionControl sc = Base.getExistingSessionControl(request, true);
4221 14 Apr 08 nicklas 1644       final DbControl dc = sc.newDbControl();
4221 14 Apr 08 nicklas 1645       try
4221 14 Apr 08 nicklas 1646       {
4221 14 Apr 08 nicklas 1647          User current = User.getById(dc, sc.getLoggedInUserId());
4221 14 Apr 08 nicklas 1648          PrintWriter out = response.getWriter();
4221 14 Apr 08 nicklas 1649          out.print(template.replace("{user}", current.getName()));
4221 14 Apr 08 nicklas 1650       }
4221 14 Apr 08 nicklas 1651       finally
4221 14 Apr 08 nicklas 1652       {
4221 14 Apr 08 nicklas 1653          if (dc != null) dc.close();
4221 14 Apr 08 nicklas 1654       }
4221 14 Apr 08 nicklas 1655    }
4221 14 Apr 08 nicklas 1656    @Override
4221 14 Apr 08 nicklas 1657    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
4221 14 Apr 08 nicklas 1658       throws ServletException, IOException
4221 14 Apr 08 nicklas 1659    {
4221 14 Apr 08 nicklas 1660       doGet(req, resp);
4221 14 Apr 08 nicklas 1661    }
4221 14 Apr 08 nicklas 1662 }
4221 14 Apr 08 nicklas 1663 ]]>
4221 14 Apr 08 nicklas 1664 </programlisting>
4221 14 Apr 08 nicklas 1665
4221 14 Apr 08 nicklas 1666     <para>
4221 14 Apr 08 nicklas 1667       Invoking the servlet is done with a URL that is constructed like:
4221 14 Apr 08 nicklas 1668       <filename>$HOME$/[servlet-name].servlet</filename>, where <code>$HOME$</code>
5640 24 May 11 nicklas 1669       is the home directory of the extension. An alternate URL 
4975 15 Jun 09 nicklas 1670       that doesn't require the <filename>.servlet</filename> extension is available: 
4975 15 Jun 09 nicklas 1671       <filename>$SERVLET_HOME$/[servlet-name]</filename>, where <code>$SERVLET_HOME$</code>
4975 15 Jun 09 nicklas 1672       is the home directory of servlets for the extension. Note that this 
4975 15 Jun 09 nicklas 1673       directory is on a different sub-path than the <code>$HOME$</code> directory.
4221 14 Apr 08 nicklas 1674     </para>
4703 11 Dec 08 nicklas 1675     <para>
5640 24 May 11 nicklas 1676       Extra path information is supported 
4703 11 Dec 08 nicklas 1677       if it is inserted between the servlet name and the <filename>.servlet</filename>
4975 15 Jun 09 nicklas 1678       extension: <filename>$HOME$/[servlet-name][/extra/path/info].servlet</filename>,
4975 15 Jun 09 nicklas 1679       <filename>$SERVLET_HOME$/[servlet-name][/extra/path/info]</filename>
4975 15 Jun 09 nicklas 1680       
4703 11 Dec 08 nicklas 1681     </para>
4703 11 Dec 08 nicklas 1682     <para>
4703 11 Dec 08 nicklas 1683       Query parameters are supported as normal:
4975 15 Jun 09 nicklas 1684       <filename>$HOME$/[servlet-name].servlet?param1=value&amp;param2=value</filename>,
4975 15 Jun 09 nicklas 1685       <filename>$SERVLET_HOME$/[servlet-name]?param1=value&amp;param2=value</filename>
4703 11 Dec 08 nicklas 1686     </para>
4703 11 Dec 08 nicklas 1687     
4221 14 Apr 08 nicklas 1688
4221 14 Apr 08 nicklas 1689     <programlisting language="xml">
4221 14 Apr 08 nicklas 1690 <![CDATA[
4221 14 Apr 08 nicklas 1691 <extension
4221 14 Apr 08 nicklas 1692    id="net.sf.basedb.clients.web.menu.extensions.helloservletworld"
4221 14 Apr 08 nicklas 1693    extends="net.sf.basedb.clients.web.menu.extensions"
4221 14 Apr 08 nicklas 1694    >
4221 14 Apr 08 nicklas 1695    <index>5</index>
4221 14 Apr 08 nicklas 1696    <about>
4221 14 Apr 08 nicklas 1697       <name>Hello Servlet world</name>
4221 14 Apr 08 nicklas 1698       <description>
4221 14 Apr 08 nicklas 1699          This example uses a custom Servlet page to display the
4221 14 Apr 08 nicklas 1700          "Hello world" message instead of a javascript popup.
4221 14 Apr 08 nicklas 1701       </description>
4221 14 Apr 08 nicklas 1702    </about>
4221 14 Apr 08 nicklas 1703    <action-factory>
4221 14 Apr 08 nicklas 1704       <factory-class>
4221 14 Apr 08 nicklas 1705          net.sf.basedb.clients.web.extensions.menu.FixedMenuItemFactory
4221 14 Apr 08 nicklas 1706       </factory-class>
4221 14 Apr 08 nicklas 1707       <parameters>
4221 14 Apr 08 nicklas 1708          <title>Hello Servlet world!</title>
4221 14 Apr 08 nicklas 1709          <tooltip>Opens a Servlet generated page with the message</tooltip>
6403 29 Jan 14 nicklas 1710          <data-url>$HOME$/HelloWorld.servlet?ID=$SESSION-ID$</data-url>
6403 29 Jan 14 nicklas 1711          <data-popup>HelloServletWorld, 400, 300</data-popup>
4221 14 Apr 08 nicklas 1712          <icon>~/images/servlet.png</icon>
4221 14 Apr 08 nicklas 1713       </parameters>
4221 14 Apr 08 nicklas 1714    </action-factory>
4221 14 Apr 08 nicklas 1715 </extension>
4221 14 Apr 08 nicklas 1716 ]]>
4221 14 Apr 08 nicklas 1717 </programlisting>
4221 14 Apr 08 nicklas 1718     
4221 14 Apr 08 nicklas 1719     <note>
4221 14 Apr 08 nicklas 1720       <para>
4221 14 Apr 08 nicklas 1721         To keep things as simple as possible, a new instance of the servlet 
4221 14 Apr 08 nicklas 1722         class is created for each request. If the servlet needs complex or 
4221 14 Apr 08 nicklas 1723         expensive initialisation, that should be externalised to other
4221 14 Apr 08 nicklas 1724         classes that the servlet can use.
4221 14 Apr 08 nicklas 1725       </para>
4221 14 Apr 08 nicklas 1726     </note>
4221 14 Apr 08 nicklas 1727     
4221 14 Apr 08 nicklas 1728   </sect1>
4221 14 Apr 08 nicklas 1729   
5640 24 May 11 nicklas 1730   <sect1 id="extensions_developer.base_extension_points">
5782 04 Oct 11 nicklas 1731     <?dbhtml filename="builtin.html" ?>
5640 24 May 11 nicklas 1732     <title>Extension points defined by BASE</title>
5640 24 May 11 nicklas 1733     
5640 24 May 11 nicklas 1734     <para>
5640 24 May 11 nicklas 1735       In this section, we will give an overview of the extension points defined
5640 24 May 11 nicklas 1736       by BASE. Most extension points are used in the web client to add
5640 24 May 11 nicklas 1737       buttons and menu items, but there are a few for the core API as well.
5640 24 May 11 nicklas 1738     </para>
5640 24 May 11 nicklas 1739     
5640 24 May 11 nicklas 1740     <sect2 id="extensions_developer.menuitems">
5640 24 May 11 nicklas 1741       <title>Menu: extensions</title>
5640 24 May 11 nicklas 1742       
5640 24 May 11 nicklas 1743       <para>
5640 24 May 11 nicklas 1744         Menu items can be added to the top-level 
5640 24 May 11 nicklas 1745         <menuchoice><guimenu>Extensions</guimenu></menuchoice>
5640 24 May 11 nicklas 1746         menu. Actions should implement the interface: <interfacename 
5654 15 Jun 11 nicklas 1747         docapi="net.sf.basedb.clients.web.extensions.menu">MenuItemAction</interfacename>
5640 24 May 11 nicklas 1748       </para>
5640 24 May 11 nicklas 1749       
5640 24 May 11 nicklas 1750       <para>
5640 24 May 11 nicklas 1751         The <methodname>MenuItemAction.getMenuType()</methodname> provides support
5640 24 May 11 nicklas 1752         for <constant>MENUITEM</constant>, <constant>SUBMENU</constant> and
5640 24 May 11 nicklas 1753         <constant>SEPARATOR</constant> menus. Which of the other properties that
5640 24 May 11 nicklas 1754         are needed depend on the menu type. Read the javadoc for more information.
6403 29 Jan 14 nicklas 1755         The rendering is internal (eg. extensions can't provide their own renderers).
5640 24 May 11 nicklas 1756       </para>
5640 24 May 11 nicklas 1757       
5640 24 May 11 nicklas 1758       <para>
5640 24 May 11 nicklas 1759         BASE ships with two action factories: 
5654 15 Jun 11 nicklas 1760         <classname docapi="net.sf.basedb.clients.web.extensions.menu">FixedMenuItemFactory</classname> and
5654 15 Jun 11 nicklas 1761         <classname docapi="net.sf.basedb.clients.web.extensions.menu">PermissionMenuItemFactory</classname>.
5640 24 May 11 nicklas 1762         
5640 24 May 11 nicklas 1763         The fixed factory provides a menu that is the same for all users.
5640 24 May 11 nicklas 1764         The permission factory can disable or hide a menu depending on the
5640 24 May 11 nicklas 1765         logged in user's role-based permissions. The title, icon, etc. can have
5640 24 May 11 nicklas 1766         different values depending on if the menu item is disabled or enabled.
5640 24 May 11 nicklas 1767       </para>
6403 29 Jan 14 nicklas 1768       
6403 29 Jan 14 nicklas 1769       <note>
6812 30 Mar 15 nicklas 1770         <title>onclick has been removed</title>
6403 29 Jan 14 nicklas 1771         <para>
6812 30 Mar 15 nicklas 1772           The onclick attribute has been deprecated since BASE 3.3 and was removed in BASE 3.5. Use a custom script instead to
6403 29 Jan 14 nicklas 1773           bind the click event with the menu item or <sgmltag class="starttag">data-url</sgmltag>
6403 29 Jan 14 nicklas 1774           if the menu simply navigates to another page. <sgmltag class="starttag">data-popup</sgmltag> 
6403 29 Jan 14 nicklas 1775           can be used to open the page in a popup window and should contain three comma-separated
6403 29 Jan 14 nicklas 1776           values: name-of-window, width-of-window, height-of-window
6403 29 Jan 14 nicklas 1777         </para>
6403 29 Jan 14 nicklas 1778       </note>
5640 24 May 11 nicklas 1779     </sect2>
5640 24 May 11 nicklas 1780     
5640 24 May 11 nicklas 1781     <sect2 id="extensions_developer.toolbars">
5640 24 May 11 nicklas 1782       <title>Toolbars</title>
5640 24 May 11 nicklas 1783       <para>
5640 24 May 11 nicklas 1784         Most toolbars on all list and single-item view pages can
5640 24 May 11 nicklas 1785         be extended with extra buttons. Actions should implement
5640 24 May 11 nicklas 1786         the interface: <interfacename 
5654 15 Jun 11 nicklas 1787           docapi="net.sf.basedb.clients.web.extensions.toolbar">ButtonAction</interfacename>.
5640 24 May 11 nicklas 1788         Button actions are very simple and only need to provide things like
6403 29 Jan 14 nicklas 1789         a title, tooltip, icon, etc. This extension point has
5640 24 May 11 nicklas 1790         support for custom javascript, stylesheets and renderers. The
5640 24 May 11 nicklas 1791         default renderer is <classname 
5640 24 May 11 nicklas 1792         docapi="net.sf.basedb.clients.web.extensions.toolbar">ToolbarButtonRendererFactory</classname>.
5640 24 May 11 nicklas 1793       </para>
5640 24 May 11 nicklas 1794
5640 24 May 11 nicklas 1795       <para>
5640 24 May 11 nicklas 1796         BASE ships with two action factories: 
5654 15 Jun 11 nicklas 1797         <classname docapi="net.sf.basedb.clients.web.extensions.toolbar">FixedButtonFactory</classname> and
5654 15 Jun 11 nicklas 1798         <classname docapi="net.sf.basedb.clients.web.extensions.toolbar">PermissionButtonFactory</classname>.
5640 24 May 11 nicklas 1799         
5640 24 May 11 nicklas 1800         The fixed factory provides a toolbar button that is the same for all users.
5640 24 May 11 nicklas 1801         The permission factory can disable or hide a buton depending on the
5640 24 May 11 nicklas 1802         logged in user's role-based permissions. The title, icon, etc. can have
5640 24 May 11 nicklas 1803         different values depending on if the menu item is disabled or enabled.
5640 24 May 11 nicklas 1804       </para>
6403 29 Jan 14 nicklas 1805       
6403 29 Jan 14 nicklas 1806       <note>
6812 30 Mar 15 nicklas 1807         <title>onclick has been removed</title>
6403 29 Jan 14 nicklas 1808         <para>
6812 30 Mar 15 nicklas 1809           The onclick attribute has been deprecated since BASE 3.3 and was removed in BASE 3.5. Use a custom script instead to
6403 29 Jan 14 nicklas 1810           bind the click event with the button. Download the example code to see it in action.
6403 29 Jan 14 nicklas 1811         </para>
6403 29 Jan 14 nicklas 1812       </note>
6403 29 Jan 14 nicklas 1813       
5640 24 May 11 nicklas 1814     </sect2>
5640 24 May 11 nicklas 1815
5640 24 May 11 nicklas 1816     <sect2 id="extensions_developer.edit_dialogs">
5640 24 May 11 nicklas 1817       <title>Edit dialogs</title>
5640 24 May 11 nicklas 1818       
5640 24 May 11 nicklas 1819       <para>
5640 24 May 11 nicklas 1820         Most item edit dialogs can be extended with additional tabs. 
5640 24 May 11 nicklas 1821         Actions should implement the interface: <interfacename 
5654 15 Jun 11 nicklas 1822           docapi="net.sf.basedb.clients.web.extensions.tabcontrol">TabAction</interfacename>.
5640 24 May 11 nicklas 1823         The actions are, in principle, simple and only need to
5640 24 May 11 nicklas 1824         provide a title and content (HTML). The action may also provide 
5640 24 May 11 nicklas 1825         javascripts for validation, etc. This extension point has support
5640 24 May 11 nicklas 1826         for custom stylesheets and javascript. Rendering is fixed and can't
5640 24 May 11 nicklas 1827         be overridden.
5640 24 May 11 nicklas 1828       </para>
5640 24 May 11 nicklas 1829       
5640 24 May 11 nicklas 1830       <para>
5640 24 May 11 nicklas 1831         BASE ships with two action factories: 
5654 15 Jun 11 nicklas 1832         <classname docapi="net.sf.basedb.clients.web.extensions.tabcontrol">FixedTabFactory</classname> and
5654 15 Jun 11 nicklas 1833         <classname docapi="net.sf.basedb.clients.web.extensions.tabcontrol">IncludeContentTabFactory</classname>.
5640 24 May 11 nicklas 1834         
5816 20 Oct 11 nicklas 1835         The fixed factory provides a tab with fixed content that is the same for all users
5816 20 Oct 11 nicklas 1836         and all items. This factory is not very useful in a real scenario.
5640 24 May 11 nicklas 1837         The other factory provides content by including the output from another resource,
5640 24 May 11 nicklas 1838         eg. a JSP page, a servlet, etc. The current context is stored in a request-scoped
5640 24 May 11 nicklas 1839         attribute under the key given by <code>JspContext.ATTRIBUTE_KEY</code>. 
5640 24 May 11 nicklas 1840         A JSP or servlet should use this to hook into the current flow. Here is a code example:
5640 24 May 11 nicklas 1841       </para>
5640 24 May 11 nicklas 1842       
5640 24 May 11 nicklas 1843       <programlisting language="java">
5640 24 May 11 nicklas 1844 <![CDATA[
5640 24 May 11 nicklas 1845 // Get the JspContext that was created on the main edit page
5640 24 May 11 nicklas 1846 final JspContext jspContext = (JspContext)request.getAttribute(JspContext.ATTRIBUTE_KEY);
5640 24 May 11 nicklas 1847
5640 24 May 11 nicklas 1848 // The current item is found in the context. NOTE! Can be null if a new item
5640 24 May 11 nicklas 1849 final BasicItem item = (BasicItem)jspContext.getCurrentItem();
5640 24 May 11 nicklas 1850
5640 24 May 11 nicklas 1851 // Get the DbControl and SessionControl used to handle the request (do not close!)
5640 24 May 11 nicklas 1852 final DbControl dc = jspContext.getDbControl();
5640 24 May 11 nicklas 1853 final SessionControl sc = dc.getSessionControl();
5640 24 May 11 nicklas 1854 ]]>
5640 24 May 11 nicklas 1855 </programlisting>
5640 24 May 11 nicklas 1856
5640 24 May 11 nicklas 1857       <para>
5816 20 Oct 11 nicklas 1858         The extra tab need to be paired with an extension that is invoked when
5640 24 May 11 nicklas 1859         the edit form is saved. Each edit-dialog extension point has a corresponding
5640 24 May 11 nicklas 1860         on-save extension point. Actions should implement the interface: <interfacename 
5654 15 Jun 11 nicklas 1861           docapi="net.sf.basedb.clients.web.extensions.edit">OnSaveAction</interfacename>.
5640 24 May 11 nicklas 1862         
5640 24 May 11 nicklas 1863         This interface define three callback methods that BASE will call when
5640 24 May 11 nicklas 1864         saving an item. The <methodname>OnSaveAction.onSave()</methodname>
5640 24 May 11 nicklas 1865         method is called first, but not until all regular properties have been
5640 24 May 11 nicklas 1866         updated. If the transaction is committed the <methodname>OnSaveAction.onCommit()</methodname>
5640 24 May 11 nicklas 1867         method is also called, otherwise the <methodname>OnSaveAction.onRollback()</methodname>
5640 24 May 11 nicklas 1868         is called. The <methodname>onSave()</methodname> method can throw an exception that
5640 24 May 11 nicklas 1869         will be displayed to the user. The other callback method should not throw exceptions
5640 24 May 11 nicklas 1870         at all, since that may result in undefined behaviour and can be confusing for the user.
5640 24 May 11 nicklas 1871       </para>
5640 24 May 11 nicklas 1872     </sect2>
5640 24 May 11 nicklas 1873     
5640 24 May 11 nicklas 1874     <sect2 id="extensions_developer.bioassayset_tools">
5640 24 May 11 nicklas 1875       <title>Bioassay set: Tools</title>
5640 24 May 11 nicklas 1876       <para>
5640 24 May 11 nicklas 1877         The bioassay set listing for an experiment has a <guilabel>Tools</guilabel>
5640 24 May 11 nicklas 1878         column which can be extended by extensions. This extension point is similar
5640 24 May 11 nicklas 1879         to the toolbar extension points and actions should implement
5640 24 May 11 nicklas 1880         the interface: <interfacename 
5654 15 Jun 11 nicklas 1881           docapi="net.sf.basedb.clients.web.extensions.toolbar">ButtonAction</interfacename>.
5640 24 May 11 nicklas 1882       </para>
5640 24 May 11 nicklas 1883       
5640 24 May 11 nicklas 1884       <para>
5640 24 May 11 nicklas 1885         Note that the list can contain 
5640 24 May 11 nicklas 1886         <classname docapi="net.sf.basedb.core">BioAssaySet</classname>,
5640 24 May 11 nicklas 1887         <classname docapi="net.sf.basedb.core">Transformation</classname> and
5640 24 May 11 nicklas 1888         <classname docapi="net.sf.basedb.core">ExtraValue</classname> items.
5640 24 May 11 nicklas 1889         The factory implementation need to be aware of this if it uses
5640 24 May 11 nicklas 1890         the <methodname>JspContext.getItem()</methodname> method to examine the
5640 24 May 11 nicklas 1891         current item.
5640 24 May 11 nicklas 1892       </para>
5640 24 May 11 nicklas 1893     </sect2>
5640 24 May 11 nicklas 1894
5640 24 May 11 nicklas 1895     <sect2 id="extensions_developer.bioassayset_plots">
5640 24 May 11 nicklas 1896       <title>Bioassay set: Overview plots</title>
5640 24 May 11 nicklas 1897       <para>
5640 24 May 11 nicklas 1898         The bioassay set page has a tab <guilabel>Overview plots</guilabel>.
5640 24 May 11 nicklas 1899         The contents of this tab is supposed to be some kind of images
5640 24 May 11 nicklas 1900         that have been generated from the data in the current bioassay set.
5640 24 May 11 nicklas 1901         What kind of plots that can be generated typically depends on the
5640 24 May 11 nicklas 1902         kind of data you have. BASE ships with an extension 
5640 24 May 11 nicklas 1903         (<classname docapi="net.sf.basedb.clients.web.extensions">MAPlotFactory</classname>)
5654 15 Jun 11 nicklas 1904         that creates MA plots and Correction factor plots for 2-channel bioassays.
5654 15 Jun 11 nicklas 1905         Actions should implement the interface: 
5654 15 Jun 11 nicklas 1906         <interfacename docapi="net.sf.basedb.clients.web.extensions.plot">OverviewPlotAction</interfacename>.
5654 15 Jun 11 nicklas 1907         A single action generates a sub-tab in the <guilabel>Overview plots</guilabel> tab.
5654 15 Jun 11 nicklas 1908         The sub-tab may contain  one or more images. Each image is defined by a
5640 24 May 11 nicklas 1909         <interfacename docapi="net.sf.basedb.clients.web.extensions.plot">PlotGenerator</interfacename>
5640 24 May 11 nicklas 1910         which sets the size of the image and provides an URL to a servlet that generates 
5654 15 Jun 11 nicklas 1911         the actual image. It is recommended that the servlet cache images since the
5654 15 Jun 11 nicklas 1912         data in a bioassay set never changes. The BASE core API provides a
5654 15 Jun 11 nicklas 1913         system-managed file cache that is suitable for this. Call 
5654 15 Jun 11 nicklas 1914         <methodname>Application.getStaticCache()</methodname> to get a 
5654 15 Jun 11 nicklas 1915         <classname docapi="net.sf.basedb.util">StaticCache</classname> instance.
5654 15 Jun 11 nicklas 1916         See the source code for the core 
5654 15 Jun 11 nicklas 1917         <classname docapi="net.sf.basedb.clients.web.servlet">PlotServlet</classname>
5654 15 Jun 11 nicklas 1918         for details of how to use the cache.
5640 24 May 11 nicklas 1919       </para>
5640 24 May 11 nicklas 1920       
5640 24 May 11 nicklas 1921     </sect2>
5640 24 May 11 nicklas 1922
5640 24 May 11 nicklas 1923     <sect2 id="extensions_developer.services">
5640 24 May 11 nicklas 1924       <title>Services</title>
5640 24 May 11 nicklas 1925       <para>
5640 24 May 11 nicklas 1926         A service is a piece of code that is loaded when the BASE web 
5640 24 May 11 nicklas 1927         server starts up. The service is then running as long as the BASE web 
5640 24 May 11 nicklas 1928         server is running. It is possible to manually stop and start services. 
5640 24 May 11 nicklas 1929         This extension point is different from most others in that it doesn't 
5640 24 May 11 nicklas 1930         affects the visible interface. Since services are loaded at startup time, 
6443 04 Apr 14 nicklas 1931         this also means that the context passed to <interfacename>ActionFactory</interfacename> 
6443 04 Apr 14 nicklas 1932         methods will have a special <classname>ClientContext</classname> associated with it.
6443 04 Apr 14 nicklas 1933         There is no current item, and no user is logged in. However, the <classname>SessionControl</classname>
6443 04 Apr 14 nicklas 1934         returned from <methodname>ClientContext.getSessionControl()</methodname> gives
6443 04 Apr 14 nicklas 1935         permission to imporsonate another making it possible for the extension
6443 04 Apr 14 nicklas 1936         to access the BASE database almost without limitation. There is no meaning for 
6443 04 Apr 14 nicklas 1937         extensions to specify a <interfacename>RendererFactory</interfacename>. Service 
6443 04 Apr 14 nicklas 1938         actions should implement the interface: 
5654 15 Jun 11 nicklas 1939         <interfacename docapi="net.sf.basedb.clients.web.extensions.service">ServiceControllerAction</interfacename>.
5640 24 May 11 nicklas 1940         
5640 24 May 11 nicklas 1941         The interface provides <methodname>start()</methodname> and
5640 24 May 11 nicklas 1942         <methodname>stop()</methodname> methods for controlling the service.
5640 24 May 11 nicklas 1943         BASE doesn't ship with any service, but there is an FTP service 
5640 24 May 11 nicklas 1944         available at the BASE plug-ins site: <ulink 
7982 14 Jun 21 nicklas 1945         url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.ftp">
7982 14 Jun 21 nicklas 1946         https://baseplugins.thep.lu.se/wiki/net.sf.basedb.ftp</ulink>
5640 24 May 11 nicklas 1947       </para>
5640 24 May 11 nicklas 1948     </sect2>
5640 24 May 11 nicklas 1949
7274 24 Jan 17 nicklas 1950     <sect2 id="extensions_developer.service-actions">
7274 24 Jan 17 nicklas 1951       <title>Service actions</title>
7274 24 Jan 17 nicklas 1952       <para>
7274 24 Jan 17 nicklas 1953         The services list page has an <guilabel>Action</guilabel> column
7274 24 Jan 17 nicklas 1954         for showing the <guilabel>Start</guilabel> and <guilabel>Stop</guilabel>
7274 24 Jan 17 nicklas 1955         actions as well as any other actions extending this extension point.
7274 24 Jan 17 nicklas 1956         This extension point is similar to the toolbar extension points and actions
7274 24 Jan 17 nicklas 1957         should implement the <interfacename 
7274 24 Jan 17 nicklas 1958           docapi="net.sf.basedb.clients.web.extensions.toolbar">ButtonAction</interfacename>
7274 24 Jan 17 nicklas 1959         interface. This extension point supports custom scripts and stylesheets. 
7274 24 Jan 17 nicklas 1960         
7274 24 Jan 17 nicklas 1961         Note that all extensions are invoked for all services. The 
7274 24 Jan 17 nicklas 1962         <methodname>ClientContext.getItem()</methodname> returns the 
7274 24 Jan 17 nicklas 1963         <interfacename docapi="net.sf.basedb.clients.web.extensions.service">ServiceControllerAction</interfacename>
7274 24 Jan 17 nicklas 1964         instance for the current service. Extensions should use this to
7274 24 Jan 17 nicklas 1965         decide if an action should be created or not.
7274 24 Jan 17 nicklas 1966       </para>
7274 24 Jan 17 nicklas 1967     </sect2>
7274 24 Jan 17 nicklas 1968
5640 24 May 11 nicklas 1969     <sect2 id="extensions_developer.connection_manager">
5640 24 May 11 nicklas 1970       <title>Connection managers</title>
5640 24 May 11 nicklas 1971       <para>
5640 24 May 11 nicklas 1972         This extension point adds support for using external files
5640 24 May 11 nicklas 1973         in BASE. This is a core extension point and is available
5640 24 May 11 nicklas 1974         independently of the web client. Actions should implement
5654 15 Jun 11 nicklas 1975         the interface: 
5654 15 Jun 11 nicklas 1976         <interfacename docapi="net.sf.basedb.util.uri">ConnectionManagerFactory</interfacename>.
5640 24 May 11 nicklas 1977       </para>
5640 24 May 11 nicklas 1978       
5640 24 May 11 nicklas 1979       <para>
5640 24 May 11 nicklas 1980         The <methodname>getDisplayName()</methodname> and <methodname>getDescription()</methodname>
5640 24 May 11 nicklas 1981         methods are used in the gui when a user manually selects which connection
5654 15 Jun 11 nicklas 1982         manager to use. The <methodname>supports(URI)</methodname> is used when auto-selecting
5654 15 Jun 11 nicklas 1983         a connection manager based on the URI of the resource.
5640 24 May 11 nicklas 1984       </para>
5640 24 May 11 nicklas 1985       
5640 24 May 11 nicklas 1986       <para>
5640 24 May 11 nicklas 1987         BASE ships with factory that supports HTTP and HTTPS file
5640 24 May 11 nicklas 1988         references: <classname 
5640 24 May 11 nicklas 1989         docapi="net.sf.basedb.util.uri.http">HttpConnectionManagerFactory</classname>.
5640 24 May 11 nicklas 1990         
5640 24 May 11 nicklas 1991         The BASE plug-ins site has an connection manager that support
7548 10 Dec 18 nicklas 1992         external files via FTP and SFTP: <ulink 
7982 14 Jun 21 nicklas 1993         url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.xfiles">
7982 14 Jun 21 nicklas 1994         https://baseplugins.thep.lu.se/wiki/net.sf.basedb.xfiles</ulink>
5640 24 May 11 nicklas 1995       </para>
5640 24 May 11 nicklas 1996       
5640 24 May 11 nicklas 1997     </sect2>
5640 24 May 11 nicklas 1998
5640 24 May 11 nicklas 1999     <sect2 id="extensions_developer.fileset_validator">
5640 24 May 11 nicklas 2000       <title>Fileset validators</title>
5640 24 May 11 nicklas 2001       
5654 15 Jun 11 nicklas 2002       <itemizedlist>
5654 15 Jun 11 nicklas 2003         <title>See also</title>
5654 15 Jun 11 nicklas 2004         <listitem><para><xref linkend="core_api.data_in_files" /></para></listitem>
5654 15 Jun 11 nicklas 2005         <listitem><para><xref linkend="data_api.platforms" /></para></listitem>
5654 15 Jun 11 nicklas 2006       </itemizedlist>
5654 15 Jun 11 nicklas 2007   
5640 24 May 11 nicklas 2008       <para>
5654 15 Jun 11 nicklas 2009         In those cases where files are used to store data instead
5654 15 Jun 11 nicklas 2010         of importing it to the database, BASE can use extensions to 
5654 15 Jun 11 nicklas 2011         check that the supplied files are valid and also to extract
5654 15 Jun 11 nicklas 2012         metadata from the files. For example, the 
5654 15 Jun 11 nicklas 2013         <classname docapi="net.sf.basedb.util.affymetrix">CelValidationAction</classname>
5654 15 Jun 11 nicklas 2014         is used to check if a file is a valid Affymetrix CEL file and
5654 15 Jun 11 nicklas 2015         to extract data headers and the number of spots from it.
5654 15 Jun 11 nicklas 2016       </para>
5640 24 May 11 nicklas 2017       
5654 15 Jun 11 nicklas 2018       <para>
5654 15 Jun 11 nicklas 2019         Validation and metadata extraction actions should implement
5654 15 Jun 11 nicklas 2020         the <interfacename docapi="net.sf.basedb.util.fileset">ValidationAction</interfacename>
5654 15 Jun 11 nicklas 2021         interface. This is a core extension point and is available
5654 15 Jun 11 nicklas 2022         independently of the web client.
5640 24 May 11 nicklas 2023       </para>
5640 24 May 11 nicklas 2024       
5654 15 Jun 11 nicklas 2025       <para>
5654 15 Jun 11 nicklas 2026         This extension point is a bit more complex than most other extension
5654 15 Jun 11 nicklas 2027         points. To begin with, the factory class will be called with the
5654 15 Jun 11 nicklas 2028         owner of the file set as the current item. Eg. the 
5654 15 Jun 11 nicklas 2029         <code>ClientContext.getCurrentItem()</code> should return a
5654 15 Jun 11 nicklas 2030         <interfacename docapi="net.sf.basedb.core">FileStoreEnabled</interfacename>
5654 15 Jun 11 nicklas 2031         item. It is recommended that the factory performs a pre-filtering
5654 15 Jun 11 nicklas 2032         of the items to avoid calling the actual validation code on unsupported
5654 15 Jun 11 nicklas 2033         files. For example, the <classname docapi="net.sf.basedb.util.affymetrix">CelValidationFactory</classname>
5654 15 Jun 11 nicklas 2034         will check that the item is a <classname docapi="net.sf.basedb.core">RawBioAssay</classname>
5654 15 Jun 11 nicklas 2035         item using the Affymetrix platform.
5654 15 Jun 11 nicklas 2036       </para>
5654 15 Jun 11 nicklas 2037       
5654 15 Jun 11 nicklas 2038       <para>
5654 15 Jun 11 nicklas 2039         Each file in the file set is then passed to the
5654 15 Jun 11 nicklas 2040         <methodname>ValidationAction.acceptFile(FileSetMember)</methodname>
5654 15 Jun 11 nicklas 2041         which may accept or reject the file. If the file is accepted it may
5654 15 Jun 11 nicklas 2042         be accepted for immediate validation or later validation. The latter option
5654 15 Jun 11 nicklas 2043         is useful in more complex scenarios were files need to be validated as a group.
5654 15 Jun 11 nicklas 2044         If the file is accepted the <methodname>ValidationAction.validateAndExtractMetadata()</methodname>
5654 15 Jun 11 nicklas 2045         is called, which is were the real work should happen.
5654 15 Jun 11 nicklas 2046       </para>
5654 15 Jun 11 nicklas 2047       
5654 15 Jun 11 nicklas 2048       <para>
5654 15 Jun 11 nicklas 2049         The extensions for this extension point is also called when a file is replaced
5654 15 Jun 11 nicklas 2050         or removed from the file set. The calling sequence to set up the validation is
5654 15 Jun 11 nicklas 2051         more or less the same as described above, but the last step is to 
5654 15 Jun 11 nicklas 2052         call <methodname>ValidationAction.resetMetadata()</methodname> instead
5654 15 Jun 11 nicklas 2053         of <methodname>ValidationAction.validateAndExtractMetadata()</methodname>.
5654 15 Jun 11 nicklas 2054       </para>
5654 15 Jun 11 nicklas 2055
5654 15 Jun 11 nicklas 2056       <tip>
5654 15 Jun 11 nicklas 2057         <title>
5654 15 Jun 11 nicklas 2058           Use the <classname docapi="net.sf.basedb.util.fileset">SingleFileValidationAction</classname>
5654 15 Jun 11 nicklas 2059           class.
5654 15 Jun 11 nicklas 2060         </title>
5654 15 Jun 11 nicklas 2061         <para>
5654 15 Jun 11 nicklas 2062           Most validators that work on a single file at a time may find the
5654 15 Jun 11 nicklas 2063           <classname>SingleFileValidationAction</classname> class useful. Is should
5654 15 Jun 11 nicklas 2064           simplify the task of making sure that only the desired file type is
5654 15 Jun 11 nicklas 2065           validated. See the source code of the <classname 
5654 15 Jun 11 nicklas 2066           docapi="net.sf.basedb.util.affymetrix">CelValidationAction</classname>
5654 15 Jun 11 nicklas 2067           class for an example.
5654 15 Jun 11 nicklas 2068         </para>
5654 15 Jun 11 nicklas 2069       </tip>
5654 15 Jun 11 nicklas 2070       
5640 24 May 11 nicklas 2071     </sect2>
6048 18 Apr 12 nicklas 2072   
6080 07 Aug 12 nicklas 2073     <sect2 id="extensions_developer.logging">
6080 07 Aug 12 nicklas 2074       <title>Logging managers</title>
6080 07 Aug 12 nicklas 2075       
6080 07 Aug 12 nicklas 2076       <para>
6080 07 Aug 12 nicklas 2077         This extension point makes it possible to detect changes that are made to
6080 07 Aug 12 nicklas 2078         item and generate log entries in real time. The core will send notifications
6080 07 Aug 12 nicklas 2079         for all item creations, updates and deletions to all registered logging
6080 07 Aug 12 nicklas 2080         managers. It is up to each implementation to decide if an event should be
6080 07 Aug 12 nicklas 2081         logged, where to log it and how much information that should be stored. 
6080 07 Aug 12 nicklas 2082         The BASE core provides a logging implementation that save some information
6080 07 Aug 12 nicklas 2083         to the database which can also be viewed through the web interface.
6080 07 Aug 12 nicklas 2084       </para>
6080 07 Aug 12 nicklas 2085       
6080 07 Aug 12 nicklas 2086       <para>
6080 07 Aug 12 nicklas 2087         The logging mechanism works on the data layer level and hooks into
6080 07 Aug 12 nicklas 2088         callbacks provided by Hibernate. <interfacename 
6080 07 Aug 12 nicklas 2089         docapi="net.sf.basedb.core.log">EntityLogger</interfacename>:s are used to
6080 07 Aug 12 nicklas 2090         extract relevant information from Hibernate and create log entries.
6080 07 Aug 12 nicklas 2091         While it is possible to have a generic logger it is usually better
6080 07 Aug 12 nicklas 2092         to have different implementations depending on the type of entity that
6080 07 Aug 12 nicklas 2093         was changed. For example, a change in a child item should, for usability
6080 07 Aug 12 nicklas 2094         reasons, be logged as a change in the parent item. Entity loggers
6080 07 Aug 12 nicklas 2095         are created by a <interfacename 
6080 07 Aug 12 nicklas 2096         docapi="net.sf.basedb.core.log">LogManagerFactory</interfacename>. All changes
6080 07 Aug 12 nicklas 2097         made in a single transaction are usually collected by a <interfacename 
6080 07 Aug 12 nicklas 2098         docapi="net.sf.basedb.core.log">LogManager</interfacename> which is also
6080 07 Aug 12 nicklas 2099         created by the factory.
6080 07 Aug 12 nicklas 2100       </para>
6080 07 Aug 12 nicklas 2101       
6080 07 Aug 12 nicklas 2102       <sect3 id="extensions_developer.logging.factory">
6080 07 Aug 12 nicklas 2103         <title>The LogManagerFactory interface</title>
6080 07 Aug 12 nicklas 2104         
6080 07 Aug 12 nicklas 2105         <para>
6080 07 Aug 12 nicklas 2106           Each registered action factory shoulds create a <interfacename 
6080 07 Aug 12 nicklas 2107           docapi="net.sf.basedb.core.log">LogManagerFactory</interfacename> 
6080 07 Aug 12 nicklas 2108           that is used throughout a single transaction. If the factory is
6080 07 Aug 12 nicklas 2109           thread-safe, the same instance can be re-used for multiple requests
6080 07 Aug 12 nicklas 2110           at the same time. Here is a list of
6080 07 Aug 12 nicklas 2111           the methods the factory must implement:
6080 07 Aug 12 nicklas 2112         </para>
6080 07 Aug 12 nicklas 2113         
6080 07 Aug 12 nicklas 2114         <variablelist>
6080 07 Aug 12 nicklas 2115           <varlistentry>
6080 07 Aug 12 nicklas 2116             <term>
6080 07 Aug 12 nicklas 2117               <methodsynopsis language="java">
6080 07 Aug 12 nicklas 2118                 <modifier>public</modifier>
6080 07 Aug 12 nicklas 2119                 <type>LogManager</type>
6080 07 Aug 12 nicklas 2120                 <methodname>getLogManager</methodname>
6080 07 Aug 12 nicklas 2121                 <methodparam>
6080 07 Aug 12 nicklas 2122                   <type>LogControl</type>
6080 07 Aug 12 nicklas 2123                   <parameter>logControl</parameter>
6080 07 Aug 12 nicklas 2124                 </methodparam>
6080 07 Aug 12 nicklas 2125               </methodsynopsis>
6080 07 Aug 12 nicklas 2126             </term>
6080 07 Aug 12 nicklas 2127             <listitem>
6080 07 Aug 12 nicklas 2128               <para>
6080 07 Aug 12 nicklas 2129               Creates a log manager for a single transaction. Since a transaction
6080 07 Aug 12 nicklas 2130               is not thread-safe the log manager implementation doesn't have to
6080 07 Aug 12 nicklas 2131               be either. The factory has the possibility to create new log managers
6080 07 Aug 12 nicklas 2132               for each transaction.
6080 07 Aug 12 nicklas 2133               </para>
6080 07 Aug 12 nicklas 2134             </listitem>
6080 07 Aug 12 nicklas 2135           </varlistentry>
6080 07 Aug 12 nicklas 2136           
6080 07 Aug 12 nicklas 2137           <varlistentry>
6080 07 Aug 12 nicklas 2138             <term>
6080 07 Aug 12 nicklas 2139               <methodsynopsis language="java">
6080 07 Aug 12 nicklas 2140                 <modifier>public</modifier>
6080 07 Aug 12 nicklas 2141                 <type>boolean</type>
6080 07 Aug 12 nicklas 2142                 <methodname>isLoggable</methodname>
6080 07 Aug 12 nicklas 2143                 <methodparam>
6080 07 Aug 12 nicklas 2144                   <type>Object</type>
6080 07 Aug 12 nicklas 2145                   <parameter>entity</parameter>
6080 07 Aug 12 nicklas 2146                 </methodparam>
6080 07 Aug 12 nicklas 2147               </methodsynopsis>
6080 07 Aug 12 nicklas 2148             </term>
6080 07 Aug 12 nicklas 2149             <listitem>
6080 07 Aug 12 nicklas 2150               <para>
6080 07 Aug 12 nicklas 2151               Checks if changes to the given entity should be
6080 07 Aug 12 nicklas 2152               logged or not. For performance reasons, it usually makes sense to 
6080 07 Aug 12 nicklas 2153               not log everything. For example, the database logger implementation 
6080 07 Aug 12 nicklas 2154               only logs changes if the entity implements the <interfacename 
6080 07 Aug 12 nicklas 2155               docapi="net.sf.basedb.core.data">LoggableData</interfacename>
6080 07 Aug 12 nicklas 2156               interface. The return value of this method should be consistent
6080 07 Aug 12 nicklas 2157               with <methodname>getEntityLogger()</methodname>.
6080 07 Aug 12 nicklas 2158               </para>
6080 07 Aug 12 nicklas 2159             </listitem>
6080 07 Aug 12 nicklas 2160           </varlistentry>
6080 07 Aug 12 nicklas 2161
6080 07 Aug 12 nicklas 2162           <varlistentry>
6080 07 Aug 12 nicklas 2163             <term>
6080 07 Aug 12 nicklas 2164               <methodsynopsis language="java">
6080 07 Aug 12 nicklas 2165                 <modifier>public</modifier>
6080 07 Aug 12 nicklas 2166                 <type>EntityLogger</type>
6080 07 Aug 12 nicklas 2167                 <methodname>getEntityLogger</methodname>
6080 07 Aug 12 nicklas 2168                 <methodparam>
6080 07 Aug 12 nicklas 2169                   <type>LogManager</type>
6080 07 Aug 12 nicklas 2170                   <parameter>logManager</parameter>
6080 07 Aug 12 nicklas 2171                 </methodparam>
6080 07 Aug 12 nicklas 2172                 <methodparam>
6080 07 Aug 12 nicklas 2173                   <type>Object</type>
6080 07 Aug 12 nicklas 2174                   <parameter>entity</parameter>
6080 07 Aug 12 nicklas 2175                 </methodparam>
6080 07 Aug 12 nicklas 2176               </methodsynopsis>
6080 07 Aug 12 nicklas 2177             </term>
6080 07 Aug 12 nicklas 2178             <listitem>
6080 07 Aug 12 nicklas 2179               <para>
6080 07 Aug 12 nicklas 2180               Create or get an entity logger that knows how to log
6080 07 Aug 12 nicklas 2181               changes to the given entity. If the entity should not be
6080 07 Aug 12 nicklas 2182               logged, <constant>null</constant> can be returned. This method
6080 07 Aug 12 nicklas 2183               is called for each modified item in the transaction.
6080 07 Aug 12 nicklas 2184               </para>
6080 07 Aug 12 nicklas 2185             </listitem>
6080 07 Aug 12 nicklas 2186           </varlistentry>
6080 07 Aug 12 nicklas 2187         </variablelist>
6080 07 Aug 12 nicklas 2188         
6080 07 Aug 12 nicklas 2189       </sect3>
6080 07 Aug 12 nicklas 2190       
6080 07 Aug 12 nicklas 2191       <sect3 id="extensions_developer.logging.manager">
6080 07 Aug 12 nicklas 2192         <title>The LogManager interface</title>
6080 07 Aug 12 nicklas 2193         
6080 07 Aug 12 nicklas 2194         <para>
6080 07 Aug 12 nicklas 2195           A new log manager is created for each transaction. The log manager
6080 07 Aug 12 nicklas 2196           is responsible for collecting all changes made in the transaction 
6080 07 Aug 12 nicklas 2197           and store those changes in the appropriate place. The interface doesn't define
6080 07 Aug 12 nicklas 2198           any methods for this collection, since each implementation may have
6080 07 Aug 12 nicklas 2199           very different needs.
6080 07 Aug 12 nicklas 2200         </para>
6080 07 Aug 12 nicklas 2201         
6080 07 Aug 12 nicklas 2202         <variablelist>
6080 07 Aug 12 nicklas 2203           <varlistentry>
6080 07 Aug 12 nicklas 2204             <term>
6080 07 Aug 12 nicklas 2205               <methodsynopsis language="java">
6080 07 Aug 12 nicklas 2206                 <modifier>public</modifier>
6080 07 Aug 12 nicklas 2207                 <type>LogControl</type>
6080 07 Aug 12 nicklas 2208                 <methodname>getLogControl</methodname>
6080 07 Aug 12 nicklas 2209               </methodsynopsis>
6080 07 Aug 12 nicklas 2210             </term>
6080 07 Aug 12 nicklas 2211             <listitem>
6080 07 Aug 12 nicklas 2212               <para>
6080 07 Aug 12 nicklas 2213               Get the log control object that was supplied by the BASE core
6080 07 Aug 12 nicklas 2214               when the transaction was started. The log controller contains
6080 07 Aug 12 nicklas 2215               methods for accessing information about the transaction, such
6080 07 Aug 12 nicklas 2216               as the logged in user, executing plug-in, etc. It can also
6080 07 Aug 12 nicklas 2217               be used to execute queries against the database to get
6080 07 Aug 12 nicklas 2218               even more information.
6080 07 Aug 12 nicklas 2219               </para>
6080 07 Aug 12 nicklas 2220               
6080 07 Aug 12 nicklas 2221               <warning>
6080 07 Aug 12 nicklas 2222                 <para>
6080 07 Aug 12 nicklas 2223                   Be careful about the queries that are executed by the log
6080 07 Aug 12 nicklas 2224                   controller. Since all logging code is executed at flush
6080 07 Aug 12 nicklas 2225                   time in callbacks from Hibernate we are not allowed to
6080 07 Aug 12 nicklas 2226                   use the regular session. Instead, all queries are sent
6080 07 Aug 12 nicklas 2227                   through the stateless session. The stateless session has no
6080 07 Aug 12 nicklas 2228                   caching functionality which means that Hibernate will use
6080 07 Aug 12 nicklas 2229                   extra queries to load associations. Our recommendation is
6080 07 Aug 12 nicklas 2230                   to avoid quires that return full entities, use scalar 
6080 07 Aug 12 nicklas 2231                   queries instead to just load the values that are needed.
6080 07 Aug 12 nicklas 2232                 </para>
6080 07 Aug 12 nicklas 2233               </warning>
6080 07 Aug 12 nicklas 2234             </listitem>
6080 07 Aug 12 nicklas 2235           </varlistentry>
6080 07 Aug 12 nicklas 2236           <varlistentry>
6080 07 Aug 12 nicklas 2237             <term>
6080 07 Aug 12 nicklas 2238               <methodsynopsis language="java">
6080 07 Aug 12 nicklas 2239                 <modifier>public</modifier>
6080 07 Aug 12 nicklas 2240                 <void/>
6080 07 Aug 12 nicklas 2241                 <methodname>afterCommit</methodname>
6080 07 Aug 12 nicklas 2242               </methodsynopsis>
6080 07 Aug 12 nicklas 2243             </term>
6080 07 Aug 12 nicklas 2244             <term>
6080 07 Aug 12 nicklas 2245               <methodsynopsis language="java">
6080 07 Aug 12 nicklas 2246                 <modifier>public</modifier>
6080 07 Aug 12 nicklas 2247                 <void/>
6080 07 Aug 12 nicklas 2248                 <methodname>afterRollback</methodname>
6080 07 Aug 12 nicklas 2249               </methodsynopsis>
6080 07 Aug 12 nicklas 2250             </term>
6080 07 Aug 12 nicklas 2251             <listitem>
6080 07 Aug 12 nicklas 2252               Called after a successful commit or after a rollback. Note
6080 07 Aug 12 nicklas 2253               that the connection to the database has been closed at this
6080 07 Aug 12 nicklas 2254               time and it is not possible to save any more information to 
6080 07 Aug 12 nicklas 2255               it at this time.
6080 07 Aug 12 nicklas 2256             </listitem>
6080 07 Aug 12 nicklas 2257           </varlistentry>
6080 07 Aug 12 nicklas 2258         </variablelist>
6080 07 Aug 12 nicklas 2259       </sect3>
6080 07 Aug 12 nicklas 2260
6080 07 Aug 12 nicklas 2261       <sect3 id="extensions_developer.logging.entitylogger">
6080 07 Aug 12 nicklas 2262         <title>The EntityLogger interface</title>
6080 07 Aug 12 nicklas 2263         
6080 07 Aug 12 nicklas 2264         <para>
6080 07 Aug 12 nicklas 2265           An entity logger is responsible for extracting the changes 
6080 07 Aug 12 nicklas 2266           made to an entity and converting it to something that is useful
6080 07 Aug 12 nicklas 2267           as a log entry. In most cases, this is not very complicated, but
6080 07 Aug 12 nicklas 2268           in some cases, a change in one entity should actually be logged
6080 07 Aug 12 nicklas 2269           as a change in a different entity. For example, changes to
6080 07 Aug 12 nicklas 2270           annotations are handled by the <classname 
6080 07 Aug 12 nicklas 2271           docapi="net.sf.basedb.core.log.db">AnnotationLogger</classname> which
6080 07 Aug 12 nicklas 2272           which log it as a change on the parent item.
6080 07 Aug 12 nicklas 2273         </para>
6080 07 Aug 12 nicklas 2274         
6080 07 Aug 12 nicklas 2275         <variablelist>
6080 07 Aug 12 nicklas 2276           <varlistentry>
6080 07 Aug 12 nicklas 2277             <term>
6080 07 Aug 12 nicklas 2278               <methodsynopsis language="java">
6080 07 Aug 12 nicklas 2279                 <modifier>public</modifier>
6080 07 Aug 12 nicklas 2280                 <void/>
6080 07 Aug 12 nicklas 2281                 <methodname>logChanges</methodname>
6080 07 Aug 12 nicklas 2282                 <methodparam>
6080 07 Aug 12 nicklas 2283                   <type>LogManager</type>
6080 07 Aug 12 nicklas 2284                   <parameter>logManager</parameter>
6080 07 Aug 12 nicklas 2285                 </methodparam>
6080 07 Aug 12 nicklas 2286                 <methodparam>
6080 07 Aug 12 nicklas 2287                   <type>EntityDetails</type>
6080 07 Aug 12 nicklas 2288                   <parameter>details</parameter>
6080 07 Aug 12 nicklas 2289                 </methodparam>
6080 07 Aug 12 nicklas 2290               </methodsynopsis>
6080 07 Aug 12 nicklas 2291             </term>
6080 07 Aug 12 nicklas 2292             <listitem>
6080 07 Aug 12 nicklas 2293               <para>
6080 07 Aug 12 nicklas 2294               This method is called whenever a change has been detected
6080 07 Aug 12 nicklas 2295               in an entity. The <varname>details</varname> variable contains
6080 07 Aug 12 nicklas 2296               information about the entity and, to a certain degree, 
6080 07 Aug 12 nicklas 2297               what changes that has been made.
6080 07 Aug 12 nicklas 2298               </para>
6080 07 Aug 12 nicklas 2299             </listitem>
6080 07 Aug 12 nicklas 2300           </varlistentry>
6080 07 Aug 12 nicklas 2301         </variablelist>
6080 07 Aug 12 nicklas 2302       </sect3>
6080 07 Aug 12 nicklas 2303       
6080 07 Aug 12 nicklas 2304     </sect2>
6080 07 Aug 12 nicklas 2305   
6080 07 Aug 12 nicklas 2306   
6048 18 Apr 12 nicklas 2307     <sect2 id="extensions_developer.overview_loader">
6048 18 Apr 12 nicklas 2308       <title>Item overview loaders</title>
6048 18 Apr 12 nicklas 2309       
6048 18 Apr 12 nicklas 2310       <para>
6048 18 Apr 12 nicklas 2311         The item overview functionality allow extensions to load more items in the tree
6048 18 Apr 12 nicklas 2312         structure. The extension point is a core extension point that is available 
6048 18 Apr 12 nicklas 2313         independently of the web client. Actions should implement the 
6048 18 Apr 12 nicklas 2314         <interfacename docapi="net.sf.basedb.util.overview.extensions">ChildNodeLoaderAction</interfacename>
6048 18 Apr 12 nicklas 2315         interface. We recommend that the actions also extend the 
6048 18 Apr 12 nicklas 2316         <classname docapi="net.sf.basedb.util.overview.loader">BasicItemNodeLoader</classname>
6048 18 Apr 12 nicklas 2317         since this will make it easier to handle situations with missing items, permission
6048 18 Apr 12 nicklas 2318         problems and validation. Since each registered extension is checked for each item
6048 18 Apr 12 nicklas 2319         in the overview we recommend that the action factory makes a first filtering step
6048 18 Apr 12 nicklas 2320         before an action is created. This should be relatively simple since the current
6048 18 Apr 12 nicklas 2321         item in the <classname>ClientContext</classname> is the parent node. For example:
6048 18 Apr 12 nicklas 2322       </para>
6048 18 Apr 12 nicklas 2323       
6048 18 Apr 12 nicklas 2324       <programlisting language="java">
6048 18 Apr 12 nicklas 2325 <![CDATA[
6048 18 Apr 12 nicklas 2326 // From the ActionFactory interface
6048 18 Apr 12 nicklas 2327 public boolean prepareContext(InvokationContext<? super ChildNodeLoaderAction> context) 
6048 18 Apr 12 nicklas 2328 {
6048 18 Apr 12 nicklas 2329    Node parentNode = (Node)context.getClientContext().getCurrentItem();
6048 18 Apr 12 nicklas 2330    if (parentNode != null)
6048 18 Apr 12 nicklas 2331    {
6048 18 Apr 12 nicklas 2332       if (parentNode.getItem() instanceof Ownable)
6048 18 Apr 12 nicklas 2333       {
6048 18 Apr 12 nicklas 2334          return true;
6048 18 Apr 12 nicklas 2335       }
6048 18 Apr 12 nicklas 2336    }
6048 18 Apr 12 nicklas 2337    return false;
6048 18 Apr 12 nicklas 2338 }
6048 18 Apr 12 nicklas 2339 ]]>
6048 18 Apr 12 nicklas 2340 </programlisting>
6048 18 Apr 12 nicklas 2341       
6048 18 Apr 12 nicklas 2342     </sect2>
5640 24 May 11 nicklas 2343     
6048 18 Apr 12 nicklas 2344     <sect2 id="extensions_developer.overview_validator">
6048 18 Apr 12 nicklas 2345       <title>Item overview validation</title>
6048 18 Apr 12 nicklas 2346       
6048 18 Apr 12 nicklas 2347       <para>
6048 18 Apr 12 nicklas 2348         The item overview functionality allow extensions to add validation code
6048 18 Apr 12 nicklas 2349         to any item in the tree. There are two co-existing extension points, one
6048 18 Apr 12 nicklas 2350         for the actual validation code and one for the validation rule defintions.
6048 18 Apr 12 nicklas 2351         Both extension points are core extension points that is available 
6048 18 Apr 12 nicklas 2352         independently of the web client. Validation actions should implement the 
6048 18 Apr 12 nicklas 2353         <interfacename docapi="net.sf.basedb.util.overview.extensions">NodeValidatorAction</interfacename>
6048 18 Apr 12 nicklas 2354         interface, which is simple the same as <interfacename docapi="net.sf.basedb.util.overview.validator">NodeValidator</interfacename>
6048 18 Apr 12 nicklas 2355         We recommend that the actions extend the 
6048 18 Apr 12 nicklas 2356         <classname docapi="net.sf.basedb.util.overview.validator">NameableNodeValidator</classname>
6048 18 Apr 12 nicklas 2357         or <classname docapi="net.sf.basedb.util.overview.validator">BasicNodeValidator</classname>
6048 18 Apr 12 nicklas 2358         since this will make it easier to handle situations with missing items and permission
6048 18 Apr 12 nicklas 2359         problems. Since each registered extension is checked for each item
6048 18 Apr 12 nicklas 2360         in the overview we recommend that the action factory makes a first filtering step
6048 18 Apr 12 nicklas 2361         before an action is created. This should be relatively simple since the current
6048 18 Apr 12 nicklas 2362         item in the <classname>ClientContext</classname> is type of that should be validated.
6048 18 Apr 12 nicklas 2363         For example:
6048 18 Apr 12 nicklas 2364       </para>
6048 18 Apr 12 nicklas 2365       
6048 18 Apr 12 nicklas 2366       <programlisting language="java">
6048 18 Apr 12 nicklas 2367 <![CDATA[
6048 18 Apr 12 nicklas 2368 // From the ActionFactory interface
6048 18 Apr 12 nicklas 2369 public boolean prepareContext(InvokationContext<? super NodeValidatorAction> context) 
6048 18 Apr 12 nicklas 2370 {
6048 18 Apr 12 nicklas 2371    return context.getClientContext().getCurrentItem() == Item.USER;
6048 18 Apr 12 nicklas 2372 }
6048 18 Apr 12 nicklas 2373 ]]>
6048 18 Apr 12 nicklas 2374 </programlisting>
6048 18 Apr 12 nicklas 2375
6048 18 Apr 12 nicklas 2376       <para>
6048 18 Apr 12 nicklas 2377         Rule definition actions should implement the <interfacename 
6048 18 Apr 12 nicklas 2378         docapi="net.sf.basedb.util.overview.extensions">ValidationRuleAction</interfacename>. 
6048 18 Apr 12 nicklas 2379         This is simply a container with some information about the validation rule, such as
6048 18 Apr 12 nicklas 2380         a title, description and a default severity level. The 
6048 18 Apr 12 nicklas 2381         <classname docapi="net.sf.basedb.util.overview">Validator</classname> class
6048 18 Apr 12 nicklas 2382         that ships with BASE already implements this interface. The <classname 
6048 18 Apr 12 nicklas 2383         docapi="net.sf.basedb.util.overview.extensions">ReflectValidationRuleActionFactory</classname>
6048 18 Apr 12 nicklas 2384         can be used to return an existing <code>public static final</code> rule definition as an 
6048 18 Apr 12 nicklas 2385         action:
6048 18 Apr 12 nicklas 2386       </para>
6048 18 Apr 12 nicklas 2387       
6048 18 Apr 12 nicklas 2388       <programlisting language="xml">
6048 18 Apr 12 nicklas 2389 <![CDATA[
6048 18 Apr 12 nicklas 2390 <extension
6048 18 Apr 12 nicklas 2391    id="validationrule.invalid-url"
6048 18 Apr 12 nicklas 2392    extends="net.sf.basedb.util.overview.validationrule">
6048 18 Apr 12 nicklas 2393    <index>4</index>
6048 18 Apr 12 nicklas 2394    <about>
6048 18 Apr 12 nicklas 2395       <name>Invalid URL</name>
6048 18 Apr 12 nicklas 2396       <description>Checks if an URL has a valid syntax.</description>
6048 18 Apr 12 nicklas 2397    </about>
6048 18 Apr 12 nicklas 2398    <action-factory>
6048 18 Apr 12 nicklas 2399       <factory-class>
6048 18 Apr 12 nicklas 2400          net.sf.basedb.util.overview.extensions.ReflectValidationRuleActionFactory
6048 18 Apr 12 nicklas 2401       </factory-class>
6048 18 Apr 12 nicklas 2402       <parameters>
6048 18 Apr 12 nicklas 2403          <field>net.sf.basedb.examples.extensions.overview.OwnerValidator.INVALID_URL</field>
6048 18 Apr 12 nicklas 2404       </parameters>
6048 18 Apr 12 nicklas 2405    </action-factory>
6048 18 Apr 12 nicklas 2406 </extension>
6048 18 Apr 12 nicklas 2407 ]]>
6048 18 Apr 12 nicklas 2408 </programlisting>
6048 18 Apr 12 nicklas 2409       
6048 18 Apr 12 nicklas 2410     </sect2>
6048 18 Apr 12 nicklas 2411     
6052 23 Apr 12 nicklas 2412     <sect2 id="extensions_developer.overview_information">
6052 23 Apr 12 nicklas 2413       <title>Item overview information</title>
6052 23 Apr 12 nicklas 2414       
6052 23 Apr 12 nicklas 2415       <para>
6052 23 Apr 12 nicklas 2416         The item overview functionality allow extensions to display additional information
6052 23 Apr 12 nicklas 2417         about the currently selected node in the right pane in the web interface. 
6052 23 Apr 12 nicklas 2418         Each <interfacename docapi="net.sf.basedb.clients.web.extensions.section">SectionAction</interfacename> 
6052 23 Apr 12 nicklas 2419         object that is created by extensions will result in an additional section in the
6052 23 Apr 12 nicklas 2420         GUI. Note that all extension factories are called for all nodes. The
6052 23 Apr 12 nicklas 2421         <methodname>ActionFactory.prepareContext()</methodname> should be used to enable/disable
6052 23 Apr 12 nicklas 2422         the extension depending on the node that is selected. BASE ships with the
6052 23 Apr 12 nicklas 2423         <classname docapi="net.sf.basedb.clients.web.extensions.section">IncludeContentSectionFactory</classname>
6052 23 Apr 12 nicklas 2424         factory implementation which allows a resourse (eg. another JSP script) to generate
6052 23 Apr 12 nicklas 2425         the content of the section. The current context is stored in a request-scoped
6052 23 Apr 12 nicklas 2426         attribute under the key given by <code>JspContext.ATTRIBUTE_KEY</code>. 
6052 23 Apr 12 nicklas 2427         A JSP or servlet should use this to hook into the current flow. Here is a code example:
6052 23 Apr 12 nicklas 2428       </para>
6052 23 Apr 12 nicklas 2429       
6052 23 Apr 12 nicklas 2430       <programlisting language="java">
6052 23 Apr 12 nicklas 2431 <![CDATA[
6052 23 Apr 12 nicklas 2432 // Get the JspContext that was created on the main edit page
6052 23 Apr 12 nicklas 2433 final JspContext jspContext = (JspContext)request.getAttribute(JspContext.ATTRIBUTE_KEY);
6052 23 Apr 12 nicklas 2434
6052 23 Apr 12 nicklas 2435 // The currently selected node is found in the context.
6052 23 Apr 12 nicklas 2436 final Node node = (Node)jspContext.getCurrentItem();
6052 23 Apr 12 nicklas 2437
6052 23 Apr 12 nicklas 2438 // Get the DbControl and SessionControl used to handle the request (do not close!)
6052 23 Apr 12 nicklas 2439 final DbControl dc = jspContext.getDbControl();
6052 23 Apr 12 nicklas 2440 final SessionControl sc = dc.getSessionControl();
6052 23 Apr 12 nicklas 2441 ]]>
6052 23 Apr 12 nicklas 2442 </programlisting>
6052 23 Apr 12 nicklas 2443         
6052 23 Apr 12 nicklas 2444     </sect2>
6052 23 Apr 12 nicklas 2445     
6052 23 Apr 12 nicklas 2446     
6050 19 Apr 12 nicklas 2447     <sect2 id="extensions_developer.list_column">
6050 19 Apr 12 nicklas 2448       <title>Table list columns</title>
6050 19 Apr 12 nicklas 2449       
6050 19 Apr 12 nicklas 2450       <para>
6050 19 Apr 12 nicklas 2451         This extension point makes it possible to add more columns to most major list pages
6050 19 Apr 12 nicklas 2452         in the web interface. Actions should implement the <interfacename 
6050 19 Apr 12 nicklas 2453         docapi="net.sf.basedb.clients.web.extensions.list">ListColumnAction</interfacename> interface.
6050 19 Apr 12 nicklas 2454         This interface contains several methods which can be grouped into three main types:
6050 19 Apr 12 nicklas 2455       </para>
6050 19 Apr 12 nicklas 2456
6050 19 Apr 12 nicklas 2457       <itemizedlist>
6050 19 Apr 12 nicklas 2458         <listitem>
6050 19 Apr 12 nicklas 2459           <para>
6050 19 Apr 12 nicklas 2460             Metadata methods, for example, the id and title of the column and if the column
6050 19 Apr 12 nicklas 2461             can be sorted, filtered, etc.
6050 19 Apr 12 nicklas 2462           </para>
6050 19 Apr 12 nicklas 2463         </listitem>
6050 19 Apr 12 nicklas 2464         
6050 19 Apr 12 nicklas 2465         <listitem>
6050 19 Apr 12 nicklas 2466           <para>
6050 19 Apr 12 nicklas 2467             Rendering information, for example, CSS class and style information that is 
6050 19 Apr 12 nicklas 2468             used for the column header.
6050 19 Apr 12 nicklas 2469           </para>
6050 19 Apr 12 nicklas 2470         </listitem>
6050 19 Apr 12 nicklas 2471         
6050 19 Apr 12 nicklas 2472         <listitem>
6050 19 Apr 12 nicklas 2473           <para>
6050 19 Apr 12 nicklas 2474             Worker methods, that retrieve the value from the current item and format
6050 19 Apr 12 nicklas 2475             it for proper display. Different methods are used for the web display
6050 19 Apr 12 nicklas 2476             and for exporting to a file.
6050 19 Apr 12 nicklas 2477           </para>
6050 19 Apr 12 nicklas 2478         </listitem>
6050 19 Apr 12 nicklas 2479       </itemizedlist>
6050 19 Apr 12 nicklas 2480       
6050 19 Apr 12 nicklas 2481       <para>
6050 19 Apr 12 nicklas 2482         The <classname docapi="net.sf.basedb.clients.web.extensions.list">AbstractListColumnBean</classname>
6050 19 Apr 12 nicklas 2483         class provides a bean-like implementation for all methods except the <methodname>getValue()</methodname>
6050 19 Apr 12 nicklas 2484         method. Extending from this class makes it easy to your own implementations. BASE ships with the
6050 19 Apr 12 nicklas 2485         <classname docapi="net.sf.basedb.clients.web.extensions.list">PropertyPathActionFactory</classname>
6050 19 Apr 12 nicklas 2486         factory that can be used without coding if the added column can be expressed as a property path that
6050 19 Apr 12 nicklas 2487         can be handled by the <classname docapi="net.sf.basedb.core">Metadata</classname> class.
7982 14 Jun 21 nicklas 2488         As usual, see the <ulink url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.examplecode">example code</ulink> 
6050 19 Apr 12 nicklas 2489         for some examples.
6050 19 Apr 12 nicklas 2490       </para>
6050 19 Apr 12 nicklas 2491       
6050 19 Apr 12 nicklas 2492     </sect2>
6048 18 Apr 12 nicklas 2493     
7915 24 Feb 21 nicklas 2494     <sect2 id="extensions_developer.query_filters">
7915 24 Feb 21 nicklas 2495       <title>Query filters</title>
7915 24 Feb 21 nicklas 2496       
7915 24 Feb 21 nicklas 2497       <para>
7915 24 Feb 21 nicklas 2498         This extension point makes it possible to extend filtering
7915 24 Feb 21 nicklas 2499         functionality for queries that are generated by list pages via the
7915 24 Feb 21 nicklas 2500         <methodname>ItemContext.configureQuery()</methodname> method in the 
7915 24 Feb 21 nicklas 2501         <classname docapi="net.sf.basedb.core">ItemContext</classname> class.
7915 24 Feb 21 nicklas 2502         
7915 24 Feb 21 nicklas 2503         Actions should implement the <interfacename 
7915 24 Feb 21 nicklas 2504         docapi="net.sf.basedb.core.query">QueryFilterAction</interfacename> 
7915 24 Feb 21 nicklas 2505         interface. This interface allows an extension to filter a query based
7915 24 Feb 21 nicklas 2506         on a single column filter, a filter row or a combination of everything.
7915 24 Feb 21 nicklas 2507       </para>
7915 24 Feb 21 nicklas 2508       
7915 24 Feb 21 nicklas 2509       <para>
7915 24 Feb 21 nicklas 2510         Note that the <methodname>ActionFactory.prepareContext()</methodname> is
7915 24 Feb 21 nicklas 2511         called for all filter extensions at all times. It is recommended that 
7915 24 Feb 21 nicklas 2512         the implementation checks the current context for the type of items in the
7915 24 Feb 21 nicklas 2513         list and if there is a filter in a column that the extension should handle.
7915 24 Feb 21 nicklas 2514         An extension may override the default implementation of any filter, but this
7915 24 Feb 21 nicklas 2515         is not recommended. The recommended design is to combine the filter
7915 24 Feb 21 nicklas 2516         extension with a custom column that uses the <code>!x.</code> prefix
7915 24 Feb 21 nicklas 2517         as the column id. Here is an example from the Variant Search extension 
7982 14 Jun 21 nicklas 2518         (<ulink url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.varsearch"
7982 14 Jun 21 nicklas 2519         >https://baseplugins.thep.lu.se/wiki/net.sf.basedb.varsearch</ulink>):
7915 24 Feb 21 nicklas 2520       </para>
7915 24 Feb 21 nicklas 2521       
7915 24 Feb 21 nicklas 2522       <programlisting language="java">
7915 24 Feb 21 nicklas 2523 <![CDATA[
7915 24 Feb 21 nicklas 2524 public boolean prepareContext(InvokationContext<? super QueryFilterAction> context) 
7915 24 Feb 21 nicklas 2525 {
7915 24 Feb 21 nicklas 2526    // Enabled in the RAWBIOASSAY list page
7915 24 Feb 21 nicklas 2527    // and if the !x.lucene column is present with a filter
7915 24 Feb 21 nicklas 2528    // and if the service database is running
7915 24 Feb 21 nicklas 2529    ItemContext ctx = context.getClientContext().getCurrentItem();
7915 24 Feb 21 nicklas 2530    return ctx.getItemType() == Item.RAWBIOASSAY && 
7915 24 Feb 21 nicklas 2531       ctx.hasExtensionFilter("lucene") && 
7915 24 Feb 21 nicklas 2532       VarSearchService.getInstance().isRunning();
7915 24 Feb 21 nicklas 2533 }
7915 24 Feb 21 nicklas 2534 ]]>
7915 24 Feb 21 nicklas 2535 </programlisting>
7915 24 Feb 21 nicklas 2536       
7915 24 Feb 21 nicklas 2537       
7915 24 Feb 21 nicklas 2538     </sect2>
7915 24 Feb 21 nicklas 2539     
6429 10 Mar 14 nicklas 2540     <sect2 id="extensions_developer.login-manager">
6429 10 Mar 14 nicklas 2541       <title>Login manager</title>
6429 10 Mar 14 nicklas 2542       <para>
6429 10 Mar 14 nicklas 2543         This extension point makes it possible to authenticate users by some other means than
6429 10 Mar 14 nicklas 2544         the regular internal username+password authentication. Authentication managers should
6429 10 Mar 14 nicklas 2545         implement the <classname docapi="net.sf.basedb.core.authentication">AuthenticationManager</classname>
7543 06 Dec 18 nicklas 2546         action interface. This interface is simple and the only method that is required to implement
7543 06 Dec 18 nicklas 2547         is the parameter-less <methodname>authenticate()</methodname> method. There are three outcomes:
6429 10 Mar 14 nicklas 2548       </para>
6429 10 Mar 14 nicklas 2549       
6429 10 Mar 14 nicklas 2550       <itemizedlist>
6429 10 Mar 14 nicklas 2551         <listitem>
6429 10 Mar 14 nicklas 2552           <para>A <classname docapi="net.sf.basedb.core.authentication">AuthenticatedUser</classname>
6429 10 Mar 14 nicklas 2553           is returned with information about a user that has passed authentication.
6429 10 Mar 14 nicklas 2554           </para>
6429 10 Mar 14 nicklas 2555         </listitem>
6429 10 Mar 14 nicklas 2556         
6429 10 Mar 14 nicklas 2557         <listitem>
6429 10 Mar 14 nicklas 2558           <para>A <constant>null</constant> value is returned to indicate that the manager could
6429 10 Mar 14 nicklas 2559           not determine if the login credentials are valid or not. The BASE core may try another
6429 10 Mar 14 nicklas 2560           authentication manager or use internal authentication.
6429 10 Mar 14 nicklas 2561           </para>
6429 10 Mar 14 nicklas 2562         </listitem>
6429 10 Mar 14 nicklas 2563         
6429 10 Mar 14 nicklas 2564         <listitem>
6429 10 Mar 14 nicklas 2565           <para>An exception is thrown to indicate that the manager has determined that
6429 10 Mar 14 nicklas 2566           the login credentials are invalid.
6429 10 Mar 14 nicklas 2567           </para>
6429 10 Mar 14 nicklas 2568         </listitem>
6429 10 Mar 14 nicklas 2569         
6429 10 Mar 14 nicklas 2570       </itemizedlist>
6429 10 Mar 14 nicklas 2571       
6429 10 Mar 14 nicklas 2572       <para>
6429 10 Mar 14 nicklas 2573         Since the action interface doesn't contain any parameters that contain information about the 
6429 10 Mar 14 nicklas 2574         login request, the implementation need to get this from the <classname 
6429 10 Mar 14 nicklas 2575         docapi="net.sf.basedb.util.extensions">ClientContext</classname> that is passed to the 
6429 10 Mar 14 nicklas 2576         action factory. The <methodname>getCurrentItem()</methodname> item is a <classname 
6429 10 Mar 14 nicklas 2577         docapi="net.sf.basedb.core.authentication">LoginRequest</classname> containing the login and
6429 10 Mar 14 nicklas 2578         password the user entered on the login page. The <classname>ClientContext</classname>
6429 10 Mar 14 nicklas 2579         ojbect can be cast to <classname docapi="net.sf.basedb.core">AuthenticationContext</classname>
6429 10 Mar 14 nicklas 2580         which provide some extra services to the authentication manager.
6429 10 Mar 14 nicklas 2581       </para>
6429 10 Mar 14 nicklas 2582       
7543 06 Dec 18 nicklas 2583       <sect3 id="extensions_developer.login-manager.multiple">
7543 06 Dec 18 nicklas 2584         <title>Supporting multiple installed login managers</title>
7543 06 Dec 18 nicklas 2585         
7543 06 Dec 18 nicklas 2586         <para>
7543 06 Dec 18 nicklas 2587           As of BASE 3.14 it should be easier to support server configurations that
7543 06 Dec 18 nicklas 2588           include multiple login manages. The <code>login-form</code> attribute in the
7543 06 Dec 18 nicklas 2589           <classname>LoginRequest</classname> parameter contains the login form
7543 06 Dec 18 nicklas 2590           that was used by the user. A login manager should check this value 
7543 06 Dec 18 nicklas 2591           to decide if the login request should be handled or not. Note that 
7543 06 Dec 18 nicklas 2592           the value may be missing.
7543 06 Dec 18 nicklas 2593         </para>
7543 06 Dec 18 nicklas 2594         
7543 06 Dec 18 nicklas 2595         <para>
7543 06 Dec 18 nicklas 2596           The <classname docapi="net.sf.basedb.core.authentication">AuthenticationManager</classname>
7543 06 Dec 18 nicklas 2597           interface also includes an optional method, 
7543 06 Dec 18 nicklas 2598           <methodname>vetoAuthenticatedUser(UserData, AuthenticatedUser)</methodname>. This method
7543 06 Dec 18 nicklas 2599           is only called if one of the installed login manager authenticated the user successfully. 
7543 06 Dec 18 nicklas 2600           Then, all other installed login managers get a chance to raise a veto by throwing an
7543 06 Dec 18 nicklas 2601           exception from this method. A responsible login manager probably need to implement this
7543 06 Dec 18 nicklas 2602           method to detect if a user that is supposed to login with a specific method is trying to
7543 06 Dec 18 nicklas 2603           login with some other method. Examples of actual implementations can be found in the
7543 06 Dec 18 nicklas 2604           the <ulink 
7982 14 Jun 21 nicklas 2605           url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.yubikey">YubiKey</ulink>
7543 06 Dec 18 nicklas 2606           and <ulink 
7982 14 Jun 21 nicklas 2607           url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.otp">OTP</ulink> extensions.
7543 06 Dec 18 nicklas 2608         </para>
7543 06 Dec 18 nicklas 2609         
7543 06 Dec 18 nicklas 2610       </sect3>
7543 06 Dec 18 nicklas 2611       
6429 10 Mar 14 nicklas 2612       <sect3 id="extensions_developer.login-manager.internal-vs-external">
6429 10 Mar 14 nicklas 2613         <title>Internal vs. external authentation</title>
6429 10 Mar 14 nicklas 2614       
6429 10 Mar 14 nicklas 2615         <para>
6685 20 Jan 15 nicklas 2616           All login requests are always sent to registered authentication
6429 10 Mar 14 nicklas 2617           managers first. Internal authentication is only used if no authentication 
6429 10 Mar 14 nicklas 2618           manager could validate the user. Even with external authentication it is possible to 
6429 10 Mar 14 nicklas 2619           let BASE cache the logins/passwords. This makes it possible to login to 
6429 10 Mar 14 nicklas 2620           BASE if the external authentication server is down.
6429 10 Mar 14 nicklas 2621         </para>
6429 10 Mar 14 nicklas 2622         
6429 10 Mar 14 nicklas 2623         <note>
6429 10 Mar 14 nicklas 2624           <para>
6429 10 Mar 14 nicklas 2625           An external authentication server can only be used to grant or deny 
6429 10 Mar 14 nicklas 2626           a user access to BASE. It cannot be used to give a user permissions,
6429 10 Mar 14 nicklas 2627           or put a user into groups or different roles inside BASE.
6429 10 Mar 14 nicklas 2628           </para>
6429 10 Mar 14 nicklas 2629         </note>
6429 10 Mar 14 nicklas 2630
6429 10 Mar 14 nicklas 2631         <para>
6429 10 Mar 14 nicklas 2632           The authentication process goes something like this:
6429 10 Mar 14 nicklas 2633           
6429 10 Mar 14 nicklas 2634           <itemizedlist>
6429 10 Mar 14 nicklas 2635           <listitem>
6429 10 Mar 14 nicklas 2636             <para>
6429 10 Mar 14 nicklas 2637               An external authentication manager determines that the login request
6429 10 Mar 14 nicklas 2638               is valid and the user is already known to BASE.
6429 10 Mar 14 nicklas 2639               If the extra information (name, email, phone, etc.) is supplied
6429 10 Mar 14 nicklas 2640               and the <property>auth.synchronize</property> setting
6429 10 Mar 14 nicklas 2641               is <constant>TRUE</constant> the extra information is copied to 
6429 10 Mar 14 nicklas 2642               the BASE server.
6429 10 Mar 14 nicklas 2643             </para>
6429 10 Mar 14 nicklas 2644           </listitem>
6429 10 Mar 14 nicklas 2645           
6429 10 Mar 14 nicklas 2646           <listitem>
6429 10 Mar 14 nicklas 2647             <para>
6429 10 Mar 14 nicklas 2648               An external authentication manager determines that the login request
6429 10 Mar 14 nicklas 2649               is valid, but the user is not known to BASE. This happens
6429 10 Mar 14 nicklas 2650               the first time a user logs in. BASE will create
6429 10 Mar 14 nicklas 2651               a new user account. If the authentication manager provides extra information, it 
6429 10 Mar 14 nicklas 2652               is copied to the BASE server (even if <property>auth.synchronize</property> 
6429 10 Mar 14 nicklas 2653               is not set). The new user account will get the default quota 
6429 10 Mar 14 nicklas 2654               and be added to the all roles and groups which has been
6429 10 Mar 14 nicklas 2655               marked as <emphasis>default</emphasis>.
6429 10 Mar 14 nicklas 2656             </para>
6429 10 Mar 14 nicklas 2657           </listitem>
6429 10 Mar 14 nicklas 2658
6429 10 Mar 14 nicklas 2659           <listitem>
6429 10 Mar 14 nicklas 2660             <para>
6429 10 Mar 14 nicklas 2661               If password caching is enabled, the password is copied to BASE. 
6429 10 Mar 14 nicklas 2662               If an expiration timeout has been set, an expiration date
6429 10 Mar 14 nicklas 2663               will be calculated and set on the user account. The expiration
6429 10 Mar 14 nicklas 2664               date is only checked when the external authentication server is 
6429 10 Mar 14 nicklas 2665               down.
6429 10 Mar 14 nicklas 2666             </para>
6429 10 Mar 14 nicklas 2667           </listitem>
6429 10 Mar 14 nicklas 2668
6429 10 Mar 14 nicklas 2669           <listitem>
6429 10 Mar 14 nicklas 2670             <para>
6429 10 Mar 14 nicklas 2671               The external authentication manager says that the login is invalid or 
6429 10 Mar 14 nicklas 2672               the password is incorrect. The user will not be logged in. 
6429 10 Mar 14 nicklas 2673             </para>
6429 10 Mar 14 nicklas 2674           </listitem>
6429 10 Mar 14 nicklas 2675           
6429 10 Mar 14 nicklas 2676           <listitem>
6429 10 Mar 14 nicklas 2677             <para>
6429 10 Mar 14 nicklas 2678               The authentication manager says that something else is wrong. 
6429 10 Mar 14 nicklas 2679               If password caching is enabled, internal authentication will be 
6429 10 Mar 14 nicklas 2680               used. Otherwise the user will not be logged in.
6429 10 Mar 14 nicklas 2681             </para>
6429 10 Mar 14 nicklas 2682           </listitem>
6429 10 Mar 14 nicklas 2683           </itemizedlist>
6429 10 Mar 14 nicklas 2684           
6429 10 Mar 14 nicklas 2685         </para>
6429 10 Mar 14 nicklas 2686       </sect3>
6429 10 Mar 14 nicklas 2687       
8045 03 Jun 22 nicklas 2688       <sect3 id="extensions_developer.login-manager.settings">
6429 10 Mar 14 nicklas 2689         <title>Configuration settings</title>
6429 10 Mar 14 nicklas 2690       
6429 10 Mar 14 nicklas 2691         <para>
6429 10 Mar 14 nicklas 2692           The configuration settings for the authentication system are located 
6429 10 Mar 14 nicklas 2693           in the <filename>base.config</filename> file. 
6429 10 Mar 14 nicklas 2694           Here is an overview of the settings. For more information read 
6429 10 Mar 14 nicklas 2695           <xref linkend="appendix.base.config.authentication" />.
6429 10 Mar 14 nicklas 2696         </para>
6429 10 Mar 14 nicklas 2697         
6429 10 Mar 14 nicklas 2698         <variablelist>
6429 10 Mar 14 nicklas 2699         <varlistentry>
6429 10 Mar 14 nicklas 2700           <term><property>auth.synchronize</property></term>
6429 10 Mar 14 nicklas 2701           <listitem>
6429 10 Mar 14 nicklas 2702             <para>
6429 10 Mar 14 nicklas 2703             If extra user information is synchronized at login time or not. 
6429 10 Mar 14 nicklas 2704             This setting is ignored if the driver does not support extra information. 
6429 10 Mar 14 nicklas 2705             </para>
6429 10 Mar 14 nicklas 2706           </listitem>
6429 10 Mar 14 nicklas 2707         </varlistentry>
6429 10 Mar 14 nicklas 2708         
6429 10 Mar 14 nicklas 2709         <varlistentry>
6429 10 Mar 14 nicklas 2710           <term><property>auth.cachepasswords</property></term>
6429 10 Mar 14 nicklas 2711           <listitem>
6429 10 Mar 14 nicklas 2712             <para>
6429 10 Mar 14 nicklas 2713               If passwords should be cached by BASE or not. If the passwords are 
6429 10 Mar 14 nicklas 2714               cached a user may login to BASE even if the external authentication 
6429 10 Mar 14 nicklas 2715               server is down.
6429 10 Mar 14 nicklas 2716             </para>
6429 10 Mar 14 nicklas 2717           </listitem>
6429 10 Mar 14 nicklas 2718         </varlistentry>
6429 10 Mar 14 nicklas 2719         
6429 10 Mar 14 nicklas 2720         <varlistentry>
6429 10 Mar 14 nicklas 2721           <term><property>auth.daystocache</property></term>
6429 10 Mar 14 nicklas 2722           <listitem>
6429 10 Mar 14 nicklas 2723             <para>
6429 10 Mar 14 nicklas 2724               How many days to cache the passwords if caching has been enabled. 
6429 10 Mar 14 nicklas 2725               A value of 0 caches the passwords for ever.      
6429 10 Mar 14 nicklas 2726             </para>
6429 10 Mar 14 nicklas 2727           </listitem>
6429 10 Mar 14 nicklas 2728         </varlistentry>
6429 10 Mar 14 nicklas 2729         </variablelist>
6429 10 Mar 14 nicklas 2730       </sect3>
6429 10 Mar 14 nicklas 2731       
6429 10 Mar 14 nicklas 2732     </sect2>
6429 10 Mar 14 nicklas 2733     
6429 10 Mar 14 nicklas 2734     <sect2 id="extensions_developer.login-form">
6429 10 Mar 14 nicklas 2735       <title>Login form</title>
6429 10 Mar 14 nicklas 2736       
6429 10 Mar 14 nicklas 2737       <para>
6429 10 Mar 14 nicklas 2738         This extension point is typically used in combination with a login manager to provide a
6429 10 Mar 14 nicklas 2739         customized login form. Extensions should implement the <interfacename 
6429 10 Mar 14 nicklas 2740         docapi="net.sf.basedb.clients.web.extensions.login">LoginFormAction</interfacename>
6429 10 Mar 14 nicklas 2741         action which is used to specify prompts, tooltips, help texts and styling information
6429 10 Mar 14 nicklas 2742         for the login and password fields. The extension point supports custom scripts and stylesheets.
6429 10 Mar 14 nicklas 2743       </para>
6429 10 Mar 14 nicklas 2744       
6429 10 Mar 14 nicklas 2745       <note>
7543 06 Dec 18 nicklas 2746         <title>As of BASE 3.14 it is possible to install multiple login managers</title>
6429 10 Mar 14 nicklas 2747         <para>
7543 06 Dec 18 nicklas 2748           All installed and enabled login forms are available in a selection list
8045 03 Jun 22 nicklas 2749           from which the user can select to switch to another login form. Since BASE 3.19.3
8045 03 Jun 22 nicklas 2750           custom scripts and stylesheets are only loaded for the currently active form.
8045 03 Jun 22 nicklas 2751           In earlier BASE versions, custom scripts and stylesheets were loaded for all installed 
8045 03 Jun 22 nicklas 2752           login forms.
6429 10 Mar 14 nicklas 2753         </para>
7543 06 Dec 18 nicklas 2754         <para>
8045 03 Jun 22 nicklas 2755           It is possible for both style sheets and scripts to verify that they are only used on
8045 03 Jun 22 nicklas 2756           the intended login form. BASE is setting two data-attributes on the 
7543 06 Dec 18 nicklas 2757           <sgmltag class="starttag">body</sgmltag> tag:
7543 06 Dec 18 nicklas 2758         </para>
7543 06 Dec 18 nicklas 2759         
7543 06 Dec 18 nicklas 2760         <variablelist>
7543 06 Dec 18 nicklas 2761         <varlistentry>
7543 06 Dec 18 nicklas 2762           <term><property>data-login-form</property></term>
7543 06 Dec 18 nicklas 2763           <listitem>
7543 06 Dec 18 nicklas 2764             <para>
7543 06 Dec 18 nicklas 2765             The ID of the currently active login form.
7543 06 Dec 18 nicklas 2766             </para>
7543 06 Dec 18 nicklas 2767           </listitem>
7543 06 Dec 18 nicklas 2768         </varlistentry>
7543 06 Dec 18 nicklas 2769         <varlistentry>
7543 06 Dec 18 nicklas 2770           <term><property>data-requested-form</property></term>
7543 06 Dec 18 nicklas 2771           <listitem>
7543 06 Dec 18 nicklas 2772             <para>
7543 06 Dec 18 nicklas 2773             The ID of the login form that was requested. This may differ from the currently active
7543 06 Dec 18 nicklas 2774             if it is not installed or enabled.
7543 06 Dec 18 nicklas 2775             </para>
7543 06 Dec 18 nicklas 2776           </listitem>
7543 06 Dec 18 nicklas 2777         </varlistentry>
7543 06 Dec 18 nicklas 2778         </variablelist>
7543 06 Dec 18 nicklas 2779         
7543 06 Dec 18 nicklas 2780         <para>
7543 06 Dec 18 nicklas 2781           In CSS files, rules that are targeting elements on the login form should match
7543 06 Dec 18 nicklas 2782           against the <sgmltag class="attribute">data-login-form</sgmltag> attribute in the selector,
7543 06 Dec 18 nicklas 2783           for example:
7543 06 Dec 18 nicklas 2784         </para>
7543 06 Dec 18 nicklas 2785         
7543 06 Dec 18 nicklas 2786         <programlisting language="css">
7543 06 Dec 18 nicklas 2787 /* Example from the YubiKey login form */
7543 06 Dec 18 nicklas 2788 body[data-login-form="net.sf.basedb.yubikey.login-form"] 
7543 06 Dec 18 nicklas 2789    #loginform #login-row th
7543 06 Dec 18 nicklas 2790 {
7543 06 Dec 18 nicklas 2791    background-image: url('../images/yubico.png');
7543 06 Dec 18 nicklas 2792    background-position: right center;
7543 06 Dec 18 nicklas 2793    background-repeat: no-repeat;
7543 06 Dec 18 nicklas 2794    padding-right: 20px;
7543 06 Dec 18 nicklas 2795 }
7543 06 Dec 18 nicklas 2796 </programlisting>
7543 06 Dec 18 nicklas 2797         
7543 06 Dec 18 nicklas 2798         <para>
7543 06 Dec 18 nicklas 2799           Scripts should also check the value of this attribute before doing stuff:
7543 06 Dec 18 nicklas 2800         </para>
7543 06 Dec 18 nicklas 2801         <programlisting language="javascript">
7543 06 Dec 18 nicklas 2802 /* Examle from the OTP login form */
7543 06 Dec 18 nicklas 2803 if (Data.get(document.body, 'login-form') != 'net.sf.basedb.otp.login-form') 
7543 06 Dec 18 nicklas 2804 {
7543 06 Dec 18 nicklas 2805    // Not the OTP login form
7543 06 Dec 18 nicklas 2806    return;
7543 06 Dec 18 nicklas 2807 }
7543 06 Dec 18 nicklas 2808 </programlisting>
7543 06 Dec 18 nicklas 2809
7543 06 Dec 18 nicklas 2810         <para>
7543 06 Dec 18 nicklas 2811           When logging in, the ID of the selected login form is added to the
7543 06 Dec 18 nicklas 2812           <classname docapi="net.sf.basedb.core.authentication">LoginRequest</classname>
7543 06 Dec 18 nicklas 2813           with attribute name <code>login-form</code> so that login managers can
7543 06 Dec 18 nicklas 2814           pick it up and take action on it.
7543 06 Dec 18 nicklas 2815         </para>
7543 06 Dec 18 nicklas 2816
6429 10 Mar 14 nicklas 2817       </note>
6429 10 Mar 14 nicklas 2818       
8045 03 Jun 22 nicklas 2819       <sect3 id="extensions_developer.login-form.before-login">
8045 03 Jun 22 nicklas 2820         <title>The before-login event</title>
8045 03 Jun 22 nicklas 2821       
8045 03 Jun 22 nicklas 2822         <para>
8045 03 Jun 22 nicklas 2823           In BASE 3.19.3 the <code>before-login</code> was introduced. It is a custom event
8045 03 Jun 22 nicklas 2824           that is sent to the <sgmltag class="starttag">form</sgmltag> tag just before the
8045 03 Jun 22 nicklas 2825           login form is submitted to the server. Extensions may add event listeners for this
8045 03 Jun 22 nicklas 2826           event if they need to take some action and they have the possibility to cancel
8045 03 Jun 22 nicklas 2827           the submission by calling the <code>event.preventDefault()</code> method.
8045 03 Jun 22 nicklas 2828         </para>
8045 03 Jun 22 nicklas 2829         
8045 03 Jun 22 nicklas 2830         <para>
8045 03 Jun 22 nicklas 2831           This functionality is, for example, used by the <ulink 
8045 03 Jun 22 nicklas 2832           url="https://baseplugins.thep.lu.se/wiki/net.sf.basedb.webauthn">WebAuthn</ulink> extension,
8045 03 Jun 22 nicklas 2833           which need to contact the server to get a <emphasis>challenge</emphasis>, ask the user
8045 03 Jun 22 nicklas 2834           to insert and click on the security key, and then return the signed challenge in the
8045 03 Jun 22 nicklas 2835           <code>extraField</code> before the login form is actually submitted. Since all of this
8045 03 Jun 22 nicklas 2836           is handled asynchronously the <code>before-login</code> event need to be cancelled. The login
8045 03 Jun 22 nicklas 2837           form can be submitted by calling <code>Login.submitLoginForm()</code>.
8045 03 Jun 22 nicklas 2838         </para>
8045 03 Jun 22 nicklas 2839       </sect3>
6429 10 Mar 14 nicklas 2840     </sect2>
6628 26 Nov 14 nicklas 2841     
6628 26 Nov 14 nicklas 2842     <sect2 id="extensions_developer.skins">
6628 26 Nov 14 nicklas 2843       <title>Skins</title>
6628 26 Nov 14 nicklas 2844       
6628 26 Nov 14 nicklas 2845       <para>
6628 26 Nov 14 nicklas 2846         This extension point can be used to change the visual appearance of BASE. Contrary
6628 26 Nov 14 nicklas 2847         to other extension points, providing actions are optional. The skinning is
6628 26 Nov 14 nicklas 2848         done by having the action factory set style sheet and script files on the <classname 
6628 26 Nov 14 nicklas 2849         docapi="net.sf.basedb.clients.web.extensions">JspContext</classname> instance.
6628 26 Nov 14 nicklas 2850         Typically the style sheet override or set some properties defined by the BASE
6628 26 Nov 14 nicklas 2851         core stylesheets.
6628 26 Nov 14 nicklas 2852       </para>
6628 26 Nov 14 nicklas 2853       
6628 26 Nov 14 nicklas 2854       <para>
6628 26 Nov 14 nicklas 2855         Actions may be provided and should then implement the <interfacename 
6628 26 Nov 14 nicklas 2856         docapi="net.sf.basedb.clients.web.extensions.skin">SkinAction</interfacename>
6628 26 Nov 14 nicklas 2857         interface. Actions are needed if the skin extension wants to modify the
6628 26 Nov 14 nicklas 2858         fav-icon or include some data in a hidden <sgmltag class="starttag">div</sgmltag>
6628 26 Nov 14 nicklas 2859         tag. For this to work, the action must also implement the <interfacename 
6628 26 Nov 14 nicklas 2860         docapi="net.sf.basedb.clients.web.extensions">DynamicActionAttributes</interfacename>
6628 26 Nov 14 nicklas 2861         interface, since only the dynamic attribute values are included in the web page.
6628 26 Nov 14 nicklas 2862       </para>
6628 26 Nov 14 nicklas 2863       
6628 26 Nov 14 nicklas 2864       <para>
6628 26 Nov 14 nicklas 2865         BASE provides a simple action factory implementation,
6628 26 Nov 14 nicklas 2866         <classname docapi="net.sf.basedb.clients.web.extensions.skin">FixedSkinActionFactory</classname>,
6628 26 Nov 14 nicklas 2867         that supports all of the above.
6628 26 Nov 14 nicklas 2868       </para>
6628 26 Nov 14 nicklas 2869       
6628 26 Nov 14 nicklas 2870     </sect2>
7115 16 Mar 16 nicklas 2871     
7115 16 Mar 16 nicklas 2872     <sect2 id="extensions_developer.start-page">
7115 16 Mar 16 nicklas 2873       <title>Start page</title>
7115 16 Mar 16 nicklas 2874       
7115 16 Mar 16 nicklas 2875       <para>
7115 16 Mar 16 nicklas 2876         This extension point can be used to change the start page that is
7115 16 Mar 16 nicklas 2877         loaded after a use logs in to BASE. The normal start page is 
7115 16 Mar 16 nicklas 2878         the <menuchoice>
7115 16 Mar 16 nicklas 2879           <guimenu>BASE</guimenu>
7115 16 Mar 16 nicklas 2880           <guimenuitem>Home</guimenuitem>
7115 16 Mar 16 nicklas 2881         </menuchoice> page. Extensions should implement the <interfacename 
7115 16 Mar 16 nicklas 2882         docapi="net.sf.basedb.clients.web.extensions.startpage">StartPageAction</interfacename>
7115 16 Mar 16 nicklas 2883         interface. The current item in the <classname 
7115 16 Mar 16 nicklas 2884         docapi="net.sf.basedb.clients.web.extensions">JspContext</classname> 
7115 16 Mar 16 nicklas 2885         is the currently logged in user. All possible 
7115 16 Mar 16 nicklas 2886         start pages will be listed as a user configuration in the 
7115 16 Mar 16 nicklas 2887         <menuchoice>
7115 16 Mar 16 nicklas 2888           <guimenu>BASE</guimenu>
7115 16 Mar 16 nicklas 2889           <guimenuitem>Preferences</guimenuitem>
7115 16 Mar 16 nicklas 2890         </menuchoice> dialog. The ID of the selected start page is stored as
7115 16 Mar 16 nicklas 2891         a user setting. When the user is logging in to BASE the extension is
7115 16 Mar 16 nicklas 2892         queried for the URL to load and the browser is redirected to that page.
7115 16 Mar 16 nicklas 2893       </para>
7115 16 Mar 16 nicklas 2894       
7115 16 Mar 16 nicklas 2895       <para>
7115 16 Mar 16 nicklas 2896         BASE provides a simple action factory implementation:
7115 16 Mar 16 nicklas 2897         <classname docapi="net.sf.basedb.clients.web.extensions.startpage">FixedStartPageFactory</classname>.
7115 16 Mar 16 nicklas 2898       </para>
7115 16 Mar 16 nicklas 2899       
7115 16 Mar 16 nicklas 2900     </sect2>
5640 24 May 11 nicklas 2901   </sect1>
5640 24 May 11 nicklas 2902   
4184 20 Mar 08 nicklas 2903 </chapter>