Changeset 3366
- Timestamp:
- May 23, 2007, 12:56:38 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/src/docbook/developerdoc/plugin_developer.xml
r3329 r3366 29 29 <chapter id="plugin_developer"> 30 30 <?dbhtml dir="plugin_developer"?> 31 <title>Plug in developer</title>31 <title>Plug-in developer</title> 32 32 <sect1 id="plugin_developer.organize"> 33 <title>How to organize your plug in project</title>33 <title>How to organize your plug-in project</title> 34 34 35 35 <sect2 id="plugin_developer.organize.ant"> 36 36 <title>Using Ant</title> 37 37 <para> 38 Here is a simple example of how you might organize your project using ant (39 <ulink url="http://ant.apache.org">http://ant.apache.org</ulink>40 ) as the buildtool. This is just a recommendation that we have found to be working38 Here is a simple example of how you might organize your project using ant 39 (<ulink url="http://ant.apache.org">http://ant.apache.org</ulink>) as the build 40 tool. This is just a recommendation that we have found to be working 41 41 well. You may choose to do it another way. 42 42 </para> … … 45 45 <title>Directory layout</title> 46 46 <para> 47 48 Create a directory on your computer where you want 49 to store your plug-in project. This directory is the 50 <filename class="directory"><replaceable>pluginname</replaceable>/</filename> 51 directory in the listing below. You should also create some subdirectories: 52 47 53 <literallayout> 48 54 <filename class="directory"><replaceable>pluginname</replaceable>/</filename> … … 53 59 The 54 60 <filename class="directory">bin/</filename> 55 directory is empty to start with. It will contain the compiled code. The 56 <filename class="directory">lib/</filename> 57 directory contains the JAR files your plugin uses (including the 58 <filename>BASE2Core.jar</filename> 59 ). The 61 directory is empty to start with. It will contain the compiled code. 62 In the <filename class="directory">lib/</filename> 63 directory you should put <filename>BASE2Core.jar</filename> 64 and other library files your plug-in depends on. The 60 65 <filename class="directory">src/</filename> 61 directory contains your source code. 66 directory contains your source code. In this directory you should create 67 subdirectories corresponding to the package name of your plug-in 68 class(es). See <ulink url="http://en.wikipedia.org/wiki/Java_package" 69 >http://en.wikipedia.org/wiki/Java_package</ulink> for information 70 about conventions for naming packages. 62 71 </para> 63 72 </sect3> … … 68 77 In the root of your directory, create the build file: 69 78 <filename>build.xml</filename> 70 . Here is an example that will compile your plug in and put it in a JAR file.79 . Here is an example that will compile your plug-in and put it in a JAR file. 71 80 </para> 72 81 <example id="plugin_developer.organize.build.file"> … … 96 105 <target 97 106 name="build.plugin" 98 description="Compiles the plug in and put in jar"107 description="Compiles the plug-in and put in jar" 99 108 > 100 109 <javac … … 113 122 </target> 114 123 </project> 115 124 </programlisting> 116 125 </example> 117 126 <para> 118 If your plugin depends on other JAR files than the 119 <filename>Base2Core.jar</filename> 120 you should list them in the 121 <filename>MANIFEST.MF</filename> 122 file. Otherwise you should remove the manifest attribute of the jar tag in the build 123 file. 127 If your plug-in depends on other JAR files than the 128 <filename>BASE2Core.jar</filename> you must create a file called 129 <filename>MANIFEST.MF</filename> in the project root directory. 130 List the other JAR files as in the following example. 131 If your plug-in doesn't depend on other JAR files, remove the 132 <sgmltag class="attribute">manifest</sgmltag> 133 attribute of the <sgmltag class="starttag">jar</sgmltag> tag. 124 134 <programlisting> 125 135 Manifest-Version: 1.0 126 136 Class-Path: OtherJar.jar ASecondJar.jar 127 137 </programlisting> 128 138 </para> 129 139 </sect3> 130 140 131 141 <sect3 id="plugin_developer.organize.ant.build"> 132 <title>Building the plug in</title>142 <title>Building the plug-in</title> 133 143 <para> 134 Compile the plug in simply by typing144 Compile the plug-in simply by typing 135 145 <command>ant</command> 136 146 in the console window. If all went well the … … 139 149 </para> 140 150 <para> 141 To install the plug in copy the JAR file to the server including the dependent JAR142 files (if any). Place all files together in the same directory. Then follow the143 in structions in chapter144 <xref linkend="plugins.installation" /> .151 To install the plug-in copy the JAR file to the server including the dependent JAR 152 files (if any). Place all files together in the same directory. For more 153 information read 154 <xref linkend="plugins.installation" /> 145 155 </para> 146 156 </sect3> … … 149 159 <sect2 id="plugin_developer.organize.eclipse"> 150 160 <title>With Eclipse</title> 151 <para> </para>161 <para>TODO</para> 152 162 </sect2> 153 163 154 <sect2 id="plugin_developer.organize.installing">155 <title>Packaging and installing the plugin</title>156 <para>157 We recommend that each plugin or group of related plugins are compiled separately. To be158 able to use the plugin it must be put in a JAR file. Place the JAR file on the server159 <emphasis>outside</emphasis>160 the web servers classpath, ie. not in the161 <filename class="directory">WEB-INF/lib</filename>162 . Our recommendation is to place the plugin JAR in163 <filename class="directory">164 <replaceable><base-dir></replaceable>165 /plugins/166 <replaceable><name-of-plugin></replaceable>167 /168 </filename>169 </para>170 171 <para>172 The main benefit from placing the JAR file outside the classpath is that173 Base uses it's own classloader that supports unloading of the classes as well.174 This means that you may replace the JAR file with a new version without175 restarting the web server.176 </para>177 </sect2>178 164 </sect1> 179 165 180 166 <sect1 id="plugin_developer.api"> 181 <title>The Plug in API</title>167 <title>The Plug-in API</title> 182 168 <para> 183 169 </para> … … 185 171 <sect2 id="plugin_developer.api.interfaces"> 186 172 187 <title>The plugin interfaces</title>173 <title>The main plug-in interfaces</title> 188 174 <para> 189 The Base2 core defined two interfaces that are vital for implementing plugins. 175 The Base2 core defines two interfaces and one 176 abstract class that are vital for implementing plug-ins: 190 177 <itemizedlist spacing="compact"> 191 178 <listitem> … … 199 186 </simpara> 200 187 </listitem> 188 <listitem> 189 <simpara> 190 <classname>net.sf.basedb.core.plugin.AbstractPlugin</classname> 191 </simpara> 192 </listitem> 201 193 </itemizedlist> 202 It is required that the 203 <interfacename>Plugin</interfacename> 204 interface is implemented, but the 205 <interfacename>InteractivePlugin</interfacename> 206 is optional, and is only needed if you want user interaction. 194 195 A plug-in is always required to implement the 196 <interfacename>Plugin</interfacename> interface. 197 The <interfacename>InteractivePlugin</interfacename> 198 interface is optional, and is only needed if you want user interaction. 199 The <classname>AbstractPlugin</classname> is a useful base class 200 that your plug-in can use as a superclass. It provides default implementations 201 for some of the interface methods and also has utility methods for 202 validating and storing job and configuration parameter values. Another 203 reason to use this class as a superclass is that it will shield your 204 plug-in from future changes to the Plug-in API. For example, if 205 we decide that a new method is needed in the <interfacename>Plugin</interfacename> 206 interface we will also try to add a default implementation in 207 the <classname>AbstractPlugin</classname> class. 207 208 </para> 208 209 210 <important> 211 <para> 212 A plug-in must also have public no-argument contructor. Otherwise, BASE will not 213 be able to create instances of the class. 214 </para> 215 </important> 216 209 217 <sect3 id="plugin_developer.api.interfaces.plugin"> 210 218 <title>net.sf.basedb.core.plugin.Plugin</title> 211 <para>This interface defines seven methods and must be implemented by all plug ins.</para>219 <para>This interface defines seven methods and must be implemented by all plug-ins.</para> 212 220 <variablelist> 213 221 <varlistentry> … … 222 230 <listitem> 223 231 <para> 224 Return information about the plug in, i.e. the name, version, and a short225 description about what the plug in does. The232 Return information about the plug-in, i.e. the name, version, and a short 233 description about what the plug-in does. The 226 234 <classname>About</classname> 227 235 object also has fields for naming the author and various other contact 228 236 information. The returned information is copied by the core at 229 237 installation time into the database. The only required information is 230 the name of the plug in. All other fields may have null values.238 the name of the plug-in. All other fields may have null values. 231 239 </para> 232 240 <example id="net.sf.basedb.core.plugin.Plugin.getAbout"> … … 249 257 return about; 250 258 } 251 259 </programlisting> 252 260 </example> 253 261 </listitem> … … 264 272 <listitem> 265 273 <para> 266 Return information about the main type of plug in. The274 Return information about the main type of plug-in. The 267 275 <classname>MainType</classname> 268 is an enumeration w hich definesfive possible values:276 is an enumeration with five possible values: 269 277 <itemizedlist> 270 278 <listitem> 271 279 <para> 272 <constant>ANALYZE</constant> 273 : An analysis plugin280 <constant>ANALYZE</constant>: 281 An analysis plug-in 274 282 </para> 275 283 </listitem> 276 284 <listitem> 277 285 <para> 278 <constant>EXPORT</constant> 279 : A plugin the exports data286 <constant>EXPORT</constant>: 287 A plug-in the exports data 280 288 </para> 281 289 </listitem> 282 290 <listitem> 283 291 <para> 284 <constant>IMPORT</constant> 285 : A plugin that imports data292 <constant>IMPORT</constant>: 293 A plug-in that imports data 286 294 </para> 287 295 </listitem> 288 296 <listitem> 289 297 <para> 290 <constant>INTENSITY</constant> 291 : A plugin that calculates the original spot intensities298 <constant>INTENSITY</constant>: 299 A plug-in that calculates the original spot intensities 292 300 from raw data 293 301 </para> … … 295 303 <listitem> 296 304 <para> 297 <constant>OTHER</constant> 298 : Any other type of plugin305 <constant>OTHER</constant>: 306 Any other type of plug-in 299 307 </para> 300 308 </listitem> … … 302 310 The returned value is stored in the database but is otherwise not used 303 311 by the core. Client applications (such as the web client) will probably 304 use this information to group the plugins, i.e., a button labeled Export 305 will let you select among the export plugins. 312 use this information to group the plug-ins, i.e., a button labeled 313 <guibutton>Export</guibutton> 314 will let you select among the export plug-ins. 306 315 </para> 307 316 <example id="net.sf.basedb.core.plugin.Plugin.getMainType"> … … 312 321 return Plugin.MainType.OTHER; 313 322 } 314 323 </programlisting> 315 324 </example> 316 325 </listitem> … … 327 336 <listitem> 328 337 <para> 329 If this method returns true the plug in can have different338 If this method returns true the plug-in can have different 330 339 configurations, (i.e. 331 <classname>PluginConfiguration</classname> 332 ).Note that this method may return true even if the340 <classname>PluginConfiguration</classname>). 341 Note that this method may return true even if the 333 342 <interfacename>InteractivePlugin</interfacename> 334 343 interface isn't implemented. The … … 350 359 <listitem> 351 360 <para> 352 If this method returns true a Job can't be created without a 353 configuration. The 361 If this method returns true the plug-in must have a configuration 362 to be able to run. For example, some of the core import plug-ins 363 must have information about the file format to be able to import 364 any data. 365 The 354 366 <classname>AbstractPlugin</classname> 355 367 returns false for this method which is the old way before the … … 376 388 <parameter>job</parameter> 377 389 </methodparam> 390 <exceptionname>BaseException</exceptionname> 378 391 </methodsynopsis> 379 392 </term> 380 393 <listitem> 381 394 <para> 382 Prepare the plug in for execution (or configuration). If the plugin needs395 Prepare the plug-in for execution (or configuration). If the plug-in needs 383 396 to do some initialization this is the place to do it. A typical 384 397 implementation however only stores the passed parameters in instance … … 387 400 <para> 388 401 The parameters passed to this method has vital information that is 389 needed to execute the plug in. The402 needed to execute the plug-in. The 390 403 <classname>SessionControl</classname> 391 404 is a central core object which holds information about the logged in 392 user and a llows youto create405 user and are used to create 393 406 <classname>DbControl</classname> 394 objects which allows a plug in to connect to the database to read, add or407 objects which allows a plug-in to connect to the database to read, add or 395 408 update information. The two 396 409 <classname>ParameterValues</classname> 397 objects contains information about the parameters to the plugin. The 398 configuration object holds all parameters stored together with a 399 <classname>PluginConfiguration</classname> 400 object in the database. The job object holds all parameters that are 401 stored together with a Job object in the database. 402 </para> 403 <para> 404 The difference between a plugin configuration and a job parameter is 410 objects contains information about the configuration and job 411 parameters to the plug-in. 412 The <varname>configuration</varname> object holds all parameters stored 413 together with a <classname>PluginConfiguration</classname> 414 object in the database. If the plug-in is started without 415 a configuration this object is null. 416 The <varname>job</varname> object holds all parameters that are 417 stored together with a <classname>Jon</classname> object in the 418 database. This object is null if the plug-in is started without a job. 419 </para> 420 <para> 421 The difference between a configuration parameter and a job parameter is 405 422 that a configuration is usually something an administrator sets up, 406 while a job is an actual execution of a plug in. For examplea407 configuration for an import plug in holds the regular expressions needed423 while a job is an actual execution of a plug-in. For example, a 424 configuration for an import plug-in holds the regular expressions needed 408 425 to parse a text file and find the headers, sections and data lines, 409 426 while the job holds the file to parse. … … 412 429 The 413 430 <classname>AbstractPlugin</classname> 414 contains an implementation of this method make the passed parameters 415 available as protected instance variables. We recommend plugin 416 developers to let their plugins extend this class since it also has some 417 other useful methods. For example for validating parameters resulting 418 from user interaction and to store these values in the database. 431 contains an implementation of this method that saves the passed objects 432 in protected instance variables. If you override this method 433 we recommend that you also call <code>super.init()</code>. 419 434 </para> 420 435 <example id="net.sf.basedb.core.plugin.Plugin.init"> 421 <title>The <classname>AbstractPlugin</classname> implementation of this method</title>436 <title>The <classname>AbstractPlugin</classname> implementation of this Plugin.init()</title> 422 437 <programlisting> 423 438 protected SessionControl sc = null; … … 425 440 protected ParameterValues job = null; 426 441 /** 427 Store copies of the session control, plug in and job configuration. These442 Store copies of the session control, plug-in and job configuration. These 428 443 are available to subclasses in the {@link #sc}, {@link #configuration} 429 444 and {@link #job} variables. If a subclass overrides this method it is … … 438 453 this.job = job; 439 454 } 440 455 </programlisting> 441 456 </example> 442 457 </listitem> … … 460 475 <parameter>progress</parameter> 461 476 </methodparam> 462 <exceptionname>BaseException</exceptionname>463 477 </methodsynopsis> 464 478 </term> 465 479 <listitem> 466 480 <para> 467 Runs the plugin. The 468 <classname>Request</classname> 469 parameter has no useful information and can be ignored. It was 470 originally used for passing parameters to the plugin but this is now 471 found in the two 472 <classname>ParameterValues</classname> 473 objects passed to the init method. 474 </para> 475 <para> 476 The 477 <classname>ProgressReporter</classname> 478 can be used by a plugin to report it's progress back to the core. The 481 Runs the plug-in. The <varname>request</varname> 482 parameter is of historical interest only. It has no useful information 483 and can be ignored. 484 </para> 485 <para> 486 The <varname>progress</varname> parameter 487 can be used by a plug-in to report it's progress back to the core. The 479 488 core will usually send the progress information to the database, which 480 allows users to see exactly how the plug in is progressing from the web489 allows users to see exactly how the plug-in is progressing from the web 481 490 interface. This parameter can be null, but if it isn't we recommend all 482 plug ins to use it. However, it should be used sparingly, since each call491 plug-ins to use it. However, it should be used sparingly, since each call 483 492 to set the progress results in a database update. If the execution 484 493 involves several thousands of items it is a bad idea to update the 485 494 progress after processing each one of them. A good starting point is to 486 495 divide the work into 100 pieces each representing 1% of the work, i.e., 487 if the plug in should export 100 000 items it should report progress496 if the plug-in should export 100 000 items it should report progress 488 497 after every 1000 items. 489 498 </para> 490 499 <para> 491 The 492 <classname>Response</classname> 493 parameter is used to tell the core if the plugin was successful or 500 The <varname>response</varname> 501 parameter is used to tell the core if the plug-in was successful or 494 502 failed. Not setting a response is considered a failure by the core. From 495 503 the run method it is only allowed to use the … … 497 505 or the 498 506 <methodname>setError()</methodname> 499 methods. 500 </para> 507 methods. 508 </para> 509 510 <note> 511 It is also considered bad practice to let exceptions escape 512 out from this method. Always use <code>try...catch</code> 513 to catch exceptions and use <code>response.setError()</code> 514 to reporter the error back to the core. 515 </note> 516 501 517 <example id="net.sf.basedb.core.plugin.Plugin.run"> 502 518 <title> 503 Here is a skeleton that we recommend each plug in to use in it's519 Here is a skeleton that we recommend each plug-in to use in it's 504 520 implementation of the 505 521 <methodname>run()</methodname> … … 514 530 try 515 531 { 516 // Insert code for plug in here532 // Insert code for plug-in here 517 533 518 534 // Commit the work 519 535 dc.commit(); 520 response.setDone("Plug in ended successfully");536 response.setDone("Plug-in ended successfully"); 521 537 } 522 538 catch (Throwable t) … … 532 548 } 533 549 } 534 550 </programlisting> 535 551 </example> 536 552 </listitem> … … 547 563 <listitem> 548 564 <para> 549 Clean up all resources after executing the plug in. This method mustn't565 Clean up all resources after executing the plug-in. This method mustn't 550 566 throw any exceptions. 551 567 </para> … … 554 570 The 555 571 <classname>AbstractPlugin</classname> 556 contains an implementation of this method which simply sets the 572 contains an implementation of the <methodname>done()</methodname> 573 method simply sets the 557 574 parameters passed to the 558 575 <methodname>init()</methodname> … … 580 597 <title>net.sf.basedb.core.plugin.InteractivePlugin</title> 581 598 <para> 582 If you want the plug in to be able to interact with the user you must also implement583 this interface. This is probably the case for most plug ins. Among the plugins584 s upplied with the core of Basethe599 If you want the plug-in to be able to interact with the user you must also implement 600 this interface. This is probably the case for most plug-ins. Among the core plug-ins 601 shipped with BASE the 585 602 <classname>SpotImageCreator</classname> 586 is one plug in that doesn't interact with the user. Instead, the web client has603 is one plug-in that doesn't interact with the user. Instead, the web client has 587 604 special JSP pages that handles all the interaction, creates a job for it and sets 588 the parameters. This, kind of hardcoded, approach can be used for other plug ins as605 the parameters. This, kind of hardcoded, approach can be used for other plug-ins as 589 606 well, but then it usually requires modification of the client application as well. 590 607 </para> … … 592 609 The 593 610 <interfacename>InteractivePlugin</interfacename> 594 has three main tasks: tell a client application where the plugin should be plugged 595 in, ask users for parameters, and validate and store those parameters. It requires 596 the implementation of four method. 611 has three main tasks: 612 613 <orderedlist> 614 <listitem> 615 <para> 616 Tell a client application where the plug-in should be plugged 617 in. 618 </para> 619 </listitem> 620 <listitem> 621 <para> 622 Ask the users for configuration and job parameters. 623 </para> 624 </listitem> 625 626 <listitem> 627 <para> 628 Validate parameter values entered by the user and store those in the 629 database. 630 </para> 631 </listitem> 632 </orderedlist> 633 This requires that the following methods are 634 implemented. 597 635 </para> 636 598 637 <variablelist> 599 638 <varlistentry> … … 608 647 <listitem> 609 648 <para> 610 Return information about where the plug in should be plugged in. Each649 Return information about where the plug-in should be plugged in. Each 611 650 place is identified by a 612 651 <classname>GuiContext</classname> … … 614 653 <classname>Item</classname> 615 654 and a 616 <classname>Type</classname> 617 .The item is one of the objects defined by the655 <classname>Type</classname>. 656 The item is one of the objects defined by the 618 657 <classname>net.sf.basedb.core.Item</classname> 619 658 enumeration and the type is either 620 659 <constant>Type.LIST</constant> 621 660 or 622 <constant>Type.ITEM</constant> 623 .661 <constant>Type.ITEM</constant>, which corresponde to the 662 list view and the single-item view in the web client. 624 663 </para> 625 664 <para> 626 665 For example, the 627 <varname>GuiContext</varname> 628 <literal>= (</literal> 629 <constant>Item.REPORTER</constant> 630 <literal>,</literal> 631 <constant>Type.LIST</constant> 632 <literal>)</literal> 633 tells a client application that this plugin can be plugged in whenever a 666 <varname>GuiContext</varname> = 667 (<constant>Item.REPORTER</constant>, 668 <constant>Type.LIST</constant>) 669 tells a client application that this plug-in can be plugged in whenever a 634 670 list of reporters is displayed. The 635 <varname>GuiContext</varname> 636 = ( 637 <constant>Item.REPORTER</constant> 638 , 639 <constant>Type.ITEM</constant> 640 ) tells a client application that this plugin can be plugged in whenever 671 <varname>GuiContext</varname> = 672 (<constant>Item.REPORTER</constant>, 673 <constant>Type.ITEM</constant>) 674 tells a client application that this plug-in can be plugged in whenever 641 675 a single reporter is displayed. The first case may be appropriate for a 642 plug in that imports or exports reporters. The second case may be used by643 a plug in that updates the reporter information from an external source676 plug-in that imports or exports reporters. The second case may be used by 677 a plug-in that updates the reporter information from an external source 644 678 (well, it may make sense to use this in the list case as well). 645 679 </para> 646 680 <para> 647 681 The returned information is copied by the core at installation time to 648 make it easy to ask for all plugins for a certain 649 <classname>GuiContext</classname> 650 . 682 make it easy to ask for all plug-ins for a certain 683 <classname>GuiContext</classname>. 651 684 </para> 652 685 <para> … … 654 687 <classname>Set</classname> 655 688 which is returned by this method. It is important that the returned set 656 can't be modified , since it may be a security issue if a badbehaving689 can't be modified. It may be a security issue if a misbehaving 657 690 client application does that. 658 691 </para> … … 663 696 </title> 664 697 <programlisting> 665 // From the net.sf.basedb.plugins.RawDataFlatFileImporter plug in698 // From the net.sf.basedb.plugins.RawDataFlatFileImporter plug-in 666 699 private static final Set<GuiContext> guiContexts = 667 700 Collections.singleton(new GuiContext(Item.RAWBIOASSAY, GuiContext.Type.ITEM)); … … 671 704 return <returnvalue>guiContexts</returnvalue>; 672 705 } 673 706 </programlisting> 674 707 </example> 675 708 </listitem> … … 694 727 <para> 695 728 This method is called to check if a particular item is usable for the 696 plugin, when the context type is 697 <constant>Type.ITEM</constant> 698 , i.e. the user has selected a specific sample and the the client 699 application is now displaying information about that sample. Thus, our 700 <varname>GuiContext</varname> 701 = ( 702 <constant>Item.SAMPLE</constant> 703 , 704 <constant>Type.ITEM</constant> 705 ). Now, the client application asks for a list of plugins supporting 729 plug-in. This method is only invoked from the single-item view. 730 Thus, <code>context.getType()</code> always returns 731 <constant>Type.ITEM</constant>, and <code>context.getItem()</code> 732 returns a value corresponding to the type of item that is passed 733 in the <varname>item</varname> parameter. Here is an example: 734 735 <informalexample> 736 <para> 737 The user has selected a specific sample and the the client 738 application is now displaying information about that sample. 739 Thus, our 740 <varname>GuiContext</varname> = 741 (<constant>Item.SAMPLE</constant>, 742 <constant>Type.ITEM</constant>). 743 744 Now, the client application asks for a list of plug-ins supporting 706 745 this context and for each one in the list calls this method with the 707 current sample as the item parameter. The plugin should answer if it can 708 do whatever it is supposed to do by returning null or a string 709 containing a message why it can't. 746 current sample as the value of the <varname>item</varname> parameter. 747 </para> 748 </informalexample> 749 750 If the plug-in can do whatever it is supposed to do it should 751 return null, otherwise it should return a string with a message 752 explaining why it can't. 710 753 </para> 711 754 <para> 712 755 Here is a real example from the 713 756 <classname>RawDataFlatFileImporter</classname> 714 plug in which imports raw data to a715 <classname>RawBioAssay</classname> 716 . Thus,717 <varname>GuiContext</varname>718 = (719 <constant>Item.RAWBIOASSAY</constant>720 ,721 <constant>Type.ITEM</constant>722 ), but the plugin can only import data if there isn't any already, and723 if the raw bioassay has the same raw data type as the plug in has been757 plug-in which imports raw data to a 758 <classname>RawBioAssay</classname>. 759 760 Thus, 761 <varname>GuiContext</varname> = 762 (<constant>Item.RAWBIOASSAY</constant>, 763 <constant>Type.ITEM</constant>), 764 765 but the plug-in can only import data if there isn't any already, and 766 if the raw bioassay has the same raw data type as the plug-in has been 724 767 configured for. 725 768 </para> … … 760 803 return message; 761 804 } 762 805 </programlisting> 763 806 </example> 764 807 </listitem> … … 783 826 <listitem> 784 827 <para> 785 Ask the plug in for parameters that needs to be entered by the user. The828 Ask the plug-in for parameters that needs to be entered by the user. The 786 829 <classname>GuiContext</classname> 787 830 parameter is one of the contexts returned by the 788 831 <methodname>getGuiContexts</methodname> 789 method. The command is string telling the plug in what command was832 method. The command is string telling the plug-in what command was 790 833 executed. There are two predefined commands but as you will see the 791 plug in may define it's own commands. The two predefined commands are834 plug-in may define it's own commands. The two predefined commands are 792 835 defined in the 793 836 <classname>net.sf.basedb.core.plugin.Request</classname> … … 801 844 <para> 802 845 Used when an administrator is initiating a configuration 803 of the plug in.846 of the plug-in. 804 847 </para> 805 848 </listitem> … … 811 854 <listitem> 812 855 <para> 813 Used when a user has selected the plug in for running a856 Used when a user has selected the plug-in for running a 814 857 job. 815 858 </para> … … 817 860 </varlistentry> 818 861 </variablelist> 819 Given this information the plug in must return a862 Given this information the plug-in must return a 820 863 <classname>RequestInformation</classname> 821 864 object. This is simply a title, a description and a list of parameters. … … 827 870 <example id="net.sf.basedb.core.plugin.InteractivePlugin.getRequestInformation"> 828 871 <title> 829 When running an import plug in it needs to ask for the file to import872 When running an import plug-in it needs to ask for the file to import 830 873 from and if existing items should be updated or not 831 874 </title> 832 <programlisting >875 <programlisting > 833 876 // The complete request information 834 877 private RequestInformation configure Job; … … 893 936 return configureJob; 894 937 } 895 938 </programlisting> 896 939 </example> 897 940 <para> 898 As you can see it takes somecode to put together a941 As you can see it takes a lot of code to put together a 899 942 <classname>RequestInformation</classname> 900 object. For each parameter neededyou need one943 object. For each parameter you need one 901 944 <classname>PluginParameter</classname> 902 945 object and one 903 946 <classname>ParameterType</classname> 904 object. Actually, a947 object. To make life a little easier, a 905 948 <classname>ParameterType</classname> 906 949 can be reused for more than one 907 <classname>PluginParameter</classname> 908 . 950 <classname>PluginParameter</classname>. 909 951 </para> 910 952 … … 914 956 PluginParameter two = new PluginParameter("two", "Two", "Second string", stringPT); 915 957 // ... and so on 916 958 </programlisting> 917 959 <para> 918 960 The … … 991 1033 Asks for any other item. This parameter type requires 992 1034 that a list of options is supplied, except when the item 993 type asked for matches the current GuiContext, in which1035 type asked for matches the current <classname>GuiContext</classname>, in which 994 1036 case the currently selected item is used as the 995 1037 parameter value. … … 1004 1046 <para> 1005 1047 Ask for a path to a file or directory. The path may be 1006 non-existing and should be used when a plug in needs an1048 non-existing and should be used when a plug-in needs an 1007 1049 output destination, i.e., the file to export to, or a 1008 1050 directory where the output files should be placed. … … 1015 1057 <classname>PluginParameter</classname> 1016 1058 with a null name and 1017 <classname>ParameterType</classname> 1018 . In that case, the corewill not ask for input from the user, instead1059 <classname>ParameterType</classname>. 1060 In this case, the web client will not ask for input from the user, instead 1019 1061 it is used as a section header, allowing you to group parameters into 1020 1062 different sections which increase the readability of the input … … 1033 1075 parameters.add(firstParameterInSecondSection); 1034 1076 parameters.add(secondParameteInSecondSection); 1035 1077 </programlisting> 1036 1078 </listitem> 1037 1079 </varlistentry> … … 1058 1100 <listitem> 1059 1101 <para> 1060 Sends parameter values entered by the user for processing by the plug in.1061 T ypically the plugin shouldvalidate that the parameter values are1102 Sends parameter values entered by the user for processing by the plug-in. 1103 The plug-in must validate that the parameter values are 1062 1104 correct and then store them in database. 1063 1105 </para> 1064 <para> 1106 1107 <important> 1108 <para> 1065 1109 No validation is done by the core, except converting the input to the 1066 correct object type, i.e. if the p arameterasked for a1110 correct object type, i.e. if the plug-in asked for a 1067 1111 <classname>Float</classname> 1068 the input string is parsed and converted to a Float. If you have1069 extended the1112 the input string is parsed and converted to a 1113 <classname>Float</classname>. If you have extended the 1070 1114 <classname>AbstractPlugin</classname> 1071 class it is very easy to validate the parameters using it's1115 class it is very easy to validate the parameters with the 1072 1116 <methodname>validateRequestParameters()</methodname> 1073 1117 method. This method takes the same list of 1074 <classname>PluginParameter</classname> 1075 's used in the1118 <classname>PluginParameter</classname>:s 1119 as used in the 1076 1120 <classname>RequestInformation</classname> 1077 1121 object and uses that information for validation. It returns null or a 1078 1122 list of 1079 <exceptionname>Throwable</exceptionname> 1080 . 1081 </para> 1082 <para> 1083 When the parameters have been validated they need to be stored. Once 1084 again, it is very easy if you use one of the 1123 <exceptionname>Throwable</exceptionname>:s that can be 1124 given directly to the <code>response.setError()</code> 1125 methods. 1126 </para> 1127 </important> 1128 <para> 1129 When the parameters have been validated they need to be stored 1130 in the datatbase. Once again, it is very easy if you use one of the 1085 1131 <methodname>AbstractPlugin.storeValue()</methodname> 1086 1132 or … … 1089 1135 </para> 1090 1136 <para> 1091 The configure method works much like the 1092 <methodname>Plugin.run()</methodname> 1093 method. It must return the result in the 1094 <classname>Response</classname> 1095 object, i.e. it shouldn't trow any exceptions. 1096 </para> 1137 The configure method works much like the <methodname>Plugin.run()</methodname> 1138 method. It must return the result in the <classname>Response</classname> object, 1139 and shouldn't trow any exceptions. 1140 </para> 1141 1097 1142 <example id="net.sf.basedb.core.plugin.InteractivePlugin.configure"> 1098 1143 <title> … … 1135 1180 } 1136 1181 } 1137 1182 </programlisting> 1138 1183 </example> 1139 <para> 1140 Note that the 1141 <methodname>setDone()</methodname> 1184 1185 <para> 1186 Note that the call to 1187 <methodname>response.setDone()</methodname> 1142 1188 has a second parameter 1143 <c lassname>Job.ExecutionTime</classname>1144 . It is an indicationabout how long time it will take to execute the1145 plug in. This is of interest for job queue managers which probably1189 <constant>Job.ExecutionTime.SHORT</constant>. It is an indication 1190 about how long time it will take to execute the 1191 plug-in. This is of interest for job queue managers which probably 1146 1192 doesn't want to start too many long-running jobs at the same time 1147 1193 blocking the entire system. Please try to use this parameter wisely and 1148 not use the 1149 <constant>Job.ExecutionTime.SHORT</constant> 1150 value out of old habit all the time. 1151 </para> 1152 <para> 1153 The response also has a 1194 not use <constant>Job.ExecutionTime.SHORT</constant> 1195 out of old habit all the time. 1196 </para> 1197 <para> 1198 The <classname>Response</classname> class also has a 1154 1199 <methodname>setContinue()</methodname> 1155 method which tells the core that the plug in needs more parameters,1200 method which tells the core that the plug-in needs more parameters, 1156 1201 i.e. the core will then call 1157 1202 <methodname>getRequestInformation()</methodname> 1158 again with the new command, let the user enter values, and the call1203 again with the new command, let the user enter values, and then call 1159 1204 <methodname>configure()</methodname> 1160 with the new values. This process is repeated until the plug in1205 with the new values. This process is repeated until the plug-in 1161 1206 reports that it is done or an error occurs. 1162 1207 </para> 1163 1208 <para> 1164 1209 An important note is that during this iteration it is the same instance 1165 of the plugin that is used. However, no parameter values are stored in 1166 the database until 1167 <methodname>setDone()</methodname> 1168 is called. Then, the plugin instance is usually discarded. The execution 1169 of the plugin happens in a new instance and maybe on a different server. 1210 of the plug-in that is used. However, no parameter values are stored in 1211 the database until the plugin sends a 1212 <methodname>response.setDone()</methodname>. 1213 After that, the plug-in instance is usually discarded, and a job is placed 1214 in the job queue. The execution of the plug-in happens in a new instance 1215 and maybe on a different server. 1170 1216 </para> 1171 1217 <tip> 1172 1218 <para> 1173 You don't have to store all values the plug in asked for in the1219 You don't have to store all values the plug-in asked for in the 1174 1220 first place. You may even choose to store different values than 1175 1221 those that were entered. For example, you might ask for the mass … … 1185 1231 </sect2> 1186 1232 1187 <sect2 id="plugin_developer.api.parameters"> 1188 <title>Asking for parameters</title> 1233 <sect2 id="plugin_developer.api.callsequence"> 1234 <title>What happens when...</title> 1235 1189 1236 <para> 1190 The webclient will ask for parameters by calling the method 1191 <methodname>getRequestInformation</methodname> from the interface 1192 <interfacename>InteractivePlugin</interfacename>. The 1193 <methodname>getRequestInformation</methodname> is described in detail in this example, 1194 <xref linkend="net.sf.basedb.core.plugin.InteractivePlugin.getRequestInformation"/>. 1237 This section describes how the BASE core interacts with the 1238 plug-in in a number of use cases. We will outline the 1239 order the methods are invoked on the plug-in. 1195 1240 </para> 1196 1241 1197 <sect3 id="plugin_developer.api.parameters.jsp"> 1198 <title>Using custom JSP pages for parameters</title> 1242 <sect3 id="plugin_developer.api.callsequence.install"> 1243 <title>Installing a plug-in</title> 1244 1199 1245 <para> 1200 This is an advanced option for plugins that require a different interface for 1201 specifying plugin parameters than the default list showing each parameter at a 1246 When a plug-in is installed the core is eager to find out 1247 information about the plug-in. To do this it calls the 1248 following methods in this order: 1249 </para> 1250 1251 <orderedlist> 1252 <listitem> 1253 <para> 1254 A new instance of the plug-in class is created. The plug-in must 1255 have a public no-argument constructor. 1256 </para> 1257 </listitem> 1258 1259 <listitem> 1260 <para> 1261 Calls are made to <methodname>Plugin.getMainType()</methodname>, 1262 <methodname>Plugin.supportsConfigurations()</methodname>, 1263 <methodname>Plugin.requiresConfiguration()</methodname> and 1264 <methodname>Plugin.getAbout()</methodname> to find out information 1265 about the plug-in. This is the only time theese methods are called. 1266 The information that is returned by them are copied and stored in 1267 the database for easy access. 1268 </para> 1269 1270 <note> 1271 <para> 1272 The <methodname>Plugin.init()</methodname> method is 1273 never called during plug-in installation. 1274 </para> 1275 </note> 1276 </listitem> 1277 1278 <listitem> 1279 <para> 1280 If the plug-in implements the <interfacename>InteractivePlugin</interfacename> 1281 interface the <methodname>InteractivePlugin.getGuiContexts()</methodname> 1282 method is called. This is the only time this method. The information it 1283 returns are copied and stored in the database. 1284 </para> 1285 </listitem> 1286 1287 <listitem> 1288 <para> 1289 If the server admin decided to use the plug-in permission system, the 1290 <methodname>Plugin.getPermissions()</methodname> method is called. 1291 The returned information is copied and stored in the database. 1292 </para> 1293 </listitem> 1294 1295 </orderedlist> 1296 </sect3> 1297 1298 <sect3 id="plugin_developer.api.callsequence.configure"> 1299 <title>Configuring a plug-in</title> 1300 1301 <para> 1302 The plug-in must implement the <interfacename>InteractivePlugin</interfacename> 1303 interface and the <methodname>Plugin.supportsConfigurations()</methodname> method 1304 must return <constant>TRUE</constant>. The configuration is done with 1305 a wizard-like interface (see <xref linkend="plugins.configuration.wizard" />). 1306 The same plug-in instance is used throughout the entire configuration sequence. 1307 </para> 1308 1309 <orderedlist> 1310 <listitem> 1311 <para> 1312 A new instance of the plug-in class is created. The plug-in must 1313 have a public no-argument constructor. 1314 </para> 1315 </listitem> 1316 1317 <listitem> 1318 <para> 1319 The <methodname>Plugin.init()</methodname> method is called. The 1320 <varname>job</varname> parameter is null. 1321 </para> 1322 </listitem> 1323 1324 <listitem id="plugin_developer.api.callsequence.configure.requestinformation"> 1325 <para> 1326 The <methodname>InteractivePlugin.getRequestInformation()</methodname> 1327 method is called. The <varname>context</varname> parameter is <constant>null</constant> 1328 and the <varname>command</varname> is the value of the string 1329 constant <constant>Request.COMMAND_CONFIGURE_PLUGIN</constant> 1330 (_config_plugin). 1331 </para> 1332 </listitem> 1333 1334 <listitem id="plugin_developer.api.callsequence.configure.form"> 1335 <para> 1336 The web client process this information and displays a form for user 1337 input. The plug-in will have to wait some time while the user enters 1338 data. 1339 </para> 1340 </listitem> 1341 1342 <listitem> 1343 <para> 1344 The <methodname>InteractivePlugin.configure()</methodname> method 1345 is called. The <varname>context</varname> parameter is still 1346 <constant>null</constant> and the <varname>request</varname> 1347 parameter contains the parameter values entered by the user. 1348 </para> 1349 </listitem> 1350 1351 <listitem> 1352 <para> 1353 The plug-in must validate the values and decided if they should be 1354 stored in the database or not. We recommend that you use the 1355 methods in the <classname>AbstractPlugin</classname> class for this. 1356 </para> 1357 </listitem> 1358 1359 <listitem> 1360 <para> 1361 The plug-in has three different respones: 1362 1363 <itemizedlist> 1364 <listitem> 1365 <para> 1366 <methodname>Response.setDone()</methodname>: The configuration 1367 is complete. The core will write any configuation changes to the 1368 database, call the <methodname>Plugin.done()</methodname> method and 1369 then discard the plug-in instance. 1370 </para> 1371 </listitem> 1372 1373 <listitem> 1374 <para> 1375 <methodname>Response.setError()</methodname>: There was one or more 1376 errors. The web client will display the error messages for the user and 1377 allow the user to enter new values. The process continues with 1378 step <xref linkend="plugin_developer.api.callsequence.configure.form" />. 1379 </para> 1380 </listitem> 1381 1382 <listitem> 1383 <para> 1384 <methodname>Response.setContinue()</methodname>: The parameters are correct 1385 but the plug-in wants more parameters. The process continues with 1386 step <xref linkend="plugin_developer.api.callsequence.configure.requestinformation" />. 1387 </para> 1388 </listitem> 1389 </itemizedlist> 1390 1391 </para> 1392 </listitem> 1393 </orderedlist> 1394 1395 </sect3> 1396 1397 <sect3 id="plugin_developer.api.callsequence.context"> 1398 <title>Checking if a plug-in can be used in a given context</title> 1399 1400 <para> 1401 If the plug-in is an <interfacename>InteractivePlugin</interfacename> 1402 it has specified in which contexts it can be used by the 1403 information returned from <methodname>InteractivePlugin.getGuiContexts()</methodname> 1404 method. The web client uses this information to decide if, 1405 for example, an <guibutton>Run plugin</guibutton> 1406 button should be displayed on a page or not. However this is not 1407 always enough to know if the plug-in can be used or not. 1408 For example, a raw data importer plug-in can't be used to 1409 import raw data if the raw bioassay already has data. 1410 So, when the user clicks the button, the web client will 1411 load all plug-ins that maybe can be used in the given context 1412 and let each one of the check if they can be used or not. 1413 </para> 1414 1415 1416 <orderedlist> 1417 <listitem> 1418 <para> 1419 A new instance of the plug-in class is created. The plug-in must 1420 have a public no-argument constructor. 1421 </para> 1422 </listitem> 1423 1424 <listitem> 1425 <para> 1426 The <methodname>Plugin.init()</methodname> method is called. 1427 The <varname>job</varname> parameter is <constant>null</constant>. 1428 The <varname>configuration</varname> parameter is <constant>null</constant> 1429 if the plug-in doesn't have any configuration parameters. 1430 </para> 1431 </listitem> 1432 1433 <listitem> 1434 <para> 1435 The <methodname>InteractivePlugin.isInContext()</methodname> 1436 is called. If the context is a list context, the <varname>item</varname> 1437 parameter is null, otherwise the current item is passed. The plug-in 1438 should return <constant>null</constant> if it can be used under the 1439 current circumstances, or a message explaining why not. 1440 </para> 1441 </listitem> 1442 1443 <listitem> 1444 <para> 1445 After this, the plug-in instance is discarded. If there are 1446 several configurations for a plug-in this procedure is repeated 1447 for each configuration. 1448 </para> 1449 1450 <warning> 1451 <para> 1452 The <methodname>Plugin.done()</methodname> method is never 1453 called! This is bug that has been reported to the developers 1454 and hopefully it will be fixed shortly. 1455 </para> 1456 </warning> 1457 </listitem> 1458 </orderedlist> 1459 </sect3> 1460 1461 <sect3 id="plugin_developer.api.callsequence.job"> 1462 <title>Creating a new job</title> 1463 1464 <para> 1465 If the web client found that the plug-in could be 1466 used in a given context and the user selected the plug-in 1467 the job configuration sequence is started. It is a wizard-like interface 1468 identical to the configuration wizard. In fact, the same JSP pages, 1469 and calling sequence is used. See <xref linkend="plugin_developer.api.callsequence.configure" />. 1470 We don't repeat everything here. There are a few differences: 1471 </para> 1472 1473 <itemizedlist> 1474 <listitem> 1475 <para> 1476 The <varname>job</varname> parameter is not null, but it doesn't contain 1477 any parameter values to start with. The plug-in should use this 1478 object to store job-related parameter values. The 1479 <varname>configuration</varname> parameter is <constant>null</constant> 1480 if the plug-in is started without configuration. In any case, 1481 the configuration values are write-protected and can't be modified. 1482 </para> 1483 </listitem> 1484 1485 <listitem> 1486 <para> 1487 The first call to <methodname>InteractivePlugin.getRequestInformation()</methodname> 1488 is done with <constant>Request.COMMAND_CONFIGURE_JOB</constant> (_configjob) 1489 as the command. The <varname>context</varname> parameter reflects the 1490 current context. 1491 </para> 1492 </listitem> 1493 1494 <listitem> 1495 <para> 1496 When calling <methodname>Response.setDone()</methodname> the plug-in 1497 should use the variant that takes an estimated execution time. 1498 If the plug-in has support for immediate execution or download 1499 (export plug-ins only) it can also respond with 1500 <methodname>Response.setExecuteImmediately()</methodname> or 1501 <methodname>Response.setDownloadImmediately()</methodname>. 1502 </para> 1503 1504 <para> 1505 If the plug-in requested and was granted immediate execution or 1506 download the same plug-in instance is used to execute the plug-in. 1507 The may be done with the same or a new thread. Otherwise, a new 1508 job is added to the job queue, the parameter value are saved 1509 and the plug-in instance is discarded after calling the 1510 <methodname>Plugin.done()</methodname> method. 1511 </para> 1512 </listitem> 1513 </itemizedlist> 1514 </sect3> 1515 1516 <sect3 id="plugin_developer.api.callsequence.execute"> 1517 <title>Executing a job</title> 1518 1519 <para> 1520 Normally, the creation of a job and the execution of it are 1521 two different events. The execution may as well be done on a 1522 different server. See <xref linkend="installation_upgrade.jobagents" />. 1523 This means that the execution takes place in a different instance 1524 of the plug-in class than what was used for creating the job. 1525 The exception is if a plug-in supports immediate execution or download. 1526 In this case the same instance is used, and it, of course, 1527 is always executed on the web server. 1528 </para> 1529 1530 <orderedlist> 1531 <listitem> 1532 <para> 1533 A new instance of the plug-in class is created. The plug-in must 1534 have a public no-argument constructor. 1535 </para> 1536 </listitem> 1537 1538 <listitem> 1539 <para> 1540 The <methodname>Plugin.init()</methodname> method is called. 1541 The <varname>job</varname> parameter contains the job 1542 configuration paramters. The <varname>configuration</varname> parameter 1543 is <constant>null</constant> if the plug-in doesn't have any 1544 configuration parameters. 1545 </para> 1546 </listitem> 1547 1548 <listitem> 1549 <para> 1550 The <methodname>Plugin.run()</methodname> method is called. 1551 It is finally time for the plug-in to do the work it has bee 1552 designed for. This method shouldn't throw any exceptions. 1553 Use the <methodname>Response.setDone()</methodname> 1554 method to report success or the <methodname>Response.setError()</methodname> 1555 to reporter errors. 1556 </para> 1557 </listitem> 1558 1559 <listitem> 1560 <para> 1561 In both cases the <methodname>Plugin.done()</methodname> 1562 method is called and the plug-in instance is discarded. 1563 </para> 1564 </listitem> 1565 1566 </orderedlist> 1567 </sect3> 1568 1569 </sect2> 1570 1571 <sect2 id="plugin_developer.api.jspparameters"> 1572 <title>Using custom JSP pages for parameter input</title> 1573 1574 <para> 1575 This is an advanced option for plug-ins that require a different interface for 1576 specifying plug-in parameters than the default list showing each parameter at a 1202 1577 time. This feature is used by setting the RequestInformation.getJspPage() 1203 property when constructi onthe request information object. If this property has1578 property when constructing the request information object. If this property has 1204 1579 a non-null value, the web client will send the browser to the specified JSP page 1205 1580 instead of to the generic parameter input page. 1206 1581 </para> 1207 1582 <para> 1208 When setting the JSP page you should not specify any path information. The web 1583 When setting the JSP page you should only set the file name. Don't include 1584 any path information. The web 1209 1585 client has a special location for these JSP pages, generated from the package 1210 name of your plugin and the returned values. If the plugin is located in the 1211 package 1586 name of your plug-in. If the plug-in is located in the package 1212 1587 <classname>org.company</classname> 1213 1588 the JSP page must be located in 1214 <filename class="directory"> www-root/plugins/org/company/</filename>1215 .Please note that the browser still thinks that it is showing the regular page1589 <filename class="directory"><base-dir>/www/plugins/org/company/</filename>. 1590 Please note that the browser still thinks that it is showing the regular page 1216 1591 at the usual location: 1217 <filename class="directory"> www-root/common/plugin/index.jsp</filename>1218 , so all links in your JSP page should be relative to that directory.1592 <filename class="directory"><base-dir>/www/common/plugin/index.jsp</filename>. 1593 All links in your JSP page should be relative to that directory. 1219 1594 </para> 1220 1595 <para> 1221 1596 Even if you use your own JSP page we recommend that you use the built-in 1222 facility for passing the parameters back to the plug in. For this to work you1597 facility for passing the parameters back to the plug-in. For this to work you 1223 1598 must: 1224 1599 </para> 1225 1600 <itemizedlist spacing="compact"> 1226 1601 <listitem> 1227 <simpara>Generate the list of <classname>PluginParameter</classname> objects as usual</simpara> 1602 <simpara> 1603 Generate the list of <classname>PluginParameter</classname> 1604 objects as usual. 1605 </simpara> 1228 1606 </listitem> 1229 1607 <listitem> 1230 1608 <simpara> 1231 Name all your input fields like:1609 Name all your input fields in the JSP like: 1232 1610 <parameter> 1233 parameter: 1234 <replaceable>name-of-parameter</replaceable> 1611 parameter:<replaceable>name-of-parameter</replaceable> 1235 1612 </parameter> 1236 1613 </simpara> … … 1244 1621 First string: <input type="text" name="parameter:one"><br> 1245 1622 Second string: <input type="text" name="parameter:two"> 1246 1623 </programlisting> 1247 1624 </listitem> 1248 1625 <listitem> … … 1250 1627 Send the form to 1251 1628 <filename>index.jsp</filename> 1252 with some parameters 1629 with the <varname>ID</varname> and <varname>cmd</varname> parameters 1630 as shown below. 1253 1631 </simpara> 1254 1632 <programlisting> … … 1258 1636 ... 1259 1637 </form> 1260 </programlisting> 1638 </programlisting> 1639 1640 </listitem> 1641 </itemizedlist> 1261 1642 <para> 1262 1643 In your JSP page you will probably need to access some information like the 1263 <classname>SessionControl</classname> 1264 and possible even the 1265 <classname>RequestInformation</classname> 1266 object created by your plugin. 1644 <classname>SessionControl</classname>, <classname>Job</classname> 1645 and possible even the <classname>RequestInformation</classname> 1646 object created by your plug-in. 1267 1647 </para> 1268 1648 <programlisting> … … 1271 1651 final String ID = sc.getId(); 1272 1652 1273 // Get information about the current request to the plug in1653 // Get information about the current request to the plug-in 1274 1654 PluginConfigurationRequest pcRequest = 1275 1655 (PluginConfigurationRequest)sc.getSessionSetting("plugin.configure.request"); … … 1281 1661 (PluginDefinition)sc.getSessionSetting("plugin.configure.job"); 1282 1662 RequestInformation ri = pcRequest.getRequestInformation(); 1283 </programlisting> 1284 </listitem> 1285 </itemizedlist> 1286 </sect3> 1663 </programlisting> 1664 1287 1665 </sect2> 1288 1666 </sect1> 1289 1667 1290 1668 <sect1 id="plugin_developer.import"> 1291 <title>Import plug ins</title>1669 <title>Import plug-ins</title> 1292 1670 <para> 1293 1671 … … 1309 1687 1310 1688 <sect1 id="plugin_developer.export"> 1311 <title>Export plug ins</title>1689 <title>Export plug-ins</title> 1312 1690 <para>TODO</para> 1313 1691 … … 1319 1697 1320 1698 <sect1 id="plugin_developer.analyse"> 1321 <title>Analysis plug ins</title>1699 <title>Analysis plug-ins</title> 1322 1700 <para> 1323 A plug in becomes an analysis plugin simply by returning1701 A plug-in becomes an analysis plug-in simply by returning 1324 1702 <constant>Plugin.MainType.ANALYSIS</constant> from the 1325 1703 <methodname>Plugin.getMainType()</methodname> method. The information returned from 1326 1704 <methodname>InteractivePlugin.getGuiContexts()</methodname> 1327 1705 must include: [<constant>Item.BIOASSAYSET</constant>, <constant>Type.ITEM</constant>] since 1328 this is the only place where the web client looks for analysis plug ins.1706 this is the only place where the web client looks for analysis plug-ins. 1329 1707 </para> 1330 1708 … … 1349 1727 1350 1728 <sect1 id="plugin_developer.other"> 1351 <title>Other plug ins</title>1729 <title>Other plug-ins</title> 1352 1730 <para></para> 1353 1731 1354 1732 <sect2 id="plugin_developer.other.authentication"> 1355 <title>Authentication plug ins</title>1733 <title>Authentication plug-ins</title> 1356 1734 <para> 1357 1735 This documentation is only available in the old format. … … 1371 1749 1372 1750 <sect2 id="plugin_developer.other.unpacker"> 1373 <title>File unpacker plug ins</title>1751 <title>File unpacker plug-ins</title> 1374 1752 <para> 1375 1753 TODO … … 1379 1757 1380 1758 <sect1 id="plugin_developer.example"> 1381 <title>Example plug ins (with download)</title>1759 <title>Example plug-ins (with download)</title> 1382 1760 <para> 1383 1761 <para>
Note: See TracChangeset
for help on using the changeset viewer.