You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by mp...@apache.org on 2001/12/17 17:31:36 UTC

cvs commit: jakarta-turbine-fulcrum/xdocs changes.xml

mpoeschl    01/12/17 08:31:36

  Modified:    xdocs/stylesheets project.xml
  Added:       xdocs/howto cache-service.xml velocity-service.xml
                        jsp-service.xml xslt-service.xml naming-service.xml
                        localization-service.xml upload-service.xml
                        pool-service.xml security-service.xml
                        xmlrpc-service.xml template-service.xml
                        intake-service.xml factory-service.xml
                        mimetype-service.xml
               xdocs    changes.xml
  Log:
  copy service howtos from turbine-2
  
  Revision  Changes    Path
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/cache-service.xml
  
  Index: cache-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Global Cache Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Global Cache Service">
  
  <p>
  The Global Cache Service provides an object cache that you can call
  from anywhere in your application to temporarily store objects. An example
  of its use may be to store the names of Countries that you use throughout
  your application to populate a look up list. If you normally store the
  information about Countries in a database, you can increase the performance
  of your application by using the Cache and decreasing the number of hits
  against the database.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.GlobalCacheService.classname=org.apache.turbine.services.cache.TurbineGlobalCacheService
  .
  .
  .
  
  # -------------------------------------------------------------------
  #
  #  C A C H E   S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # Interval at which the cache will be checked. The default is
  # 5000ms or 5 seconds.
  
  services.GlobalCacheService.cache.check.frequency = 5000
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <source><![CDATA[
  
  GlobalCacheService gs = null;
  try
  {
      /*
       * Look for the item in the cache.
       * If it doesn't exist or the item is stale,
       * the cache will throw an exception.
       */
      gs = (GlobalCacheService)TurbineServices.getInstance()
          .getService(GlobalCacheService.SERVICE_NAME);
  
      CachedObject obj = gs.getObject("cached_object");
  
      data.setMessage( data.getScreen() + " Got " +
          obj.getContents().toString() + " from global cache!" );
  }
  catch(ObjectExpiredException gone)
  {
      /*
       * Add the item to the cache.
       */
      gs.addObject("cached_object",
          new CachedObject("in_the_cache",5000));
  
      data.setMessage( data.getScreen() +
          " Refreshed/or added new item to" +
          " the cache! Expires in 5 seconds" );
  }
  
  ]]></source>
  
  <p>
  You can also place an expiration time on your objects so the Service will
  automatically remove them when they expire. If you don't specify an expiration
  time, the Service uses the default time set by the property
  <em>cache.check.frequency</em> in the TurbineResources.properties
  file. To see an example, look at the file <strong>TestGlobalCache.java</strong>
  located in the actions folder.
  </p>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/velocity-service.xml
  
  Index: velocity-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Velocity Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Velocity Service">
  
  <p>
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.VelocityService.classname=org.apache.turbine.services.cache.TurbineVelocityService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  V E L O C I T Y  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # The location of Velocity configuration file, relative to webapp root
  # These properties will override the default properties set by Velocity.
  # You should specify the path to the templates directories as well as 
  # the path to the log file and they should also be relative to webapp root
  
  services.VelocityService.template.extension=vm
  services.VelocityService.default.page = VelocityPage
  services.VelocityService.default.screen=VelocityScreen
  services.VelocityService.default.layout = VelocityECSLayout
  services.VelocityService.default.navigation=VelocityNavigation
  services.VelocityService.default.error.screen = VelocityErrorScreen
  services.VelocityService.default.layout.template = /Default.vm
  
  services.VelocityService.runtime.log=/logs/velocity.log
  #services.VelocityService.input.encoding=UTF-8
  services.VelocityService.velocimacro.library = GlobalMacros.vm
  
  services.VelocityService.resource.loader = file
  services.VelocityService.file.resource.loader.description = Velocity File Resource Loader
  services.VelocityService.file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
  services.VelocityService.file.resource.loader.path = /templates/app
  services.VelocityService.file.resource.loader.cache = false
  services.VelocityService.file.resource.loader.modificationCheckInterval = 2
  
  services.VelocityService.resource.loader = classpath
  services.VelocityService.classpath.resource.loader.description = Velocity Classpath Resource Loader
  services.VelocityService.classpath.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <source><![CDATA[
  
  ]]></source>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/jsp-service.xml
  
  Index: jsp-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - JSP Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="JSP Service">
  
  <p>
  Turbine supports the use of JSP internally through a Service which
  provides JSP related Modules with access to the JSP engine directly. We
  have another document which gives a <a
  href="../howto/jsp-howto.html">howto</a> on configuration of Turbine to
  use JSP.
  </p>
  
  <p>
  While Turbine supports the use of many templating systems, we definitely
  have our favorite system to use and recommend and that is <a
  href="http://jakarta.apache.org/velocity/">Velocity</a>.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.JspService.classname=org.apache.turbine.services.jsp.TurbineJspService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  J S P  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  services.JspService.template.extension=jsp
  services.JspService.default.page = JspPage
  services.JspService.default.screen=BaseJspScreen
  services.JspService.default.layout = JspLayout
  services.JspService.default.navigation=BaseJspNavigation
  services.JspService.default.error.screen = JspErrorScreen
  services.JspService.default.layout.template = /Default.jsp
  
  services.JspService.templates = /templates/app
  services.JspService.buffer.size = 8192
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <p>
  Please refer to the org.apache.turbine.services.jsp classes for details
  on how to use this service.
  </p>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/xslt-service.xml
  
  Index: xslt-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - XSLT Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="XSLT Service">
  
  <p>
      The XSLT service is a simple way to transform a well-formed
      XML document into web content for your site. This may be
      dynamic or static content. You can easily integrate the
      XSLT service into a Turbine screen module, or you can
      use the existing <strong>org.apache.turbine.modules.layouts.VelocityXslLayout</strong>
      class to produce dynamic content.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.XSLTService.classname=org.apache.turbine.services.xslt.TurbineXSLTService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  X S L T  S E R V I C E
  #
  # -------------------------------------------------------------------
  services.XSLTService.path = /WEB-INF/stylesheets
  services.XSLTService.cache = false
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <p>
    Please look at the <strong>org.apache.turbine.modules.layouts.VelocityXslLayout</strong>
    for an example usage pattern.
  </p>  
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/naming-service.xml
  
  Index: naming-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Naming Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
    <author email="jon@latchkey.com">Jon S. Stevens</author>
   </properties>
  
  <body>
  
  <section name="Naming Service">
  
  <p>
  The Naming Service provides access to JNDI contexts. Please note that if
  you are using Tomcat as your servlet engine and you get errors about
  sealing violations, you may need to read <a
  href="../howto/jboss-howto.html">this document</a>.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.NamingService.classname=org.apache.turbine.services.naming.TurbineNamingService
  .
  .
  .
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <source><![CDATA[
  try
  {
      // Set up the naming provider. This may not always be necessary,
      // depending on how your Java system is configured.
      System.setProperty("java.naming.factory.initial",
        "org.jnp.interfaces.NamingContextFactory");
      System.setProperty("java.naming.provider.url",
        "localhost:1099");
      // Get a naming context
      InitialContext jndiContext = new InitialContext();
  
      // Get a reference to the Interest Bean
      Object ref = jndiContext.lookup("interest/Interest");
  
      // Get a reference from this to the Bean's Home interface
      InterestHome home = (InterestHome)
          PortableRemoteObject.narrow (ref, InterestHome.class);
  
      // Create an Interest object from the Home interface
      m_interest = home.create();
  }
  catch(Exception e)
  {
      out.println("<LI>Context failed: " + e);
  }
  ]]></source>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/localization-service.xml
  
  Index: localization-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Localization Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Localization Service">
  
  <p>
  There is a Turbine service that makes it easy to add localization support
  to your application.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.GlobalCacheService.classname=org.apache.turbine.services.cache.TurbineGlobalCacheService
  .
  .
  .
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  
  <source><![CDATA[
  
  TurbineServices.getInstance().getService(LocalizationService.LOCALIZATION)
      .getString("DISPLAYPROJECTS_TITLE");
  
  ]]></source>
  
  <p>
  Wow. That is a lot of typing. That could be easily shortened to this:
  </p>
  
  <source><![CDATA[
  
  Localization.getString("DISPLAYPROJECTS_TITLE");
  
  ]]></source>
  
  <p>
  The hard example above was given as an example of using Services. The easy
  example is the one that you really should be using. Another cool feature
  of the Localization class is that you can pass in a RunData object like
  this:
  </p>
  
  <source><![CDATA[
  
  Localization.getString(data, "DISPLAYPROJECTS_TITLE");
  
  ]]></source>
  
  <p>
  This has the added effect of using the Accept-Language HTTP header to determine
  which language to display based on what setting the user has defined in
  the browser. Can you say Dynamic Localization? ;-)
  </p>
  
  <p>
  For creating the file where you get the value of the String, please
  see the <em>java.util.ListResourceBundle</em> and
  <em>java.util.ResourceBundle</em> classes for more information.
  <a href="http://java.apache.org/jyve/">Jyve</a> also contains example usage
  of this code because that was the first place where this code was originally
  developed.
  </p>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/upload-service.xml
  
  Index: upload-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Upload Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Upload Service">
  
  <p>
  The Upload Service handles the parsing of multi-part/form-data from POST
  Requests, making the multi-part files available from either memory or from a
  specified location on the file system.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.UploadService.classname=org.apache.turbine.services.upload.TurbineUploadService
  .
  .
  .
  # -------------------------------------------------------------------
  #
  #  U P L O A D  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # Whether the files should be automatically picked up by
  # ParameterParser.
  
  services.UploadService.automatic=false
  
  #
  # The directory where files will be temporarily stored.
  #
  services.UploadService.repository=.
  
  #
  # The maximum size of a request that will be processed.
  #
  services.UploadService.size.max=1048576
  
  #
  # The maximum size of a request that will have it's elements cached in
  # memory by TurbineUploadService class.
  #
  services.UploadService.size.threshold=10240
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <p>
  Change the automatic directive to true. With this set to true any
  multi-part/form-data requests which Turbine fields, will be parsed and the
  appropriate files made available to ParameterParser as FileItem objects. If
  this is set as false, the FileItems will have to be parsed out of RunData
  manually with the method getRequest() available from TurbineUpload.
  </p>
  
  <p>
  Set the remaining values to ones approriate for your installation. On Win32
  file systems for the repository directive, an entry of the form:
  <ul>
    <code>f:\path\to\upload\repository</code>
  </ul>
  is most likely necessary.
  </p>
  
  
  <p>
  Create an HTML form of the type:
  </p>
  
  <source test=""><![CDATA[
  
  <form enctype="multipart/form-data" method="POST">
  <input type="hidden" name="action" value="UploadExample" />
  <input type="file" name="filename">
  <input type="submit" value="upload" />
  </form>
  
  ]]></source>
  
  <p>
  The Upload Service manages if the FileItem is stored in Memory or in the
  Repository specified in TurbineReources.properties. It is also possible to
  overide the TurbineResources setting for the repository by using
  TurbineUpload.getRequest()  to parse the request with a custom repository
  directory. The TurbineUpload object serves as a Facade to the Upload Service
  by making available static methods to manage the upload internally in your
  application. The FileItems can be accessed in an UploadExample Action class by:
  </p>
  
  <source test=""><![CDATA[
      public void doPerform(RunData data, Context context) throws Exception
      {
          //get the ParameterParser from RunData
          ParameterParser params = data.getParameters();
  
          //grab the FileItems available in ParameterParser
          FileItem fi = params.getFileItem("filename");
  
          //do work on the FileItem
          //get the file as a File
          //or outputstream etc.
  
      }
  
  ]]></source>
  
  <p>
  Once a new instance of the FileItem is created many public methods are
  available to work on the object, whether it is in temporary storage as memory or as
  a temporary file on part of the file system. All the temporary storage management and
  clean up occurs behind the scenes and is transparent to the application being
  based on Turbine. There is no need to manually clean up the FileItems as the
  FileItem object doesn't span Requests ( or RunData instances ) and the temporary
  files that use the file system are cleaned up in a finalize() method inherited
  from Object().
  </p>
  
  <p>
  The TurbineUpload object and the FileItem object give all the functionality
  needed to manage this sort of operation or action at the application level.
  For more detailed information on the methods available to deal with uploaded
  files, view the relevant Javadocs for TurbineUpload, ParameterParser and
  FileItem.
  </p>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/pool-service.xml
  
  Index: pool-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Pool Service</title>
    <author email="ilkka.priha@simsoft.fi">Ilkka Priha</author>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Pool Service">
  
  <p>
  The Pool Service extends the functionality of the Factory Service by adding 
  support for pooling objects intantiated from the given class name or
  Class object reference. Pooling of objects stabilizes memory consumption and 
  reduces garbage collection making response times in server applications 
  more predictable.
  </p>
  
  <p>
  When a new instance is requested from the service, it first checks its pool 
  if one is available. If the the pool is empty, a new object will be instantiated 
  from the given class. If the class is specified by its name, the request to create 
  an instance will be forwarded to the Factory Service.
  </p>
  
  <p>
  For pooled objects implementing the Recyclable interface, a recycle method 
  will be called, when they are taken from the pool, and a dispose method, 
  when they are returned to the pool. Implementations of the methods should 
  clear and initialize the pooled instances correspondingly. Objects 
  that do not implement the interface can also be pooled, if they do not 
  need to perform any specific actions during pooling. A RecyclableSupport class 
  can be extended to get a minimal implementation of the interface.
  </p>
  
  <p>
  An ArrayCtorRecyclable interface extends the Recyclable interface providing
  a more efficient recycle method with less reflection for recycling frequently
  used objects having constuctors with parameters.   
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.PoolService.classname=org.apache.turbine.services.pool.TurbinePoolService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  P O O L  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # Default capacity of pools of the Object pooling service.
  #
  # Default: 128
  services.PoolService.pool.capacity = 128
  
  # Class specific capacities used instead of the default if specified.
  #
  #services.PoolService.pool.capacity.org.apache.turbine.services.rundata.DefaultTurbineRunData=512
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <p>
  The Pool Service can be called instead of the Factory Service, when instantiating
  objects that are needed repeatedly e.g. for processing client requests. Intances
  of RunData implementations, ParameterParser and CookieParser implementations, 
  Pull Service tools, etc, are typical examples of pooled objects. Used objects
  must be returned to the Pool Service for recycling. The TurbinePool class is a 
  static accessor for common methods of the Pool Service:
  </p>
  
  <source><![CDATA[
  // Get a pooled DOM parser.
  DocumentBuilder parser = 
      TurbinePool.getInstance("javax.xml.parsers.DocumentBuilder");
          
  // Parse an XML document.
  Document doc = parser.parse(myfile);
  
  // Return the parser to the pool.
  TurbinePool.putInstance(parser);    
  ]]></source>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/security-service.xml
  
  Index: security-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Security Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Security Service">
  
  <p>
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.SecurityService.classname=org.apache.turbine.services.cache.<type>SecurityService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  S E C U R I T Y  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  #
  # This is the class that implements the User interface.
  # You want to override this setting only if you want your User 
  # implementation to provide application specific addtional 
  # functionality.
  #
  # Default: org.apache.turbine.om.security.TurbineUser
  #
  
  services.SecurityService.user.class=org.apache.turbine.om.security.TurbineUser
  
  #
  # This setting is DBSecurityService specific - this class is consulted for the names
  # of the columns in the users' tables for the purpose of creating join queries. 
  # If you use your own User implementation in conjunction with DBSecurityService,
  # it's peer class must implement org.apache.turbine.om.security.peer.UserPeer interface,
  # and you need to specify the name of the peer class here.
  #
  # Defalut: org.apache.turbine.om.security.peer.TurbineUserPeer
  #
  services.SecurityService.userPeer.class=org.apache.turbine.om.security.peer.TurbineUserPeer
  
  #
  # This is the class that implements UserManager interface.
  # Override this setting if you want your User information stored
  # on a different medium (LADP directory is a good example).
  # Default implementation uses Peers and a relational database .
  #
  
  services.SecurityService.user.manager=org.apache.turbine.services.security.db.DBUserManager
  
  #
  # This is used by the SecurityService to make the password checking
  # secure. When enabled, passwords are transformed by a one-way
  # function into a sequence of bytes that is base64 encoded.
  # It is impossible to guess the plain-text form of the password
  # from the representation. When user logs in, the entered password
  # is transformed the same way and then compared with stored value.
  #
  # Default: false
  #
  
  services.SecurityService.secure.passwords=false
  
  #
  # This property lets you choose what digest algorithm will be used
  # for encrypting passwords. Check documentation of your JRE for
  # available algorithms.
  #
  # Default: SHA
  #
  
  services.SecurityService.secure.passwords.algorithm=SHA
  
  # Configuration for the LDAP Security Service implementation
  
  #services.SecurityService.ldap.security.athentication=simple
  #services.SecurityService.ldap.port=<LDAP PORT>
  #services.SecurityService.ldap.host=<LDAP HOST>
  #services.SecurityService.ldap.admin.username=<ADMIN USERNAME>
  #services.SecurityService.ldap.admin.password=<ADMIN PASSWORD>
  #services.SecurityService.ldap.user.basesearch=<SEARCH PATTERN>
  #services.SecurityService.ldap.user.search.filter=<SEARCH FILTER>
  #services.SecurityService.ldap.dn.attribute=userPrincipalName
  #services.SecurityService.ldap.provider=com.sun.jndi.ldap.LdapCtxFactory
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <source><![CDATA[
  
  ]]></source>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/xmlrpc-service.xml
  
  Index: xmlrpc-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - XML-RPC Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="XML-RPC Service">
  
  <p>
    The XML-RPC service is the easiest way to add distributed
    computing and B2B capabilities to your Turbine web application.
    The current implementation is based on the Helma XML-RPC
    package which can be found <a href="http://classic.helma.at/hannes/xmlrpc/">
    here</a>.
  </p>
  
  <p>
    You can leverage the XML-RPC service for your particular needs by
    creating <strong>handlers</strong>. A handler is simply a class that
    performs certain actions: for example you may have a FileHandler
    that is responsible for sending, getting and removing files from
    a remote server. For your convenience there is the <strong>
    org.apache.turbine.services.xmlrpc.util.FileHandler</strong>
    class that will perform these operations for you. Please refer
    to the usage section below for more details.
  </p>  
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.XmlRpcService.classname=org.apache.turbine.services.xmlrpc.TurbineXmlRpcService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  X M L R P C  S E R V I C E
  #
  # -------------------------------------------------------------------
  # This property specifies which class should be used to parse
  # xml for XmlRpc functionality.
  #
  # Default: org.apache.xerces.parsers.SAXParser
  
  services.XmlRpcService.parser=org.apache.xerces.parsers.SAXParser
  
  # This property specifies which port the server part of the XmlRpc
  # should listen, if it is active.
  #
  # Default: 12345
  
  services.XmlRpcService.port=12345
  
  # If any classes are specified here, the Service will create an 
  # instance of them here and start up a listener on the specified 
  # port.
  #
  # Note that the handlers demonstrated are not very useful.  You
  # will have to invent your own services.  They do however
  # illustrate that any class with a default constructor can be
  # added here
  #
  # The handler parameter without further extension determines
  # the default handler for the service
  #
  # Default: no classes are specified by default
  
  #services.XmlRpcService.handler.$default=java.util.Hashtable
  #services.XmlRpcService.handler.stringhandler=java.lang.String
  
  # The following properties allow the transfer of data between
  # separate Turbine applications running on different servers.
  # This allows B2B type behavior such as sending database
  # updates in the form of XML or whatever type of data
  # that needs to be shared between Turbine applications
  # running on separate servers.
  
  services.XmlRpcService.handler.file = org.apache.turbine.services.xmlrpc.util.FileHandler
  services.XmlRpcService.paranoid = false
  services.XmlRpcService.acceptClient = 192.168.1.*
  services.XmlRpcService.denyClient = 
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <p>
    The following example is taken from the class used to test the
    file transfer features of the XML-RPC service. The <strong>
    org.apache.turbine.services.xmlrpc.util.FileHandlerTest</strong>
    can be found in the CVS repository. Here is how the FileHandler
    might be used:
  </p>
  
  <source><![CDATA[
  
  public class XmlRpcExample
  {
      /**
       * We will test the following three operations:
       * 
       * 1) Send a file to a remove server
       * 2) Get a file from a remote server
       * 3) Remove a file to a remove server
       */
      public void testOperations() throws Exception
      {
          /*
           * @param serverURL
           * @param sourceLocationProperty
           * @param sourceFileName
           * @param destinationLocationProperty
           * @param destinationFileName
           */
          FileTransfer.send("http://www.far-away.com:9000/RPC2",
                            "test.location",
                            "test.txt",
                            "test.location",
                            "test.send");
          /*
           * @param serverURL
           * @param sourceLocationProperty
           * @param sourceFileName
           * @param destinationLocationProperty
           * @param destinationFileName
           */
          FileTransfer.get("http://www.far-away.com:9000/RPC2",
                           "test.location",
                           "test.txt",
                           "test.location",
                           "test.get");
  
          /*
           * @param serverURL
           * @param sourceLocationProperty
           * @param sourceFileName
           */
          FileTransfer.remove("http://www.far-away.com:9000/RPC2",
                              "test.location",
                              "test.txt");
      }
  }
  
  ]]></source>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/template-service.xml
  
  Index: template-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Template Service</title>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Template Service">
  
  <p>
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.TemplateService.classname=org.apache.turbine.services.template.TurbineTemplateService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  T E M P L A T E  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # Roughly, the number of templates in each category.
  #
  # Defaults: layout=2, navigation=10, screen=50
  
  services.TemplateService.layout.cache.size=2
  services.TemplateService.navigation.cache.size=10
  services.TemplateService.screen.cache.size=50
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <source><![CDATA[
  
  ]]></source>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/intake-service.xml
  
  Index: intake-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
  
   <properties>
    <title>Turbine Services - Intake Service</title>
    <author email="jmcnally@collab.net">John McNally</author>
    <author email="jon@latchkey.com">Jon S. Stevens</author>
   </properties>
  
   <body>
  
  <section name="Intake Service">
  
  <p>
  Intake uses an xml specification to perform web form input validation
  and mapping input data to a bean's properties.  In other words, Intake
  will allow a web application to take web form input, validate it and
  then map the data to an object. Tools like the <a
  href="../torque.html">Torque</a> help provide mapping of Objects to the
  database and Intake helps map web form data to Objects.
  </p>
  
  <p>
  The visual picture of where Intake fits into a Turbine web application
  looks something like this:
  </p>
  
  <source><![CDATA[
  ------------------
      HTML Form
  ------------------
       Intake
  ------------------
   Business Objects  <- Torque Generated
  ------------------
        Peers        <- Torque Generated
  ------------------
        RDBMS
  ------------------
  ]]></source>
  
  <p>
  There are several advantages to using Intake. First off, it provides for
  a centralized management system for dealing with form data. All of the
  configuration of Intake is done through a single XML file. Next, Intake
  is good for validating the form data. Intake provides the ability to do
  regular expression matching in order to make sure that form fields
  contain the data that they should contain. For example, if someone
  should only enter a number into a form field, it can be validated with a
  regular expression. Lastly, Intake can provides a centralized source for
  error messages. If the validation fails, the error message defined in
  the XML file can be shown to the user.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.IntakeService.classname= \
  org.apache.turbine.services.intake.TurbineIntakeService
  
  # -------------------------------------------------------------------
  # 
  #  I N T A K E   S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # The location of the xml file specifying valid inputs
  services.IntakeService.xml.path=WEB-INF/conf/intake.xml
  
  tool.request.intake=org.apache.turbine.services.intake.IntakeTool
  ]]></source>
  
  </section>
  
  <section name="Usage">
  <p>
  Intake is implemented as a Turbine Service and a Pull Tool.  An XML
  specification is parsed during the service initialization and used by
  the pull tool while processing request data and generating the response.
  </p>
  
  <p>
  Intake is made available in the Velocity context with the default value
  of $intake. The name of the variable that is used is what is configured 
  for the tool. For example, the current configuration is "tool.request.intake". 
  To change the name of the variable to "foo", it would be "tool.request.foo".
  </p>
  
  <p>
  Intake is made available in Java code by adding the following imports to
  the top of a .java file:
  </p>
  
  <source><![CDATA[
  import org.apache.turbine.services.intake.IntakeTool;
  import org.apache.turbine.services.intake.model.*;
  ]]></source>
  
  </section>
  
  <section name="Xml File">
  
  <p>
  The following example come from <a
  href="http://scarab.tigris.org/">Scarab</a>. These are a couple of
  groups from Scarab's intake.xml:
  </p>
  
  <source><![CDATA[
  <input-data basePackage="org.tigris.scarab.">
  
  <group name="AttributeValue" key="attv" 
              mapToObject="om.AttributeValue">
      <field name="Value" key="val" type="String">
          <rule name="maxLength" value="255">Value length cannot be &gt; 255</rule>
          <required-message>This module requires data for this 
                            attribute.
          </required-message>
      </field>
      <field name="Url" key="url" type="String" mapToProperty="Value">
          <rule name="maxLength" value="255">Url length cannot be &gt; 255</rule>
          <rule name="mask" value="^$|http.+">Please enter an url starting with "http"</rule>
          <required-message>This module requires a valid url.</required-message>
      </field>
      <field name="OptionId" key="optionid" type="NumberKey">
          <rule name="mask" value="^$|[0-9]+">Please select a valid choice</rule>
          <required-message>This module requires that you select an option 
                            for this attribute.
          </required-message>
      </field>
  </group>
  
  <group name="Login" key="login">
      <field name="Username" key="u" type="String">
          <rule name="minLength" value="1">Please enter an email address</rule>
          <rule name="mask" value=".+@.+\..+">Please enter a valid email address</rule>
      </field> 
      <field name="Password" key="p" type="String">
          <rule name="minLength" value="1">Please enter a password</rule>
      </field>
  </group>
  
  </input-data>
  ]]></source>
  
  <p>
  A group is a set of fields that have been aligned so that they form a
  logical unit. The first group includes some of the properties from a
  om.AttributeValue business object (BO). This object is a Java Bean
  object with get/set methods for each of the properties in the object. In
  this case, the object has been auto-generated by Torque from Scarab's
  SQL schema.
  </p>
  
  <p>
  The group tag has a class attribute which is the name that will be used
  within templates and java code to refer to the group.  It also contains a 
  key attribute which will be used in the query parameters.  The key is
  not referenced in any code, so it can be a short name (even 1 character) as 
  long as it is uniquely identifies the group from the rest.
  </p>
  <p>
  An object that the group's fields will map can also be specified.  This will
  be a default; the individual fields within a group can map to different
  objects.
  </p>
  <p>
  Fields have attributes: name and key which serve similar function to the
  group's class and key attributes.  It has mapToObject and mapToProperty fields
  that can be used to associate a business object to the field for prepopulating
  the field as well as assigning the field data to the bean after successful
  validation.  The field must have a type, which can be simple types such as
  String and Integer.  It is planned that more complex types, such as
  Email, Url, or Date, will be added that will add functionality that is 
  difficult or not possible with a simple regex mask.
  </p>
  <p>
  The field can define rule elements.  The basic fields include rules for
  minimum and maximum, lengths and values, as well as a regex mask.
  </p>
  
  </section>
  
  <section name="Login Example">
  
  <source><![CDATA[
  <group name="Login" key="login">
  ]]></source>
  
  <p>
  The name="Login" is a descriptive name for the group. The key="login" is
  the value that is used in the web forms to identify the group. The key=
  value is not directly referenced. In other words, you do not need to
  know it exists unless you are debugging your application. Both of these
  attribute values must be unique across all groups in the XML file. Now,
  lets look at the fields in the group.
  </p>
  
  <source><![CDATA[
  <field name="Username" key="u" type="String">
      <rule name="minLength" value="1">Please enter an email address</rule>
      <rule name="mask" value=".+@.+\..+">Please enter a valid email address</rule>
  </field> 
  <field name="Password" key="p" type="String">
      <rule name="minLength" value="1">Please enter a password</rule>
  </field>
  ]]></source>
  
  <p>
  The name="Username" is the descriptive name for the field. The key="u"
  is the value that is used in the web forms to identify the field. Both
  of these attributes must be unique across the fields within the group.
  The type="String" specifies what the system expects the input for that
  field to be (please see the intake.dtd for the allowed values). Within
  the field, it is possible to specify one or more rules. These rules
  define how Intake should validate web form data. There are minLength,
  maxLength and mask attributes to the rule tag. The message inside the
  rule tag is a text message which can be used to display an error within
  the template.
  </p>
  
  <p>
  At this point, it is best to show an example form of how to use Intake
  within a Velocity template:
  </p>
  
  <source><![CDATA[
  (1) <form action="$link.setPage("Login.vm")" method="POST" name="login" >
  (2)    <input type="hidden" name="action" value="Login">
  (3)    #if ($data.Parameters.nextTemplate)
  (4)    <input type="hidden" name="nextTemplate" 
                value="$data.Parameters.nextTemplate">
         #else
  (5)    <input type="hidden" name="nextTemplate" value="Start.vm">    
         #end
  
  <p>
  Email Address:
  
  (6)    #set ( $loginGroup = $intake.Login.Default )
  
  (7)    #if ( !$loginGroup.Username.isValid() )
  (8)        $loginGroup.Username.Message<br>
         #end
  (9)    <input name= "$loginGroup.Username.Key"
                value="$!loginGroup.Username" size="25" type="text">
  </p>
  
  <p>
  Password:
  
  (10)    #if ( !$loginGroup.Password.isValid() )
  (11)        $loginGroup.Password.Message<br>
          #end
  (12)   <input name= "$loginGroup.Password.Key"
                value="" size="25" type="text" 
                onChange="document.login.submit();">
  </p>
  
  (13) <input type="submit" name="eventSubmit_doLogin" value="Login">
  (14) $intake.declareGroups()
  </form>
  ]]></source>
  
  <p>
  The example above shows quite a few different concepts with regards to
  web application design, so lets break them down a bit, starting from the
  top. Each of the important lines have been numbered for easy reference.
  </p>
  
  <p>
  <ol>
      <li>
      Create the &lt;form&gt; tag. Within it, we use the $link object to
      create a URI for the template "Login.vm". In other words, when the
      button is clicked, the page will submit upon itself.
      </li>
      <li>
      Set the Action to execute to be "Login". This can either be a hidden
      input field or be defined with the
      $link.setPage().setAction("Login") method
      </li>
      <li>
      Check to see if there is a "nextTemplate" defined in the
      GET/POST/PATH_INFO information. On success, the Action can use the
      nextTemplate field to decide what page to show next.
      </li>
      <li>
      If (3), then create a hidden input tag that holds the value for
      nextTemplate.
      </li>
      <li>
      If not (3), then set the nextTemplate to be the "Start.vm" page.
      </li>
      <li>
      This retrieves the default Login Group object from Intake. What this
      means is that the group "Login" as defined in Scarab's intake.xml is
      represented as an object.
      </li>
      <li>
      It is then possible to query the object to confirm if the
      information within it is valid.
      </li>
      <li>
      This will display the invalid error message as defined in the
      intake.xml &lt;rule&gt; definitions.
      </li>
      <li>
      Here we define a form input text field. The $loginGroup.Username.Key
      specifies an Intake system generated key. The value attribute
      $!loginGroup.Username will tell Intake to either display an empty
      String or display the previous form submission.
      </li>
      <li>
      Repeat the same procedure as for the Username field.
      </li>
      <li>
      Repeat the same procedure as for the Username field.
      </li>
      <li>
      A bit of JavaScript will cause the form to submit itself if one hits
      tab after entering the password.
      </li>
      <li>
      eventSubmit_doLogin is special. It tells Turbine to execute the
      doLogin method in the Action. This is based on the Action Events
      system.
      </li>
      <li>
      $intake.declareGroups() tells Intake to add a couple hidden input
      fields to the page output. These fields represent the Groups that
      were used in the template.
      </li>
  </ol>
  </p>
  
  <p>
  Below is an example of the HTML that is sent to the browser after the 
  page has been requested:
  </p>
  
  <source><![CDATA[
  <form action="http://foo:8080/scarab/servlet/scarab/template/Login.vm" 
        method="POST" name="login" >
      <input type="hidden" name="action" value="Login">
          <input type="hidden" name="nextTemplate" value="Start.vm">    
      
  <p>
  Email Address:
      
         <input name= "login_0u"
          value="" size="25" type="text">
  </p>
  
  <p>
  Password:
  
         <input name= "login_0p"
          value="" size="25" type="text" onchange="document.login.submit();">
  </p>
  
  <input type="submit" name="eventSubmit_doLogin" value="Login">
  
  <input type="hidden" name="intake-grp" value="login"></input>
  <input type="hidden" name="login" value="_0"></input>
  
  </form>
  ]]></source>
  
  <p>
  Some notes to consider:
  </p>
  
  <ol>
      <li>
      The _0 signifies the "default" group.
      </li>
      <li>
      The login_0u signifies the login group combined with the _0 and the
      "u" is from the intake.xml file for the field "Username".
      </li>
      <li>
      The two hidden input fields are what is generated from the
      $intake.declareGroups()
      </li>
  </ol>
  
  <p>
  The Java Action code which handles the submission of the form looks like this:
  </p>
  
  <source><![CDATA[
  public void doLogin( RunData data, Context context ) throws Exception
  {
      IntakeTool intake = (IntakeTool) context.get("intake");
  
      if ( intake.isAllValid() &amp;&amp; checkUser(data, context) ) 
      {
          String template = data.getParameters()
              .getString(ScarabConstants.NEXT_TEMPLATE, 
              TurbineResources.getString("template.homepage", "Start.vm") );
          setTemplate(data, template);
      }
      else 
      {
          // Retrieve an anonymous user
          data.setUser (TurbineSecurity.getAnonymousUser());
          setTemplate(data, 
              data.getParameters()
                  .getString(ScarabConstants.TEMPLATE, "Login.vm"));
      }
  }
  
  /**
      Checks to make sure that the user exists, has been confirmed.
  */
  public boolean checkUser(RunData data, Context context)
      throws Exception
  {
      User user = null;
      IntakeTool intake = (IntakeTool)context
          .get(ScarabConstants.INTAKE_TOOL);
  
      try
      {
          String username = null;
          String password = null;
          try
          {
              Group login = intake.get("Login", IntakeTool.DEFAULT_KEY);
              username = login.get("Username").toString();
              password = login.get("Password").toString();
          }
          catch ( Exception e )
          {
              throw new TurbineSecurityException(
                  "Login information was not supplied.");
          }
  
          // Authenticate the user and get the object.
          user = TurbineSecurity.getAuthenticatedUser( username, password );
  
          ...
      }
  }
  ]]></source>
  
  <p>
  Intake is retrieved from the context and asked whether all the inputs
  that it knows about were valid. If not the login form will be quickly
  reshown and error messages will be given. If the data is valid, the
  field data is extracted manually in this case, as the Intake fields do
  not map directly to a bean object. The next example will use the
  group.setProperties() method to directly assign Intake's field data to
  the matching beans.
  </p>
  
  </section>
  
  <section name="Attribute Value example">
  
  <source><![CDATA[
  <group name="AttributeValue" key="attv" 
              mapToObject="om.AttributeValue">
  ]]></source>
  
  <p>
  The name="AttributeValue" is simply a descriptive name for the group.
  The key="attv" is the value that is used in the web forms to identify
  the group. Both of these attributes must be unique across all groups in
  the XML file. The mapToObject="om.AttributeValue" is an optional
  attribute. This specifies what Java Bean object that this group maps to.
  If a mapToObject is not specified, then it is possible to use Intake to
  retrieve the values of the data directly instead of getting it from a
  populated object. This will be covered in detail further on.
  </p>
  
  
  <source><![CDATA[
  <field name="Value" key="val" type="String">
      <rule name="maxLength" value="255">Value length cannot be &gt; 255</rule>
      <required-message>This module requires data for this 
                        attribute.
      </required-message>
  </field>
  <field name="Url" key="url" type="String" mapToProperty="Value">
      <rule name="maxLength" value="255">Url length cannot be &gt; 255</rule>
      <rule name="mask" value="^$|http.+">Please enter an url starting with "http"</rule>
      <required-message>This module requires a valid url.</required-message>
  </field>
  ]]></source>
  
  <p>
  The fields within a group relate to the form fields on a web page. At
  this point, it is probably best to show an example rather than
  explaining in detail what each part of the field tag is. Therefore,
  using the fields above in a simple example, one might have a form with a
  text entry box that allows you to edit a Url. The filename is:
  "EditUrl.vm".
  </p>
  
  <source><![CDATA[
  #set ( $action = $link.setPage("EditUrl.vm").setAction("SaveUrl") )
  <form action="$action"
        method="post">
   
  #set ( $attributeValue = $issue.AttributeValue("URL") )
  #set ( $group = $intake.AttributeValue.mapTo($attributeValue) )
  
  Enter Url:
  <input type="text" name="$group.Url.Key" value="$!group.Url.Value">
  
  <input type="submit" name="eventSubmit_doSave" value="Submit>
  
  $intake.declareGroups()
  </form>
  ]]></source>
  
  <p>
  To explain the template above, the first #set is done simply for
  convenience. The second #set is part of Scarab. It uses the $issue
  object to retrieve a "URL" AttributeValue object for a particular issue.
  </p>
  
  <p>
  The next #set tells Intake to map that object to the AttributeValue
  group. What it does is tell Intake to create an AttributeValue Group
  object which has been mapped to the AttributeValue retrieved from the
  $issue object. This Group object represents the XML file &lt;group&gt;
  as a Java object.
  </p>
  
  <p>
  Moving down further into the example, there is the &lt;input&gt; field
  which has a name and value attributes. The $group.Url.Key tells Intake
  to retrieve the key information for the field. This would evaluate to
  "attv_0url". What this is a combination of the group key (attv), a "_0"
  is the result of retrieving the "$intake.AttributeValue.Default" and the
  "url" is the field key. The value attribute would evaluate to just an 
  empty String the first time around. The $intake.declareGroups() is a 
  special method that will create a hidden input field that declares which
  groups have been added to the page. We will discuss that in more detail
  further down.
  </p>
  
  <p>
  View source on the HTML page after executing the template and this is
  what the form above would look like:
  </p>
  
  <source><![CDATA[
  <form action="http://server/s/servlet/s/template/EnterUrl.vm/action/EnterUrlAction" 
        method="post">
  
  Enter Url:
  <input type="text" name="attv_0url" value="">
  
  <input type="submit" name="eventSubmit_doEnter" value="Submit>
  
  <input type="hidden" name="attv" value="_0">
  <input type="hidden" name="intake-grp" value="attv">
  </form>
  ]]></source>
  
  <p>
  When the form is submitted to the server (the user clicks the submit
  button), the following code in the EnterUrlAction.java class is executed.
  </p>
  
  <source><![CDATA[
  public void doEnter( RunData data, Context context ) throws Exception
  {
      IntakeTool intake = (IntakeTool)context
          .get(ScarabConstants.INTAKE_TOOL);
      
      // check to see if the fields are valid
      if ( intake.isAllValid() ) 
      {
          // get the "AttributeValue" Group
          AttributeValue av = new AttributeValue();
          Group group = intake.get("AttributeValue", IntakeTool.DEFAULT_KEY);
          group.setProperties (av);
          // now av is properly populated with the form data
      }
  }
  ]]></source>
  
  <p>
  If the form fields are invalid as a result of not matching one of the
  rules that are defined in the fields in the XML file, then the action
  does nothing and the page is displayed again.
  </p>
  
  <p>
  Back to explaining the fields, lets look at the example again:
  </p>
  
  <source><![CDATA[
      <field name="Value" key="val" type="String">
          <rule name="maxLength" value="255">Value length cannot be &gt; 255</rule>
          <required-message>This module requires data for this 
                            attribute.
          </required-message>
      </field>
      <field name="Url" key="url" type="String" mapToProperty="Value">
          <rule name="maxLength" value="255">Url length cannot be &gt; 255</rule>
          <rule name="mask" value="^$|http.+">Please enter an url starting with "http"</rule>
          <required-message>This module requires a valid url.</required-message>
      </field>
  ]]></source>
  
    </section>
  
    <section name="Multiple groups of the same class in one form">
    
  <p>
  This example uses a form from Scarab that assigns values to various
  attribute's that are relevant for an issue (bug).  Attributes include
  summary, operating system, platform, assigned to, etc.  Some of the 
  attributes are required, but not all.  
  </p>
  
  <p>
  The template:
  </p>
  
  <source><![CDATA[
  #set ( $action = $link.setPage("entry,Wizard3.vm").setAction("ReportIssue")
  .addPathInfo("nextTemplate", "entry,Wizard4.vm") )
  #set ($user = $scarabR.User)
  #set ($module = $user.CurrentModule)
  #set ($issue = $user.ReportingIssue)
  
  
  <form method="get" action="$action">
  
  <hr><br>Please fill in the following:<br><br>
  
  #foreach ( $attVal in $issue.OrderedModuleAttributeValues )
    #set ( $attrInput = $intake.AttributeValue.mapTo($attVal) ) 
  
    #if ( $attVal.Attribute.AttributeType.ValidationKey )
          #set ( $field = $attVal.Attribute.AttributeType.ValidationKey )
    #elseif ($attVal.Attribute.AttributeType.Name == "combo-box" )
          #set ( $field = "OptionId" )
    #else
          #set ( $field = "Value" )  
    #end
  
      #if ( $attVal.isRequired() )
          $attrInput.get($field).setRequired(true)
          <b>*</b>
      #end
  
      $attVal.Attribute.Name:
  
      #if ($attVal.Attribute.AttributeType.Name == "combo-box" )
            <font color="red">
              #attrValueErrorMsg ( $attVal $field )
            </font>
            <br>
            #attrValueSelect ($attVal $field "")
      #else
  
            <font color="red">
              #attrValueErrorMsg ( $attVal $field )
            </font>
            <br>
          #if ($attVal.Attribute.AttributeType.Name == "long-string" )        
  
              <textarea name= "$attrInput.Value.Key" cols="40" 
                 rows="5">$!attrInput.Value</textarea>
          #else
  
             <input name= "$attrInput.Value.Key"
                  value="$!attrInput.Value" size="20" type="text">
  
          #end
  <br><br>
    #end
  #end
  
  <p>
              <input type="submit" 
                  name="eventSubmit_doEnterissue" value="Submit Issue">
  
  $intake.declareGroups()
  </form>
  ]]></source>
  
  <p>
  The main new thing added here is that the $intake group is mapped to a business
  object.  A business object that is to be used in this way is expected to
  implement the Retrievable interface, which provides a method to get a
  String key which uniquely identifies the object.  
  </p>
  <p>
  The action:
  </p>
  
  <source>
  public void doEnterissue( RunData data, Context context )
      throws Exception
  {
      IntakeTool intake = (IntakeTool)context
          .get(ScarabConstants.INTAKE_TOOL);
  
      // Summary is always required.
      ScarabUser user = (ScarabUser)data.getUser();
      Issue issue = user.getReportingIssue();
      AttributeValue aval = (AttributeValue)issue
          .getModuleAttributeValuesMap().get("SUMMARY");
      Group group = intake.get("AttributeValue", aval.getQueryKey());
      Field summary = group.get("Value");
      summary.setRequired(true);
      issue.setVocabulary(new Vocabulary(summary.toString()));
  
      if ( intake.isAllValid() ) 
      {
          Iterator i = issue.getModuleAttributeValuesMap()
              .values().iterator();
          while (i.hasNext()) 
          {
              aval = (AttributeValue)i.next();
              group = intake.get("AttributeValue", aval.getQueryKey());
              if ( group != null ) 
              {
                  group.setProperties(aval);
              }                
          }
          
          if ( issue.containsMinimumAttributeValues() ) 
          {
              issue.save();
  
              String template = data.getParameters()
                  .getString(ScarabConstants.NEXT_TEMPLATE, 
                             "entry,Wizard3.vm");
              setTemplate(data, template);            
          }
      }
  }
  </source>
  
  <p>
  The action shows how the business object or action can let intake know if
  a field is required. It also shows how multiple groups of the same class
  can be added to a template and then the information is easily passed on
  to an associated bean.
  </p>
  
  
  <source><![CDATA[
  Dan Diephouse wrote:
  > 
  > I want to validate a form that updates my business object properties
  > with intake.  I got the latest cvs of turbine-2 repository and built a
  > new distribution of the turbine jar.  I can easily use intake to add
  > validate items I add to my databse, but I'm running in to a snag when
  > trying to modify them.  I've defined by business object in the intake
  > validation file.  I use the following code to update my item:
  > 
  >          IntakeTool intake = (IntakeTool) context.get("intake");
  > 
  >          ParameterParser pp = data.getParameters();
  > 
  >          if ( intake.isAllValid() ) {
  >              Job j = new Job();
  >              j.setNew(false);
  >              group.setProperties(j);
  > 
  >              JobPeer.doUpdate(j);
  > 
  > Error-->    data.getParameters().add("jobid", j.getJobId().toString());
  >              data.setMessage("Job updated.");
  >          } else {
  >              data.setMessage("There was an error updating the job.
  > Check below for further information.");
  >          }
  > 
  > It runs OK, until I try and retrieve the JobId.  I get a Null Pointer
  > exception.  Is there something I'm doing wrong here?  Or is this a bug?
  >   Do I need to specify that this is not a new object to intake?  I would
  > include my template, but there are lots of fields so its really long.
  > But here's a little summary with most fields gone:
  > 
  > #set ( $job = $basecamp.getJob() )   - This gets a job from a pull tool
  > #set ( $jobGroup = $intake.Job.mapTo($job) )
  > <input type=hidden name="$jobGroup.JobId.Key" 
  > value="$jobGroup.JobId.Value">
  > 
  > #if ( !$jobGroup.Title.isValid() )
  > $jobGroup.Title.Message<br>
  > #end
  > <input type=text name="$jobGroup.Title.Key"
  > value="$!jobGroup.Title.Value" size="50">
  > .
  > .
  > .
  > .
  > $intake.declareGroups()
  > 
  > Thanks,
  > 
  > Dan Diephouse
  
  This is not how i usually do things, but I guess it could work.  One
  thing that is wrong is that you are using mapTo(job) in the template and
  then in the action you are using IntakeTool.DEFAULT_KEY.  Unless
  job.getQueryKey() returns "_0", this combination is not going to work.
  Print out data.getParameters().toString() in the action to see what the
  parameters look like.
  
  Here is what I consider a normal course of events:
  
  1.  In the template:  
  
  $job = $foo.Job
  #set ( $jobGroup = $intake.Job.mapTo($job) )
  
  (This job is can be a new Job or one that is already saved.)
  
  2. In the action:
  
  // get the same (not necessarilary the same java Object, but has the
  exact same attribute values) job
  Job job = foo.getJob()
  Group group = intake.get("Job", job.getQueryKey());
  group.setProperties(job);
  
  It appears as though you are trying to map the parameters given for one
  job to another job.
  
  john mcnally
  ]]></source>
  
    </section>
  
    <section name="Default Values for fields">
  
  <p>
  If you want to use input fields which should default to non-empty values,
  you can use the defaultValue field:
  </p>
  
  <source><![CDATA[
  <group name="test" key="test">
      <field name="Value" key="val" type="String" defaultValue="preset">
      </field>
  </group>
  ]]></source>
  
  If you set up a form like this:
  
  <source><![CDATA[
  #if($!dz)
  #set ($frm = $intake.test.mapTo($t))
  $frm.Mode.
  #else
  #set ($frm = $intake.test.default )
  #end
  
  <FORM NAME="entryForm">
  <INPUT type="text" name="$frm.get("val").Key" value="$!frm.get("val")">
  </FORM>
  ]]></source>
  
  <p>
  then you can either map your form to the fields of the $t object or to the default values, which, for
  the val Field is the string 'preset'.
  </p>
  
  </section>
  
   </body>
  
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/factory-service.xml
  
  Index: factory-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Factory Service</title>
    <author email="ilkka.priha@simsoft.fi">Ilkka Priha</author>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Factory Service">
  
  <p>
  The Factory Service instantiates objects from the given class name
  using either the given class loader or an applicable one found from the class
  loader repository. If neither one is specified, the default class loader
  will be used.
  </p>
  
  <p>
  The service provides the following benefits compared to Class.forName():
  </p>
  <ul>
  <li>support for parameters in constructors,</li>
  <li>internal class loader repository, which can be specified in resources,</li>
  <li>optional class specific factories, which can be used for customized instantiation, and</li>
  <li>integration with the Pool Service supporting recycling of instances created by the service.</li>
  </ul>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.FactoryService.classname=org.apache.turbine.services.factory.TurbineFactoryService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  F A C T O R Y  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # A comma separated list of classloaders (very optional)
  #
  # Example: org.foo.bar.MyClassLoader, org.ack.joe.YourClassLoader
  #
  #services.FactoryService.class.loaders=
  
  # Customized factories to be used instead of the default factory.
  # E.g. to instantiate XML parsers, SSL sockets, etc., which require
  # specific instantiation not supported by the default factory.
  # The property name is prefixed with "factory" followed by the
  # name of the production class. The value is the class name of
  # the factory implementing the Factory interface. The factory
  # will be instantiated by using the service itself.
  #
  # Examples:
  #
  #services.FactoryService.factory.javax.xml.parsers.DocumentBuilder=org.foo.xml.DomBuilderFactory
  #services.FactoryService.factory.javax.xml.parsers.SAXParser=org.foo.xml.SaxParserFactory
  #services.FactoryService.factory.java.net.ServerSocket=org.foo.net.SslServerSocketFactory
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <p>
  In Turbine, the Factory Service is currently only used internally by the Pool Service.
  Applications can also use the service instead of Class.forName() and for unifying
  initialization, configuration and access to vendor specific object factories. 
  The following is a simplified example of a customized DOM parser factory:
  </p>
  
  <source><![CDATA[
  package org.foo.xml;
  
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  import javax.xml.parsers.ParserConfigurationException;
  
  import org.apache.turbine.util.TurbineException;
  import org.apache.turbine.services.factory.Factory;
  
  /**
   * A factory for instantiating DOM parsers. 
   */
  public class DomBuilderFactory implements Factory
  {
      /**
       * The implementation of the factory.
       */
      private DocumentBuilderFactory factory;
  
      /**
       * Initializes the factory.
       */
      public void init(String className)
          throws TurbineException
      {
          factory = DocumentBuilderFactory.newInstance();
      }
  
      /**
       * Gets a DocumentBuilder instance.
       */
      public Object getInstance()
          throws TurbineException
      {
          try
          {
              return factory.newDocumentBuilder();
          }
          catch (ParserConfigurationException x)
          {
              throw new TurbineException(x);
          }
      }
  
      /**
       * Gets a DocumentBuilder instance.
       * The given loader is ignored.
       */
      public Object getInstance(ClassLoader loader)
          throws TurbineException
      {
          return getInstance();
      }
  
      /**
       * Gets a DocumentBuilder instance.
       * Constructor parameters are ignored.
       */
      public Object getInstance(Object[] params,
                                String[] signature)
          throws TurbineException
      {
          return getInstance();
      }
  
      /**
       * Gets a DocumentBuilder instance.
       * The given loader and constructor parameters are ignored.
       */
      public Object getInstance(ClassLoader loader,
                                Object[] params,
                                String[] signature)
          throws TurbineException
      {
          return getInstance();
      }
  
      /**
       * Returns false as given class loaders are not supported.
       */
      public boolean isLoaderSupported()
      {
          return false;
      }
  }
  ]]></source>
  
  <p>
  The customized DOM parser factory must be specified in Turbine Resources before it can be used:
  </p>
  
  <source><![CDATA[
  services.FactoryService.factory.javax.xml.parsers.DocumentBuilder=org.foo.xml.DomBuilderFactory
  ]]></source>
  
  <p>
  A DOM parser can now be instantiated with the following code fragment:
  </p>
  
  <source><![CDATA[
  // Access the service singleton.
  FactoryService service = (FactoryService) 
      TurbineServices.getInstance().getService(FactoryService.SERVICE_NAME);
      
  // Create a new DOM parser. 
  DocumentBuilder parser = 
      service.getInstance("javax.xml.parsers.DocumentBuilder");
  ]]></source>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/howto/mimetype-service.xml
  
  Index: mimetype-service.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
   <properties>
    <title>Turbine Services - Mimetype Service</title>
    <author email="ilkka.priha@simsoft.fi">Ilkka Priha</author>
    <author email="jvanzyl@apache.org">Jason van Zyl</author>
   </properties>
  
  <body>
  
  <section name="Mimetype Service">
  
  <p>
  The MimeType Service maintains mappings between MIME types and
  the corresponding file name extensions, and between locales and
  character encodings. The mappings are typically defined in
  properties or files located in user's home directory, Java home
  directory or the current class jar depending on the implementation.
  </p>
  
  </section>
  
  <section name="Configuration">
  
  <source><![CDATA[
  # -------------------------------------------------------------------
  # 
  #  S E R V I C E S
  #
  # -------------------------------------------------------------------
  # Classes for Turbine Services should be defined here.
  # Format: services.[name].classname=[implementing class]
  #
  # To specify properties of a service use the following syntax:
  # service.[name].[property]=[value]
  
  services.MimeTypeService.classname=org.apache.turbine.services.mimetype.TurbineMimeTypeService
  .
  .
  .
  # -------------------------------------------------------------------
  # 
  #  M I M E T Y P E  S E R V I C E
  #
  # -------------------------------------------------------------------
  
  # This property specifies a file containing mappings between MIME 
  # content types and the corresponding file name extensions. The
  # service itself contains a hardcoded set of most common mappings. 
  # The file must use the same syntax as the mime.types file of 
  # the Apache Server, i.e. 
  # <mimetype> <ext1> <ext2>...
  #
  #services.MimeTypeService.mime.types=/WEB-INF/conf/mime.types
  
  # This property specifies a file containing mappings between locales 
  # and the corresponding character encodings. The service itself 
  # contains a hardcoded set of most common mappings. 
  # The file should use the Java property file syntax, i.e. 
  # <lang_country_variant>=<charset>
  #
  #services.MimeTypeService.charsets=/WEB-INF/conf/charset.properties
  
  ]]></source>
  
  </section>
  
  <section name="Usage">
  
  <p>
  The default RunData implementation uses the MimeType Service internally
  when resolving the character encoding of the servlet response. In addition,
  applications can use it for customized encoding and content type resolving.
  </p>
  
  <p>
  The mappings between locales and the corresponding character encodings
  are specified using the Java property file syntax, where the locale 
  specification is the key of the property key and the charset is the value
  of the property. The locale specification consists of three parts:
  </p>
  
  <source><![CDATA[
  <lang>_<country>_<variant>
  ]]></source>
  
  <p>
  The variant can be whatever is appropriate for the application, like a
  markup language specification, a browser specification, etc. The service 
  looks for charsets using the following search order:
  </p>
  
  <source><![CDATA[
  <lang>_<country>_<variant>=<charset>
  _<country>_<variant>=<charset>
  <lang>__<variant>=<charset>
  __<variant>=<charset>
  <lang>_<country>=<charset>
  _<country>=<charset>
  <lang>=<charset>
  ]]></source>
  
  <p>
  The service contains defaults for several language mappings and more specific
  ones can be specified in an optional property file, e.g. __wml=UTF-8. The name
  of the property file can be given with a service property named "charsets". 
  The service caches results of the search, which should guarantee good performance.
  </p>
  
  <p>
  The mappings between MIME types and the corresponding file name extensions
  are specified using the same syntax as the mime.types file of the Apache Server,
  i.e.: 
  </p>
  
  <source><![CDATA[
  <mimetype> <ext1> <ext2>...
  ]]></source>
  
  <p>
  The service contains defaults for most common MIME types, like text/plain, 
  text/html, text/x-hdml, text/vnd.wap.wml, image/gif and image/jpeg. More
  specific ones can be specified in an optional MIME types file. The name of
  the MIME types file can be given with a service property named "mime.types".
  </p>
  
  <p>
  The TurbineMimeTypes class is a static accessor for the most common 
  MimeType Service methods.
  </p>
  
  </section>
  
  </body>
  </document>
  
  
  
  1.2       +21 -0     jakarta-turbine-fulcrum/xdocs/stylesheets/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-fulcrum/xdocs/stylesheets/project.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- project.xml	2001/07/19 09:03:24	1.1
  +++ project.xml	2001/12/17 16:31:36	1.2
  @@ -6,6 +6,27 @@
   
     <body>
       <menu name="Fulcrum">
  +      <item name="Overview"              href="/index.html"/>
  +      <item name="Changes"               href="/changes.html"/>
       </menu>
  +
  +    <menu name="Howtos">
  +      <item name="Cache Service"          href="/howto/cache-service.html"/>
  +      <item name="Factory Service"        href="/howto/factory-service.html"/>
  +      <item name="Intake Service"         href="/howto/intake-service.html"/>
  +      <item name="JSP Service"            href="/howto/jsp-service.html"/>
  +      <item name="Localization Service"   href="/howto/localization-service.html"/>
  +      <item name="Mimetype Service"       href="/howto/mimetype-service.html"/>
  +      <item name="Naming Service"         href="/howto/naming-service.html"/>
  +      <item name="Pool Service"           href="/howto/pool-service.html"/>
  +      <item name="Scheduler Service"      href="/howto/scheduler-service.html"/>
  +      <item name="Security Service"       href="/howto/security-service.html"/>
  +      <item name="Template Service"       href="/howto/template-service.html"/>
  +      <item name="Upload Service"         href="/howto/upload-service.html"/>
  +      <item name="Velocity Service"       href="/howto/velocity-service.html"/>
  +      <item name="XmlRpc Service"         href="/howto/xmlrpc-service.html"/>
  +      <item name="XSLT Service"           href="/howto/xslt-service.html"/>
  +    </menu>
  +
     </body>
   </project>
  
  
  
  1.1                  jakarta-turbine-fulcrum/xdocs/changes.xml
  
  Index: changes.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document>
  
    <properties>
      <title>Fulcrum</title>
      <author email="jvanzyl@apache.com">Jason van Zyl</author>
      <author email="mpoeschl@marmot.at">Martin Poeschl</author>
    </properties>
  
    <body>
  
      <section name="Changes">
        <p>
          <ul>
  
            <!-- template
            <li>
              <strong></strong>
              <ul>
                <li>
                  <a href="">Reference</a>.
                </li>
              </ul>
            </li>
            -->
  
          </ul>
        </p>
      </section>
    </body>
  </document>
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>