head	1.11;
access;
symbols;
locks; strict;
comment	@# @;


1.11
date	2001.08.30.18.19.36;	author leonardr;	state Exp;
branches;
next	1.10;

1.10
date	2001.08.29.16.04.53;	author leonardr;	state Exp;
branches;
next	1.9;

1.9
date	2001.08.25.00.52.55;	author leonardr;	state Exp;
branches;
next	1.8;

1.8
date	2001.08.25.00.51.38;	author leonardr;	state Exp;
branches;
next	1.7;

1.7
date	2001.08.25.00.50.45;	author leonardr;	state Exp;
branches;
next	1.6;

1.6
date	2001.08.21.22.24.43;	author leonardr;	state Exp;
branches;
next	1.5;

1.5
date	2001.08.13.20.53.03;	author leonardr;	state Exp;
branches;
next	1.4;

1.4
date	2001.08.10.19.51.10;	author leonardr;	state Exp;
branches;
next	1.3;

1.3
date	2001.08.10.19.44.06;	author leonardr;	state Exp;
branches;
next	1.2;

1.2
date	2001.08.10.19.40.21;	author leonardr;	state Exp;
branches;
next	1.1;

1.1
date	2001.08.10.14.30.26;	author leonardr;	state Exp;
branches;
next	;


desc
@@


1.11
log
@Updated doc to reflect the latest config changes.
@
text
@<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>

<head>
 <title>The Helm Component Integration Guide</title>
</head>

<body>

<h1>The Helm Component Integration Guide</h1>
Daniel Rall &lt;dlr at collab dot net&gt;<br>
Leonard Richardson &lt;leonardr at collab dot net&gt;<br>
<small>$Id: index.html,v 1.10 2001/08/29 16:04:53 leonardr Exp $</small>

<a name="Abstract"><h2>Abstract</h2></a>

 <p>This guide provides a comprehensive overview of integrating
 independent systems with Helm, and of creating new components
 specifically for use with Helm. The points of integration are
 discussed, as are the pros and cons of integrating an application
 with Helm (versus writing an application specifically for Helm) and
 the ways by which the Helm interface to a component is to be set up
 and configured.

 <p><i>[Note: The following section describes a proposed
 implementation of component integration and configuration for the
 Tigris 1.3 release. Only parts of this system are relevant to
 1.2]</i>

<h2>Table of Contents</h2>

<ol>
 <p><li><a href="#Points of Integration">Points of Integration</a>
 <p><li><a href="#Build vs. Adapt">Build vs. Adapt</a>
 <p><li><a href="#Three Ways of Integrating Components">Three Ways of Integrating Components</a>
 <p><li><a href="#Component Directory Structure">Component Directory Structure</a>
 <p><li><a href="#Adaptor Directory Structure">Adaptor Directory Structure</a>
 <p><li><a href="#Proposed Additions">Proposed Additions</a>
 <p><li><a href="#Conclusion">Conclusion</a>
</ol>

<a name="Points of Integration"><h2>Points of Integration</h2></a>

 <p>Whether an existing piece of software is being integrated into
 Helm, or a new one is being written from scratch as a Helm component,
 there are several major points of integration:

 <ol>
  <p><li><a href="#auth">Authentication</a></li>
  <p><li><a href="#access">Access Control</a></li>
  <p><li><a href="#shared">Shared Objects</a></li>
  <p><li><a href="#event">Event Propagation</a></li>
  <p><li><a href="#search">Search</a></li>
  <p><li><a href="#ui">User Interface</a></li>
 </ol>

 <p>To achieve integration with the Helm API, you must make at least
 rudimentary use of Helm's authentication and access control
 mechanisms. The other integration points are optional (though a tight
 integration will require use of all integration points).</p>

 <h3><a name="auth">Authentication</a></h3>

  <p>Authentication of users accessing Helm-based systems usually
  occurs through login via a web-based UI.  The code which currently
  handles this activity is the <a
  href="/apidocs/org/tigris/helm/domain/TLogin.html">TLogin</a>
  servlet, which in turn calls out to the <a
  href="/apidocs/org/tigris/helm/tool/SessionManager.html">SessionManager's
  init() method</a> upon successful user authentication.  Though it
  is possible to plug in other authentication mechanisms (i.e. X.509
  certs), the hook to facilitate this process has not yet been
  clearly defined.  The existing hook for external authentication
  mechanisms is a Helm-specific
  <a href="http://jakarta.apache.org/turbine/">Turbine</a> service
  interface <a
  href="/apidocs/org/tigris/helm/tool/IdentityVerificationService.html">implementation</a>.</p>

 <h3><a name="access">Access Control</h3></a>

  <p>Helm's access control system is both the most flexible and the
  most complex part of the system.  <a
  href="/docs/permissions.html">The permission system</a> has a
  user/role/nested group architecture, which restricts users to the
  operations they are allowed to perform in a given project.

  <p>For an integrated tool to provide permission-controlled
  functionality to each of an installation's projects, it must either
  have some internal notion corresponding to Helm's projects (as
  Scarab does), or a separate application data store must be set up
  for each project via a listener (as is done with CVS and
  Issuezilla).</p>

  <p>You can make permission calls using Helm's AccessControlList
  class (if your component compiles against the Helm JAR) or by using
  Helm's <code>permission</code> <a
  href="services_xmlrpc.html">XML-RPC handler</a>.

 <h3><a name="shared">Shared Objects</h3></a>

  <p>In addition to an access control handler, Helm has an XML-RPC
  handler which lets you obtain information about Helm objects via
  XML-RPC. An integrated tool should obtain all of its project and
  user account information from Helm. This may require storing such
  information in the application's internal format (for instance, if
  there are special application-specific users which do not have Helm
  accounts), which is fine so long as changes to the Helm data are
  always reflected in the application.</p>

  <p>You can get user account information using Helm's
  <code>user</code> <a href="services_xmlrpc.html">XML-RPC
  handler</a>.  Other handlers will be forthcoming.

  <p>As with access control, if your component compiles against the
  Helm JAR, you can use Helm business objects natively.

 <h3><a name="event">Event Propagation</a> 
  [<a href="event.html">More info</a>]</h3>

  <p>Every component interfaces to Helm through an implementation of
  an event listener. Each implemented method of a registered listener
  is called when the appropriate Helm event happens; for instance,
  <code>projectDeleted</code> is called after the Helm deletion of a
  project. Any given interface probably needs at least a
  <code>projectAdded</code> and a <code>projectDeleted</code>
  implementation so that the resources for a project can be
  initialized and destroyed.

  <p>Your component's listener will be automatically registered with
  the Helm event propagator, provided your <a
  href="#conf.TurbineResources.properties">TurbineResources.properties</a>
  file is properly set up.

  <p>For more information, please read the <a href="event.html">event
  propagation architecture doument</a>.

  <h3><a name="search">Search</a> [<a href="search.html">More info</a>]</h3>

  <p>A component may specify an implementation of the
  <code>SearchPlugin</code> interface. Implementing a
  <code>SearchPlugin</code> implies implementing configuration details
  regarding what in your component is searchable. Read <a
  href="search.html">the search architecture document</a> for more
  information.

 <a name="ui"><h3>User Interface</h3></a>

  <p>Certain parts of Helm iterate over components, looking for a
  specific Velocity template and parsing it if a component provides
  it.

  <ul>

   <p><li>ToolNav.vm 

       <p>Parsed by the Project_Nav template. Provides a link to the
       URL intended to serve as the 'main menu' of the component.

   <p><li>PendingActions.vm
       <p>Parsed by the StartPage servlet. Displays linked descriptions
       of component-specific pending actions for the logged-in user.

   <p><li>Search.vm 
      <p>Parsed by the Search servlet. Provides component-specific
      options for fine-grained search. If a component specifies no
      Search.vm, Helm will interrogate the component's
      <code>SearchPlugin</code> to find out its search capabilities
      (this is actually a better idea than making an Search.vm, since
      it means you don't have to keep the template up to
      date. However, it's there if you need it).

   <p><li>Options.vm
       <p>Parsed by the ProjectOptions servlet. Displays a partial
       form allowing options to be set for the component. If a
       component specifies no Options.vm, Helm will generate one using
       that component's HELM_ATTRIBUTE entries (as with Search.vm, this
       is ususally better than writing another template (which you then
       have to mantain) just because you can).
  </ul>

<a name="Build vs. Adapt">
 <h2>Build vs. Adapt</h2>
</a>

 <p>Should you build a new Helm component or adapt an existing
 component to the task? It depends on which component you're
 considering adapting, and how tight you want the integration to be.

 <p>There are four features of a component which greatly simplify
 integration of a piece of software with Helm (in fact, all but the
 first one greatly simplify integration with almost anything else, and
 changes to facilitate them will most likely be welcomed by the
 mantainers of the project).  Helm, Turbine, and Torque together give
 you most of the framework you need for a web-based software
 engineering tool, so unless the tool you want to adapt is complicated
 or scores well on more than one of these counts, it may be faster to
 reimplement the same functionality.

<ol>

 <p><li>Does it have a concept of projects (or CVS directories, or
 anything for which in Tigris there is a one-to-one mapping to
 projects), and of associating its artifacts with a particular
 project? (Bonus points for nested projects) Otherwise, you'll have to
 create a data store for each Helm project, and use the wrapper to
 swap in the appropriate one on a per-request basis.

 <p><li>Is it able to go to another piece of software for its user
 authentication? Otherwise, you'll have to add this capability or
 cause your users to suffer a double login. Components with no concept
 of user logins do not have this problem.

 <p><li>Is it able to go to another piece of software for its user
 account information? Otherwise, you'll have to add this capability or
 have your listener vigilantly keep your component's internal user
 representation in sync with Helm's. You should also disable or hide
 that portion of the user account editing information which duplicates
 functionality found in Helm. Components with no concept of user
 accounts do not have this problem.

 <p><li>Is it able to go to an outside piece of software for its
 access control? Otherwise, you'll have to add this capability, have
 your listener keep your component's internal representation of user
 permissions in sync with Helm's, or make do with the page-level
 permission checking provided by your wrapper class[es]. It is a lot
 of work to add pluggable access control to a component without
 introducing an implicit dependency on Helm.

</ol>

<h4>Advantages and Disadvantages of Building</h4>

<p>The advantages of building a component for Helm are tighter
integration and faster development time (versus implementing the same
functionality from scratch, and often versus getting the desired level
of integration between Helm and an existing component). The
disadvantage is that you won't have a standalone component (since it
requires Helm), which may limit your audience.

<p>As you might expect, for adapting an existing component to Helm,
the advantages and disadvantages are largely reversed.

<h4>Advantages of Adaptation</h4>

 <ul>

  <p><li>You get the usage of the existing code base (how much of an
  advantage this actually is depends on the quality of the code and
  the degree to which you plan to support the application in the
  future).

  <p><li>You get the advantage of whatever existing user base the
  component has, and since the component can run standalone that user
  base will probably be larger than it would be if it had Helm as a
  dependency. Larger user base == more development and more bug fixes.

 </ul>

<h4>Disadvantages of Adaptation</h4>

 <ul>

  <p><li>Integration with Tigris will tend to be looser, and in the
  worst case will be little more than a branding wrapper around the
  original functionality.

  <p><li>The adaptor must be kept up to date with functionality added
  to the component. It's not quite fair to put this as a disadvantage
  of adaptation, since this is also true of components written for
  Helm, but it's easier to keep the adaptor up to date when the
  adaptor is in the same place as the code it's adapting.

  <p><li>You will probably have to do work on the component to get it to
  play nicely with Helm, especially if it scores poorly on the four
  points listed above. Depending on how tight you want the integration
  to be, some points may not be relevant (for instance, if page-based
  access control is good enough, you can do all the access control in
  the Helm-dependant wrapper class), but in general, the more
  integration you need, the more work it will take.

  <p><li>The source code for the component may not be available, or you
  might be forbidden from changing it. This means you can't make any
  of the changes that make tight integration easier. Of course, if you
  have to integrate <i>this particular component</i> with Helm,
  writing another component to do the same thing is not an option
  anyway.

 </ul>

<a name="Three Ways of Integrating Components">
 <h2>Three Ways of Integrating Components</h2>
</a>

 <p>There are three different processes which have as their end result
 a component integrated with Helm. This section summarizes each one,
 citing one or more examples, and describing how best to attach a
 component of each type to the major Helm integration points.

 <p>Each process involves writing an adaptor, which is a chunk of
 configuration and Java code which makes your software work with
 Helm. If the Helm adaptor is not included with the component, it
 should be made a project on tigris.org and put into the "adaptors"
 category. The recommended name for a component's adaptor is
 "[component]-helm".

<h3>Writing a servlet-based component specifically for Helm</h3>

 <p><b>Example:</b> <a href="http://nidaba.tigris.org/">Nidaba</a>

 <p>This is the easiest case, since you can design your tool to
 conform to Helm's assumptions, and you can use everything in the Helm
 JAR to implement your tool. If you use Torque to handle your business
 objects (highly recommended), you can also make your database tables
 have foreign keys in Helm tables. Finally, the same package can house
 both your component and its Helm adaptor.

 <h4>How to Implement</h4>

  <ul>

   <p><li><b>Authentication:</b> You get this automatically when your
   servlets subclass HelmServlet (actually, you should subclass
   HelmServlet with a ComponentServlet and have all your servlets
   subclass that). Logging in to Helm will give a user authenticated
   access to your component's servlets.

   <p><li><b>Access Control:</b> You can instantiate and use Helm
   AccessControlList objects directly.

   <p><li><b>Shared Objects:</b> You can use instantiate and use OM
   objects directly.

   <p><li><b>Event Propagation:</b> Your listener class can reside in
   the same class structure as your component. It can call both Helm
   methods and methods of your component.

  </ul>

<h3>Adapting a servlet-based component not written for Helm</h3>

 <p><b>Example:</b> <a href="http://eyebrowse.tigris.org/">Eyebrowse</a>

 <p>You will need to create an adaptor which mediates between your
 component and Helm. This adaptor will contain all the Helm
 configuration for the component, as well as the listener
 implementation for the component.

 <p>You will also need to write one or more wrapper servlets which
 subclass HelmServlet and call the component's servlets. It seems
 possible to do all the wrapping in a single servlet, but that's not
 how Eyebrowse does it so I'm not sure.

 <h4>How to Implement</h4>

  <ul>

   <p><li><b>Authentication:</b> The wrapper classes will subclass
   HelmServlet, so logging in to Helm will give a user authenticated
   access to your component's servlets.

   <p><li><b>Access Control:</b> The wrapper classes can make direct
   AccessControlList calls. Your component must either rely on this or
   make use of an pluggable permission checker.

   <p><li><b>Shared Objects:</b> The wrapper classes can use Helm OM objects
   directly; they must provide some way of giving the neccessary
   information to the component's servlets.

   <p><li><b>Event Propagation:</b> Your listener class must reside in
   the adaptor component. It can call both Helm methods and methods of
   your component.

 </ul>

<h3>Adapting a non-servlet-based component not written for Helm</h3>

 <p><b>Examples:</b> <a
 href="http://issuezilla.tigris.org/">Issuezilla</a>, CVSWeb, CVS

 <p>This is the most difficult case. It's similar to the previous
 case, with the additional complication that the component does not
 use servlets, and is probably not even written in Java.

 <p>The adaptor will need to subclass the HelmNoodle class; you will
 be using Noodle to wrap the functionality of the
 component. HelmNoodle will check for a particular permission on every
 page access; this permission is specified in the HelmNoodle subclass
 config file and is the permission you must have to use the component
 at all. This will probably not be enough permission checking for your
 component, so you will either have to do page-specific checking in
 the HelmNoodle subclass, or plug Helm's permission checker into an
 abstract permission checker within the component.

 <p>You will need to add rewrite rules into the component's httpd
 configuration which transforms a request for a component page into a
 request for your HelmNoodle subclass.

 <h4>How to Implement</h4>

  <ul>

   <p><li><b>Authentication:</b> The HelmNoodle subclass will subclass
   HelmServlet, so logging in to Helm will give a user authenticated
   access to all your component's pages, wrapped through Noodle. If
   your component, like CVS, does not rely on a Web interface, you
   will need to give it pluggable authentication and write an
   authentication module connecting it to Helm.

   <p><li><b>Access Control:</b> The HelmNoodle subclass can make direct
   AccessControlList calls. Your component must either rely on this or
   make use of an abstract permission checker.

   <p><li><b>Shared Objects:</b> The HelmNoodle subclass can use Helm OM
   objects, but the wrapped application cannot. The subclass will have
   to turn the information represented by a request's OM objects into
   a form usable by the wrapped application.

   <p><li><b>Event Propagation</b> Your listener must reside in the
   adaptor. It can call Helm methods, and either call methods of your
   component (if your component is written in Java), or run scripts
   written to drive your component (the scripts should also live in
   the adaptor).

 </ul>

<a name="Component Directory Structure">
 <h2>Component Directory Structure</h2>
</a>

 <p><b>Note:</b> This is the suggested directory structure for a Java
 servlet application written with Helm in mind. If such an application
 contains its own adaptor (as will usually be the case), you will see
 the adaptor directory structure (described next section) overlaid on
 top of this structure.

 <blockquote>
  <code>
   <pre>
    [component]/
      build/
        build.xml
      htdoc/look/www/
        master/
          [servletname]Tasks.html (for servlets that show task bar)
          [component-specific templates, e.g., email templates]
        includes/
          [servletname]Help.vm (for servlets with sticky help notes)
      src/
        java/
          [component Java package]/
            om/
              [component business objects]
            tool/
              [additional objects to place in context]
            [servlet dirs]/
              [.java file for each servlet]
      sql/
        schema
          [component]-schema.xml
      templates/
         [component Java package]/
           [servlet dirs]/
             [.vm files for each servlet]
      www/
        [component web site files]
        docs/
          [component developer documentation files]
   </pre>
  </code>
 </blockquote>

 <h3>Explanation</h3>

  <p>Using the suggested directory structure allows the component to
  to advantage of the hooks supplied by Helm (and its instance) for
  functional extension.</p>

  <h4><code>build</code> directory</h4>

   <p>The build scripts powering any makefiles scattered throughout the
   component directory hierarchy live here.  Helm uses <a
   href="http://jakarta.apache.org/ant/">Ant</a> as much as possible to
   handle its build; components and adaptors should as well.</p>

  <h4><code>java</code> directory</h4>
 
   <p>Contains the Java source code for your component; servlets and
   tools. We <i>strongly recommend</i> that component implementations
   consist of Java as much as possible.</p>

  <h4><code>sql/schema</code> directory</h4>

    <p>Contains the <a
    href="http://jakarta.apache.org/turbine/torque/">Torque</a> XML
    schema for your component.  References to key values from tables
    in foreign database schemas (such as tables from Helm) are
    currently handled using indices in the component schema.  The plan
    is to add foreign database table support to Torque and its
    DTD.</p>

    <p>We <i>strongly recommend</i> that you use Torque in writing
    components (and web apps in general). It saves a lot of busy work
    and lets you get down to implementing servlets.

   <h4><code>templates/[component Java package]</code> directory</h3>

    <p>Contains Velocity templates for the component's servlets.</p>

   <h4><code>www</code> directory</h4>

    <p>The component's web site for [component].tigris.org. The
    <code>docs</code> subdirectory contains developer
    documentation.</p>

<a name="Adaptor Directory Structure"><h2>Adaptor Directory Structure</h2></a>

 <p><b>Note:</b> If the adaptor comes with the component, then these
 directories are to be found in the component directory tree with the
 rest of the component.

 <blockquote>
  <code>
   <pre>
    [component]-helm/
      build/
        build.sh
        build.xml
      conf/
        [component].ant.properties
        <a href="#conf.servlets">[0-9][0-9][component].servlets</a>
        <a href="#conf.TurbineResources.properties">[0-9][0-9][component].TurbineResources.properties</a>
        <a href="#conf.zone.properties">[0-9][0-9][component].zone.properties</a> (if needed)
        <a href="#conf.httpd.conf">[0-9][0-9][component].httpd.conf</a> (if needed)
      data/
        htdoc/www/www/docs/ (component-specific end-user online help pages)
      htdoc/look/www/master/
        [templates for Helm integration]
      src/
        java/
          [component Java package]/
            helm/
              [component]Listener.java (suggested location)
              [component]SearchPlugin.java (suggested location)
      scripts/
        migration/
          [versionnumber]/
      sql/
        [component Java package]/
          LoadOrder.lst
          [files specified in this, instance, or Helm LoadOrder.lst]
          [importantly, <a href="#sql.Action">SQL for component-specific actions and role assignments</a> and
          <a href="#sql.Attribute">SQL for component-specific attributes</a>.]
   </pre>
  </code>
 </blockquote>

<h3>Explanation</h2>

 <h4><code>conf</code> directory</h4>

  <p>Component-specific configuration to be copied to your Tigris
  instance's <code>site/conf/</code> directory during installation.
  Common Ant variables are specified via a
  <code>[component].ant.properties</code> file.  Configuration for
  provided servlets is added via <code>[two digit
  number]servlets</code>, with a lower number indicating higher
  precendance in final servlets configuration file.</p>

  <ul>
   <p><li><a name="conf.servlets">conf/[0-9][0-9][component].servlets</a>

       <p>If your component is written using Java servlets, this
       contains the names and classes of the component servlets (or
       the adaptor servlets which wrap them, if there are wrapper
       servlets). Otherwise, it contains the name and class of the
       HelmNoodle subclass which wraps your non-servlet pages.

   <p><li><a name="conf.TurbineResources.properties">conf/[0-9][0-9][component].TurbineResources.properties</a>

       <p>If your component makes use of any Fulcrum services (either
       built-in services or services written for your application),
       this is the configuration file in which you should name those
       services.

       <p>This file is also where you will put component-specific
       configuration:

       <ul>
        <p><li><code>component.humanReadableName.[component]</code>:
        Helm will use the value of this attribute when displaying the
        name of the component to a user, eg. "CVS Configuration
        Options".

        <p><li><code>component.[component].listener</code>: Value
        should be the fully-qualified name of a class which will serve
        as your component's listener to Helm events. Though this item
        is optional, you will need to implement a listener to get any
        kind of meaningful integration with Helm.

        <p><li><code>component.[component].searchPlugin</code>:
        Value should be the fully-qualified name of a class which
        implements the Helm interface
        <code>SearchPlugin</code>. Though this item is optional,
        you will need to implement a <code>SearchPlugin</code> to
        allow your component's artifacts to be searched using Helm's
        unified search.

        <p><li><code>component.[component].servlet.[servlet].properties</code>:
        These configuration blocks are where you put your servlet
        configuration (whether for servlets provided by your
        application or the one servlet which subclasses
        HelmNoodle). Values specified here will tell HelmServlet how
        to treat your servlet. <i>[TODO: explain servlet configuration
        in another doc.]</i>

        <p><li><code>services.BOFactoryService.current[business object
        type]</code>: You can program Helm's <code>BOFactoryService</code> from
        your component. Helm will probe each servlet request for
        certain strings corresponding to the IDs of business objects
        which it will then initialize and put into the context. 

        <p>There are several sub-options; it is easiest to explain
        them by the use of an example code block:

	<p><blockquote><code>
         services.BOFactoryService.currentPurpleFoo.peer=org.tigris.component.om.FooPeer<br>
         services.BOFactoryService.currentPurpleFoo.instantiationMethod=getPurpleFoo<br>
         services.BOFactoryService.currentPurpleFoo.parameterKey=purpleFooID<br>
         services.BOFactoryService.currentPurpleFoo.default=currentFoo<br>
         services.BOFactoryService.currentPurpleFoo.subclass=org.tigris.component.om.PurpleFoo
        </code></blockquote>

        <p>On every servlet request, <code>BOFactoryService</code>
        will check to see if a value for "purpleFooID" was provided
        (eg. "purpleFooId=3"). If a value was provided,
        <code>BOFactoryService</code> will get the value as a String
        and call org.tigris.component.om.FooPeer.getPurpleFoo(String)
        using the value as argument. If the resulting object is a
        PurpleFoo and not just a regular Foo, it will be placed into
        the context with the key "currentPurpleFoo"; if it's just a
        regular Foo or some non-purple subclass of Foo, an exception
        will be thrown.

        <p>On the other hand, if no value was provided for
        "purpleFooID", <code>BOFactoryService</code> will look in the
        context for a "currentFoo". If currentFoo is a PurpleFoo
        object and not a regular Foo or some non-purple subclass of
        Foo, it will be placed into the context again as
        "currentPurpleFoo".

	<p>Only <code>peer</code> and <code>parameterKey</code> are
	required in any given configuration block. If you do not
	specify <code>instantiationMethod</code>,
	<code>BOFactoryService</code> will assume you want a method
	called <code>getInstance</code>. If you do not specify
	<code>default</code> <code>BOFactoryService</code> will not
	try to find a default if the value corresponding to
	<code>parameterKey</code> comes up empty. If you do not
	specify <code>default</code>, <code>BOFactoryService</code>
	will not check the class of the business object returned by
	<code>instantiationMethod</code> or filed under
	<code>default</code> in the context.

        <p>You can also specify "[business object type]" as a value
        for the servlet-specific "requiredBusinessObject" property,
        which will cause an error to occur if a user tries to access
        the servlet without specifying a value for "[business object
        type]ID". This, combined with a <code>BOFactoryService</code>
        configuration block for the business object type, will allow
        your template to assume that a "current[business object type]"
        variable exists in the context.
       </ul>

   <p><li><a name="conf.zone.properties">conf/[0-9][0-9][component].zone.properties </a>

       <p>Contains Java properties for your component. Since there is
       no way to change a property beyond editing this file and
       reconfiguring, we recommend using this file for configuration
       settings which are set at install time, and specifying as
       attributes settings which should be changeable from a Web
       interface.
   
   <p><li><a name="conf.httpd.conf">conf/[0-9][0-9][component].httpd.conf</a>

       <p>Contains Apache server configuration information for your
       component. This includes rewrite rules for routing requests for
       a component's non-servlet pages to that component's HelmNoodle
       subclass.
  </ul>


 <h4><code>data</code> directory</h4>

  <p>Initial data files specific to your component.  These should be
  copied to the <code>$SANDBOX/data/</code> directory at installation
  time.  The content under <code>data/htdoc</code> is able to take
  advantage of Helm's remote branding functionality.
  <code>data/htdoc/look/www/master/</code> is for additional master
  templates (another nice hook into Helm).</p>


 <h4><code>sql/[component Java package]</code> directory</h4>

  <p>Scripts to perform initial database population.  The file
  <code>LoadOrder.lst</code> is used as the "callback" hook by Helm's
  <code>create_tigris_database</code> script to specify additional
  files to run for the component.</p>

  <p>A few of the SQL files are especially important for
  components. They are described below.

  <p><li><a name="sql.Action">SQL for component-specific actions and role
  assignments</a>

   <p>To tie your component into Helm's permission system, you will
   probably need to define some new actions. These should go into
   populate_Action.sql.

   <p>To pick good actions, think about the use cases not only for
   your component, but for the general sort of functionality provided
   by that component. Name your actions according to the sort of
   functionality provided by your component (eg. "Issue Tracking",
   "Version Control", "Document") so that another component which
   covers the same ground as your component can use the same
   actions. In the future, one project on a site may be using your
   component while another makes use of a different component to do
   the same thing. In such a case, the same role in the different
   projects should convey the same abilities in each.

   <p>Your actions won't have any effect unless you grant them to
   roles (or unless the users of the site create new roles with your
   actions). For this reason, you need a
   populate_RoleActionResource.sql file as well as
   populate_Action.sql. You can specify the roles by name, using the
   names of the default roles found in Helm's populate_Role.sql, but
   if at all possible it's better to tie your action to one or more
   Helm actions, granting your action to all the roles which have the
   others. This way, a site which gets upgraded to use your component
   will have user-created roles updated in ways that make
   sense. [<i>HELP: This has security implications, but only as
   regards access to the new functionality. Should we not recommend
   this?</i>]

   <p>Note that all of this is separate from the issue of getting your
   component to use Helm's system to do permission checks.

  <p><li><a name="sql.Attribute">SQL for component-specific attributes</a>

   <p>Helm provides an interface for centralized editing of project
   attributes. Your component can specify an attribute which will be
   made part of this interface. The listener for your component will
   be notified of changes to its attributes, as well as to Helm
   attributes (or, if your component already depends on Helm, you can
   just look up the current values of attributes).

   <p>Your attributes should be put in the file
   populate_Attribute.sql. Each attribute has a name, a default value,
   and an action which is to be checked in a project before allowing a
   user to change that attribute for that project.
  </ul>

 <h4><code>templates/[component Java package]/includes</code> directory</h4>

  <p>Contains the template fragments for <a href="#ui">user interface
  integration.</a></p>

<a name="Proposed Additions"><h2>Proposed Additions</h2></a>

 <ul>

  <p><li>Operations-oriented integration points: logging, UNIX user file
  ownership, monitoring interfaces, etc.

  <p><li>Short case studies of integration, in particular with regards
  to permissions (do as separate pages).

  <p><li>Into which integration category does Scarab fall? It's Java
  servlets and the goal is to give it tight integration with Helm in
  the presence of Helm, but also to allow it to operate standalone. A
  new category may be neccessary for this, or a section added to the
  first category.

 </ul>

<a name="Conclusion"><h2>Conclusion</h2></a>

 <p>You should now know the basics of writing components for Helm and
 of integrating foreign components into Helm. Any discoveries or rules
 of thumb made during the integration process should go onto this page
 or a related page.

</body>
</html>@


1.10
log
@Updated doc to reflect move from .properties files to TurbineResources.properties.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.9 2001/08/25 00:52:55 leonardr Exp $</small>
d215 13
a227 13
 have your <code>HelmListener</code> vigilantly keep your component's
 internal user representation in sync with Helm's. You should also
 disable or hide that portion of the user account editing information
 which duplicates functionality found in Helm. Components with no
 concept of user accounts do not have this problem.

 <p><li>Is it able to go to an outside piece of software for its access
 control? Otherwise, you'll have to add this capability, have your
 <code>HelmListener</code> keep your component's internal
 representation of user permissions in sync with Helm's, or make do
 with the page-level permission checking provided by your wrapper
 class[es]. It is a lot of work to add pluggable access control to a
 component without introducing an implicit dependency on Helm.
d594 15
a608 1
        <p><li><code>component.servlets.[servlet].properties</code>:
d610 5
a614 3
        configuration. Values specified here will tell HelmServlet how
        to treat your servlet. <i>[TODO: explain servlet
        configuration in another doc.]</i>
a671 14

        <p><li><code>component.listener.[component]</code>: Value
        should be the fully-qualified name of a class which will serve
        as your component's listener to Helm events. Though this item
        is optional, you will need to implement a listener to get any
        kind of meaningful integration with Helm.

        <p><li><code>component.searchPlugin.[component]</code>:
        Value should be the fully-qualified name of a class which
        implements the Helm interface
        <code>SearchPlugin</code>. Though this item is optional,
        you will need to implement a <code>SearchPlugin</code> to
        allow your component's artifacts to be searched using Helm's
        unified search.
@


1.9
log
@Another minor correction.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.8 2001/08/25 00:51:38 leonardr Exp $</small>
d448 9
a456 8
      java/
        [component Java package]/
          om/
            [component business objects]
          tool/
            [additional objects to place in context]
          [servlet dirs]/
            [.java and .properties file for each servlet]
d531 1
a531 1
        <a href="#conf.TurbineResources.properties">[0-9][0-9][component].TurbineResources.properties</a> (if needed)
d593 6
@


1.8
log
@Corrected hypothetical package name.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.7 2001/08/25 00:50:45 leonardr Exp $</small>
d617 3
a619 3
        the context with the key "currentFoo"; if it's just a regular
        Foo or some non-purple subclass of Foo, an exception will be
        thrown.
d622 5
a626 4
        "purpleFooID", <code>BOFactoryService</code> will look in the context for a
        "currentFoo". If currentFoo is a PurpleFoo object and not a
        regular Foo or some non-purple subclass of Foo, it will be
        placed into the context again as currentPurpleFoo.
@


1.7
log
@Changed feature description to reflect what was implemented.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.6 2001/08/21 22:24:43 leonardr Exp $</small>
d600 1
a600 1
        them by the use of an example code block.
d602 1
a602 1
	<blockquote><code>
d607 1
a607 1
         services.BOFactoryService.currentPurpleFoo.subclass=org.tigris.helm.om.PurpleFoo
@


1.6
log
@Updated doc to reflect what was actually implemented.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.5 2001/08/13 20:53:03 leonardr Exp $</small>
d593 46
a638 10
        <p><li><code>component.current[business object type]</code>:
        Value should be the fully-qualified name of a class which will
        be instantiated using as the key any string found in the
        "[business object type]ID" field in the request.

	<p>For example:
	<code>component.currentMyObject=org.tigris.helm.mycomponent.MyObject</code>
	will, if "myObjectID=3" comes in on a request, cause the
	MyObject instance with ID 3 to be available as
	"currentMyObject" in the context.
d644 4
a647 1
        type]ID".
@


1.5
log
@Corrected adaptor layout and component directive name.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.4 2001/08/10 19:51:10 leonardr Exp $</small>
d131 2
a132 1
  href="#conf.components">components</a> file is properly set up.
a528 1
        <a href="#conf.components">[0-9][0-9][component].components</a>
d569 7
a575 1
   <p><li><a name="conf.components">conf/[0-9][0-9][component].components:</a>
d577 9
a585 2
       <p>This is the file which notifies Helm of the existence of the
       component. Valid attribute settings are the following:
d588 1
a588 2

        <p><li><code>components.[component].humanReadableName</code>:
d593 4
a596 4
        <p><li><code>components.[component].current[business object
        type]</code>: Value should be the fully-qualified name of a
        class which will be instantiated using as the key any string
        found in the "[business object type]ID" field in the request.
d599 1
a599 1
	<code>components.mycomponent.currentMyObject=org.tigris.helm.mycomponent.MyObject</code>
d610 1
a610 1
        <p><li><code>components.[component].listener</code>: Value
d616 1
a616 1
        <p><li><code>components.[component].searchPlugin</code>:
a622 1

a623 15

   <p><li><a name="conf.servlets">conf/[0-9][0-9][component].servlets</a>

       <p>If your component is written using Java servlets, this
       contains the names and classes of the component servlets (or
       the adaptor servlets which wrap them, if there are wrapper
       servlets). Otherwise, it contains the name and class of the
       HelmNoodle subclass which wraps your non-servlet pages.

   <p><li><a name="conf.TurbineResources.properties">conf/[0-9][0-9][component].TurbineResources.properties</a>

       <p>If your application makes use of any Fulcrum services (either
       built-in services or services written for your application),
       this is the configuration file in which you should name those
       services.
@


1.4
log
@Put more info link in <h3> tag.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.3 2001/08/10 19:44:06 leonardr Exp $</small>
d537 6
a542 5
      java/
        [component Java package]/
          tool/
            adaptor/
              [component]Listener.java (suggested location)       
d576 4
a579 3
        <p><li><code>component.humanReadableName</code>: Helm will use
        the value of this attribute when displaying the name of the
        component to a user, eg. "CVS Configuration Options".
@


1.3
log
@Corrected link.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.2 2001/08/10 19:40:21 leonardr Exp $</small>
d136 1
a136 1
 <a name="search"><h3>Search</h3></a> [<a href="search.html">More info</a>]
@


1.2
log
@Another piece of the puzzle: definition of the search plugin architecture.
@
text
@d13 1
a13 1
<small>$Id: index.html,v 1.1 2001/08/10 14:30:26 leonardr Exp $</small>
d117 1
a117 1
 <h3><a name="event>Event Propagation</a> 
@


1.1
log
@Integration documents now have their own directory. Also added a new event propagation architecture document to the new directory.
@
text
@d13 1
a13 1
<small>$Id: integration.html,v 1.24 2001/08/07 22:40:45 leonardr Exp $</small>
d117 1
a117 1
 <a name="event"><h3>Event Propagation 
a118 1
 </a>
d129 1
a129 1
  <p>Your component's Listener will be automatically registered with
d136 1
a136 1
 <a name="search"><h3>Search</h3></a>
d139 5
a143 5
  <code>ComponentSearch</code> interface. Implementing a
  <code>ComponentSearch</code> implies implementing configuration
  details regarding what in your component is searchable; the details
  of this have yet to be worked out. <i>[In particular, what about
  indexing?]</i>
d162 9
d175 3
a177 4
       that component's HELM_ATTRIBUTE entries (this is actually a
       better idea than making an Options.vm, since it means you don't
       have to keep Options.vm up to date. However, it's there if you
       need it).
d602 1
a602 1
        <p><li><code>components.[component].ComponentSearch</code>:
d605 2
a606 2
        <code>ComponentSearch</code>. Though this item is optional,
        you will need to implement a <code>ComponentSearch</code> to
a722 2

  <p><li>The ComponentSearch specification needs to be designed,
@

