Author: smumford
Date: 2011-10-19 01:45:35 -0400 (Wed, 19 Oct 2011)
New Revision: 7776
Added:
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml
Log:
Porting revs 7738,7666,7658 to EPP
Added:
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml
===================================================================
---
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml
(rev 0)
+++
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml 2011-10-19
05:45:35 UTC (rev 7776)
@@ -0,0 +1,290 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "../../Reference_Guide.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="chap-Reference_Guide-Data_Import_Strategy">
+ <title>Data Import Strategy</title>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Introduction">
+ <title>Introduction</title>
+ <para>
+ In the Portal extension mechanism, developers can define an extension
+ that Portal data can be customized by configurations in the extension. There
+ are several cases which an extension developer wants to define how to customize
the Portal data,
+ for example modifying, overwriting or just inserting a bit into the data defined
by the portal.
+ Therefore, GateIn also defines several modes for each case and the only thing
which a developer has to do is to clarify the
+ usecase and reasonably configure extensions.
+ </para>
+ <para>
+ This section shows you how data are changes in each mode.
+ </para>
+ </section>
+
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Import_Mode">
+ <title>Import Mode</title>
+ <para>
+ In this section, the following modes for the import strategy are introduced:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>OVERWRITE</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Each mode indicates how the Portal data are imported. The import mode value is
+ set whenever <literal>NewPortalConfigListener</literal> is initiated.
If the mode is not set,
+ the default value will be used in this case. The default value is configurable
as
+ a UserPortalConfigService initial param. For example, the bellow configuration
+ means that default value is <literal>MERGE</literal>.
+ </para>
+ <programlisting language="XML" role="XML"><![CDATA[
+<component>
+ <key>org.exoplatform.portal.config.UserPortalConfigService</key>
+ <type>org.exoplatform.portal.config.UserPortalConfigService</type>
+ <component-plugins>
+ ............
+ </component-plugins>
+ <init-params>
+ <value-param>
+ <name>default.import.mode</name>
+ <value>merge</value>
+ </value-param>
+ </init-params>
+</component>
+ ]]>
+ </programlisting>
+ <para>
+ The way that the import strategy works with the import mode will be clearly
demonstrated in next sections for each type of data.
+ </para>
+ </section>
+ <section
id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy">
+ <title>Data Import Strategy</title>
+ <para>
+ The 'Portal Data' term which has been referred in the previous sections
can be
+ classified into three types of object data: Portal Config, Page Data and
+ Navigation Data; each of which has some differences in the import strategy.
+ </para>
+ <section
id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Navigation_Data">
+ <title>Navigation Data</title>
+ <para>
+ The navigation data import strategy will be processed to the import mode
level as the followings:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>: If the navigation exists,
leave it untouched. Otherwise, import data.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>: Insert the missing description
data, but add only new nodes. Other modifications remains untouched.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal>: Merge the description data, add
missing nodes and update same name nodes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>OVERWRITE</literal>: Always destroy the previous
data and recreate it.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In the GateIn navigation structure, each navigation can be referred
+ to a tree which each node links to a page content. Each node contains some
+ description data, such as label, icon, page reference, and more. Therefore,
GateIn
+ provides a way to insert or merge new data to the initiated navigation tree
or a
+ sub-tree.
+ </para>
+ <para>
+ The merge strategy performs the recursive comparison of child nodes between
the
+ existing persistent nodes of a navigation and the transient nodes provided
by
+ a descriptor:
+ </para>
+ <procedure id="proc-Reference_Guide-Merge_Strategy">
+ <step>
+ <para>
+ Start with the root nodes (which is the effective root node or
another node if the parent URI is specified).
+ </para>
+ </step>
+ <step>
+ <para>
+ Compare the set of child nodes and insert the missing nodes in the
persistent nodes.
+ </para>
+ </step>
+ <step>
+ <para>
+ Proceed recursively for each child having the same name.
+ </para>
+ </step>
+ </procedure>
+ <para>
+ Let's see the example with two navigation nodes in each import mode.
In this case, there are 2 navigation definitions:
+ </para>
+<programlisting language="XML"
role="XML"><![CDATA[<node-navigation>
+ <page-nodes>
+ <node>
+ <name>foo</name>
+ <icon>foo_icon_1</icon>
+ <node>
+ <name>juu</name>
+ <icon>juu_icon</icon>
+ </node>
+ </node>
+ <node>
+ <name>daa</name>
+ <icon>daa_icon</icon>
+ </node>
+ </page-nodes>
+</node-navigation>]]></programlisting>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation1.png"
format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+<programlisting language="XML"
role="XML"><![CDATA[<node-navigation>
+ <page-nodes>
+ <node>
+ <name>foo</name>
+ <icon>foo_icon_2</icon>
+ </node>
+ <node>
+ <name>bar</name>
+ <icon>bar_icon</icon>
+ </node>
+ </page-nodes>
+</node-navigation>]]></programlisting>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation2.png"
format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ For example, the <emphasis>navigation1</emphasis> is loaded before
<emphasis>navigation2</emphasis>. The Navigation
+ Importer processes on two navigation definitions, depending on the Import Mode
defined in portal configuration.
+ </para>
+ <variablelist>
+ <title>Import Mode Cases</title>
+ <varlistentry>
+ <term>Case 1:
<literal>CONSERVE</literal></term>
+ <listitem>
+ <para>
+ With the <literal>CONSERVE</literal> mode, data
are only imported when they do not exist. So, if
+ the navigation has been created by the
<emphasis>navigation1</emphasis> definition, the
<emphasis>navigation2</emphasis> definition
+ does not affect anything on it. We have the result as
following
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata
fileref="images/DataImportStrategy/navigation1.png" format="PNG"
align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 2: <literal>INSERT</literal></term>
+ <listitem>
+ <para>
+ If a node does not exist, the importer will add new nodes
to the navigation tree. You will see the following result:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata
fileref="images/DataImportStrategy/navigation_insert.png" format="PNG"
align="center"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Hereafter, the node 'bar' is added to the
navigation tree, because it does not exist in the initiated data.
+ Other nodes are kept in the import process.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 3: <literal>MERGE</literal></term>
+ <listitem>
+ <para>
+ The <literal>MERGE</literal> mode indicates
that a new node is added to the navigation tree, and
+ updates the node data (such node label and node icon in the
example) if it exists.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata
fileref="images/DataImportStrategy/navigation_merge.png" format="PNG"
align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 4:
<literal>OVERWRITE</literal></term>
+ <listitem>
+ <para>
+ Everything will be destroyed and replaced with new data if
the <literal>OVERWRITE</literal> mode is used.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata
fileref="images/DataImportStrategy/navigation2.png" format="PNG"
align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section
id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Portal_Config">
+ <title>Portal Config</title>
+ <para>
+ PortalConfig defines the portal name, permission, layout and some properties
+ of a site. These information are configured in the
<emphasis>portal.xml</emphasis>, <emphasis>group.xml</emphasis>
or
+ <emphasis>user.xml</emphasis>, depending on the site type. The
PortalConfig importer performs a strategy
+ that is based on the mode defined in NewPortalConfigListener, including
<literal>CONSERVE</literal>,
+ <literal>INSERT</literal>, <literal>MERGE</literal>
or <literal>OVERWRITE</literal>. Let's see how the import mode affects in
the process of
+ portal data performance:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>: There is nothing to be
imported. The existing data will be kept without any changes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>: When the portal config does not
exist, create the new portal defined by the portal config definition. Otherwise, do
nothing.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal> and
<literal>OVERWRITE</literal> have the same behavior. The new portal config
will be created if it does not exist or update portal properties defined by the portal
config definition.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section
id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Page_Data">
+ <title>Page Data</title>
+ <para>
+ The import mode affects the page data import as the same as Portal Config.
+ </para>
+ <note>
+ <para>
+ If the Import mode is <literal>CONSERVE</literal> or
<literal>INSERT</literal>, the data import strategy always performs
+ as the <literal>MERGE</literal> mode in the first data
initialization of the Portal.
+ </para>
+ </note>
+ </section>
+ </section>
+</chapter>
Added:
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml
===================================================================
---
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml
(rev 0)
+++
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml 2011-10-19
05:45:35 UTC (rev 7776)
@@ -0,0 +1,676 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"<literal>http</literal>://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
[
+<!ENTITY % BOOK_ENTITIES SYSTEM "../../Reference_Guide.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="chap-Reference_Guide-Navigation_Controller">
+ <title>Navigation Controller </title>
+ <section id="sect-Reference_Guide-Navigation_Controller-Description">
+ <title>Description</title>
+ <para>The navigation controller is a major enhancement of JBoss Enterprise
Portal Platform that has several goals:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Provide non ambiguous URLs for portal managed resources such as
navigation. Previously different resources were possible for a single URL, even worse, the
set of resources available for an URL was depending on one's private navigation
(groups and dashboard)</para>
+ </listitem>
+ <listitem>
+ <para>Decouple the <literal>http</literal> request from the
portal request. Previously both were tightly coupled, for instance the URL for a site had
to begin with <uri>/public/{sitename}</uri> or
<uri>/private/{sitename}</uri>. The navigation controller provides a flexible
and configurable mapping.</para>
+ </listitem>
+ <listitem>
+ <para>Provide more friendly URL and give a degree of freedom for portal
administrators by letting them configure how <literal>http</literal> request
should look.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section
id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action">
+ <title>Controller in Action</title>
+ <section
id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action-Controller">
+ <title>Controller</title>
+ <para>The <application>WebAppController</application> is the
component of JBoss Enterprise Portal Platform that process
<literal>http</literal> invocations and transforms them into a portal request.
It has been improved with the addition of a request mapping engine (<emphasis
role="bold">controller</emphasis>) whose role is to make the decoupling
of the <literal>http</literal> request and create a portal request.
+ </para>
+ <para>
+ The mapping engine makes two essential tasks:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Create a Map<QualifiedName, String> from an incoming
<literal>http</literal> request</para>
+ </listitem>
+ <listitem>
+ <para>Render a Map<QualifiedName, String> as an
<literal>http</literal> URL</para>
+ </listitem>
+ </itemizedlist>
+ <para>The goal of the controller (mapping engine) is to <emphasis
role="bold">decouple</emphasis> the request processed by JBoss
Enterprise Portal Platform from the incoming <literal>HTTP</literal> request.
+ </para>
+ <para>
+ Indeed a request contain data that determines how the request will be
processed and such data can be encoded in various places in the request such as the
request path or a query parameter. The controller allows JBoss Enterprise Portal Platform
route a request according to a set of parameters (a map) instead of the servlet
request.</para>
+ <para>
+ The controller configuration is declarative in an XML file, allowing easy
reconfiguration of the routing table and it is processed into an internal data structure
that is used to perform resolution (routing or rendering)</para>
+ </section>
+ <section
id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action-Building_Controller">
+ <title>Building Controller</title>
+ <para>The controller configuration that contains the routing rules is loaded
from a file named <filename>controller.xml</filename> that is retrieved in the
JBoss Enterprise Portal Platform configuration directory. Its location is determined by
the <parameter>gatein.controller.config</parameter> property.</para>
+ <para>
+ <application>WebAppController</application> loads and initializes the
mapping engine</para>
+
+<programlisting language="XML"><![CDATA[
+<!-- conf/portal/controller-configuration.xml of portal.war -->
+<component>
+ <type>org.exoplatform.web.WebAppController</type>
+ <init-params>
+ <value-param>
+ <name>controller.config</name>
+ <value>${gatein.portal.controller.config}</value>
+ </value-param>
+ </init-params>
+</component>
+]]></programlisting>
+
+ <para>JBoss Enterprise Portal Platform's extension project can define
their own routing table, because of the extension mechanism.</para>
+ <para>The <filename>controller.xml</filename> can be changed and
reloaded at runtime, this helps the testing of different configurations easily
(configuration loading operations) and provide more insight into the routing engine (the
<literal>findRoutes</literal> operation). see <emphasis
role="bold">Rebuiding controller</emphasis> for more
detail</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReBuilding controller</emphasis>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>The <application>WebAppController</application> is annotated
with <code>@Managed</code> annotations and is bound under the
<code>view=portal,service=controller</code> JMX name and under the
"portalcontroller" REST name.</para>
+ <para>It provides the following attributes and operations</para>
+ <itemizedlist>
+ <listitem>
+ <para>Attribute configurationPath : the read only the configuration path of
the controller xml file</para>
+ </listitem>
+ <listitem>
+ <para>Operation loadConfiguration : load a new configuration file from a
specified xml path</para>
+ </listitem>
+ <listitem>
+ <para>Operation reloadConfiguration : reload the configuration
file</para>
+ </listitem>
+ <listitem>
+ <para>Operation findRoutes : route the request argument through the
controller and returns a list of all parameter map resolution. The argument is a request
uri such as "/groups/:platform:administrators/administration/registry". It
returns a string representation (<code>List<Map></code>) of the
matched routes.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Controller Configuration (controller.xml)</title>
+ <para>Most of the controller configuration cares about defining rules (Routing
table - contains routes object) that will drive the resolution. Routes are processed
during the controller initialization to give a tree of node. Each node</para>
+ <itemizedlist>
+ <listitem>
+ <para>is related to its parent with a matching rule that can either be an
<emphasis role="bold">exact string matching</emphasis> or a
<emphasis role="bold">regular expression matching</emphasis>
+ </para>
+ </listitem>
+ <listitem>
+ <para>is associated with a set of parameters</para>
+ </listitem>
+ </itemizedlist>
+ <para>A parameter is defined by a qualified name and there are three kind of
parameters</para>
+ <section>
+ <title>
+ <emphasis role="bold">Route parameters</emphasis>
+ </title>
+ <para>Route parameters defines a fixed value associate with a qualified
name.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing: route parameters allow the controller to distinguish
branches easily and route the request accordingly.</para>
+ </listitem>
+ <listitem>
+ <para>Rendering: selection occurs when always.</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+</route>
+]]></programlisting>
+ <para>This configuration matches the request path "/foo" to the map
(gtn:handler=portal). Conversely it renders the (gtn:handler=portal) map as the
"/foo" URL. In this example we see two concepts</para>
+ <itemizedlist>
+ <listitem>
+ <para>exact path matching ("/foo")</para>
+ </listitem>
+ <listitem>
+ <para>route parameters ("gtn:handler")</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Path parameters - <emphasis
role="italic">Regular expression support</emphasis>
+ </emphasis>
+ </title>
+ <para>Path parameters allow to associate a portion of the request path with a
parameter. Such parameter will match any non empty portion of text except the <emphasis
role="bold">/</emphasis> character (that is the [^/]+ regular
expression) otherwise they can be associated with a regular expression for matching
specific patterns. Path parameters are mandatory for matching since they are part of the
request path, however it is allowed to write regular expression matching an empty
value.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing: route is accepted if the regular expression is
matched.</para>
+ </listitem>
+ <listitem>
+ <para>Rendering: selection occurs when the regular expression matches the
parameter.</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Encoding</emphasis>
+ </para>
+ <para>Path parameters may contain '/' character which is a reserved
char for URI path. This case is specially handled by the navigation controller by using a
special character to replace '/' literals. By default the character is the semi
colon <emphasis role="bold">:</emphasis> and can be changed to other
possible values (see controller XML schema for possible values) to give a greater amount
of flexibility.</para>
+ <para>This encoding is applied only when the encoding performed for parameter
having a mode set to the <code>default-form</code> value, for instance it does
not happen for navigation node URI (for which <emphasis
role="bold">/</emphasis> are encoded literally). The separator escape
char can still be used but under it's percent escaped form, so by default a path
parameter value containing <emphasis role="bold">:</emphasis> would
be encoded as <code>%3A</code> and conversely the <code>%3A</code>
value will be decoded as <emphasis
role="bold">:</emphasis>.</para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+</route>
+]]></programlisting>
+ <para>No pattern defined, used the default one [^/]+</para>
+<programlisting><![CDATA[
+Routing and Rendering
+Path "/foo" <--> the map (gtn:path=foo)
+
+Path "/foo:bar" <--> the map (gtn:path=foo/bar)
+]]></programlisting>
+ <para>If the request path contains another "/" char it will not
work,default encoding mode is : <emphasis
role="bold">default-form</emphasis>. For example:"/foo/bar"
--> not matched, return empty parameter map</para>
+ <para>However this could be solved with the following
configuration:</para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <orderedlist>
+ <listitem>
+ <para>The .* declaration allows to match any char sequence.</para>
+ </listitem>
+ <listitem>
+ <para>The <emphasis
role="italic">preserve-path</emphasis> <emphasis
role="bold">encoding</emphasis> tells the engine that the "/"
chars should be handled by the path parameter itself as they have a special meaning for
the router. Without this special encoding, "/" would be rendered as the
":<emphasis role="italic">" character and conversely the
":</emphasis>" character would be matched as the "/"
character.</para>
+ </listitem>
+ </orderedlist>
+ </section>
+ <section>
+ <title>Request parameters</title>
+ <para>Request parameters are matched from the request parameters (GET or
POST). The match can be optional as their representation in the request allows
it.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing</para>
+ <itemizedlist>
+ <listitem>
+ <para>route is accepted when a required parameter is present and matched
in the request.</para>
+ </listitem>
+ <listitem>
+ <para>route is accepted when an optional parameter is absent or matched
in the request.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>Rendering:</para>
+ <itemizedlist>
+ <listitem>
+ <para>selection occurs for required parameters when is the parameter is
present and matched in the map.</para>
+ </listitem>
+ <listitem>
+ <para>selection occurs for optional parameters when is the parameter is
absent or matched in the map.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/">
+ <request-param name="path" qname="gtn:path"/>
+</route>
+]]></programlisting>
+ <para>Request parameters are declared by a
<code>request-param</code> element and by default will match any value. A
request like "/?path=foo" is mapped to the (gtn:path=foo) map. The
<code>name</code> attribute of the <code>request-param</code> tag
defines the request parameter value. This element accepts more configuration</para>
+ <itemizedlist>
+ <listitem>
+ <para>a <code>value</code> or a
<code>pattern</code> element a child element to match a constant or a
pattern</para>
+ </listitem>
+ <listitem>
+ <para>a <code>control-mode</code> attribute with the value
<code>optional</code> or <code>required</code> to indicate if
matching is mandatory or not</para>
+ </listitem>
+ <listitem>
+ <para>a <code>value-mapping</code> attribute with the possible
values <code>canonical</code>, <code>never-empty</code>,
<code>never-null</code> can be used to filter filter values after matching is
done. For instance a parameter configured with
<code>value-mapping="never-empty"</code> and matching the empty
string value will not put the empty string in the map.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Route precedence</title>
+ <para>The order of route declaration is important as it influence how rules
are matched. Sometimes the same request could be matched by several routes and the routing
table is ambiguous.</para>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+</route>
+<route path="/{gtn:path}">
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <para>In that case, the request path "/foo" will always be matched
by the first rule before the second rule. This can be misleading since the map
(gtn:path=foo) would be rendered as "/foo" as well and would not be matched by
the first rule. Such ambiguit can happen, it can be desirable or not.</para>
+ </section>
+ <section>
+ <title>Route nesting</title>
+ <para>Route nesting is possible and often desirable as it helps
to</para>
+ <itemizedlist>
+ <listitem>
+ <para>factor common parameters in a common rule</para>
+ </listitem>
+ <listitem>
+ <para>perform more efficient matching as the match of the common rule is
done once for all the sub routes</para>
+ </listitem>
+ </itemizedlist>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+ <route path="/bar">
+ <route-param qname="gtn:path">
+ <value>bar</value>
+ </route-param>
+ </route>
+ <route path="/juu">
+ <route-param qname="gtn:path">
+ <value>juu</value>
+ </route-param>
+ </route>
+</route>
+]]></programlisting>
+ <itemizedlist>
+ <listitem>
+ <para>The request path "/foo/bar" is mapped to the
(gtn:handler=portal,gtn:path=bar) map</para>
+ </listitem>
+ <listitem>
+ <para>The request path "/foo/juu" is mapped to the
(gtn:handler=portal,gtn:path=juu) map</para>
+ </listitem>
+ <listitem>
+ <para>The request path "/foo" is not mapped as non leaf routes do
not perform matches.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+ </section>
+ <section>
+ <title>Integrate to JBoss Enterprise Portal Platform WebUI
framework</title>
+ <section>
+ <title>Routing</title>
+ <para>JBoss Enterprise Portal Platform defines a set of parameters in its
routing table, for each client request, the mapping engine processes the request path and
return the defined parameters with their values as a Map<QualifiedName,
String></para>
+ <para>
+ <emphasis role="bold">gtn:handler</emphasis>
+ </para>
+ <para>The gtn:handler names is one of the most important qualified name as it
determines which handler will take care of the request processing just after the
controller has determined the parameter map. The handler value is used to make a lookup in
the handler map of the controller. An handler is a class that extends the
<code>WebRequestHandler</code> class and implements the
<code>execute(ControllerContext)</code> method. Several handlers are available
by default:</para>
+ <itemizedlist>
+ <listitem>
+ <para>portal : process aggregated portal requests</para>
+ </listitem>
+ <listitem>
+ <para>upload / download : process file upload and file
download</para>
+ </listitem>
+ <listitem>
+ <para>legacy : handle legacy URL redirection (see <emphasis
role="bold">Legacy handler</emphasis> section)</para>
+ </listitem>
+ <listitem>
+ <para>default : <literal>http</literal> redirection to the
default portal of the container</para>
+ </listitem>
+ <listitem>
+ <para>staticResource: serve static resources like image, css or
javascript... files in portal.war (see <emphasis role="bold">Static
Resource Handler</emphasis> section)</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">gtn:sitetype / gtn:sitename /
gtn:path</emphasis>
+ </para>
+ <para>Those qualified names drives a request for the portal handler. They are
used to determine which site to show and which path to resolve against a navigation. For
instance the (gtn:sitetype=portal,gtn:sitename=classic,gtn:path=home) instruct the portal
handler to show the home page of the classic portal site.</para>
+ <para>
+ <emphasis role="bold">gtn:lang</emphasis>
+ </para>
+ <para>The language in the URL for the portal handler. This is a new feature
offered, now language can be specified on URL. that mean user can bookmark that URL (with
the information about language) or he can changed language simply by modifying the URL
address</para>
+ <para>
+ <emphasis role="bold">gtn:componentid / gtn:action /
gtn:objectid</emphasis>
+ </para>
+ <para>The webui parameters used by the portal handler for managing webui
component URLs for portal applications (and not for portlet applications).</para>
+ </section>
+ <section>
+ <title>Rendering</title>
+ <para>The <emphasis role="bold">controller</emphasis> is
designed to render a Map<QualifiedName, String> as an
<literal>http</literal> URL according to its routing table. But to integrate
it for using easily in WebUI Framework of JBoss Enterprise Portal Platform, we need some
more components</para>
+ <section>
+ <title>
+ <emphasis role="bold">PortalURL</emphasis>
+ </title>
+ <para>
+ <code>PortalURL</code> play a similar role at the portal level, its
main role is to abstract the creation of an URL for a resource managed by the
portal.</para>
+<programlisting language="Java"><![CDATA[
+public abstract class PortalURL<R, U extends PortalURL<U>>
+{
+ ...
+}
+]]></programlisting>
+ <para>The <code>PortalURL</code> declaration may seem a bit
strange at first sight with two generic types <code>U</code> and
<code>R</code> and the circular recursion of the <code>U</code>
generic parameter, but it's because most of the time you will not use the
<code>PortalURL</code> object but instead subclasses.</para>
+ <itemizedlist>
+ <listitem>
+ <para>The <code>R</code> generic type represents the type of
the resource managed by the portal</para>
+ </listitem>
+ <listitem>
+ <para>The <code>U</code> generic type is also described as
<emphasis role="bold">self bound generic type</emphasis>. This
design pattern allows a class to return subtypes of itself in the class declaring the
generic type. Java Enums are based on this principle (<code>class Enum<E
extends Enum<E>></code>)</para>
+ </listitem>
+ </itemizedlist>
+ <para>A portal URL has various methods but certainly the most important
method is the <code>toString()</code> method that generates an URL
representing that will target the resource associated with the URL. The remaining methods
are getter and setter for mutating the URL configuration, those options will affect the
URL representation when it is generated.</para>
+ <itemizedlist>
+ <listitem>
+ <para>resource : the mandatory resource associated with the
URL</para>
+ </listitem>
+ <listitem>
+ <para>locale : the optional locale used in the URL allowing the creation of
bookmarkable URL containing a language</para>
+ </listitem>
+ <listitem>
+ <para>confirm : the optional confirm message displayed by the portal in the
context of the portal UI</para>
+ </listitem>
+ <listitem>
+ <para>ajax : the optional ajax option allowing an ajax invocation of the
URL</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Obtaining a PortalURL</emphasis>
+ </para>
+ <para>
+ <code>PortalURL</code> objects are obtained from
<code>RequestContext</code> instance such as the
<code>PortalRequestContext</code> or the PortletRequestContext. Usually those
are obtained thanks to <code>getCurrentInstance</code> method of the
<code>RequestContext</code> class:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+]]></programlisting>
+ <para>
+ <code>PortalURL</code> are created via to the
<code>createURL</code> method that takes as input a resource type. A resource
type is usually a constant and is a type safe object that allow to retrieve
<code>PortalURL</code> subclasses:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+PortalURL<R, U> URL = ctx.createURL(type);
+]]></programlisting>
+ <para>In reality you will use a concrete type constant and have instead more
concrete code like:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+NodeURL URL = ctx.createURL(NodeURL.TYPE);
+]]></programlisting>
+ <note>
+ <para>The <code>NodeURL.TYPE</code> is actually declared as
<code>new ResourceType<NavigationResource, NodeURL>()</code>
that can be described as a <emphasis role="bold">type
literal</emphasis> object emulated by a Java anonymous inner class. Such literal
were introduced by Neil Gafter as Super Type Token and popularized by Google Guice as Type
Literal. It's an interesting way to create a literal representing a kind of Java
type.</para>
+ </note>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Node URL</emphasis>
+ </title>
+ <para>The class <code>NodeURL</code> is one of the subclass of
<code>PortalURL</code> that is specialized for navigation node
resources:</para>
+<programlisting language="Java"><![CDATA[
+public class NodeURL extends PortalURL<NavigationResource, NodeURL>
+{
+ ...
+}
+]]></programlisting>
+ <para>The good news is that the NodeURL does not carry any generic type of
its super class, which means that a NodeURL is type safe and one does not have to worry
about generic types.</para>
+ <para>Using a NodeURL is pretty straightforward:</para>
+<programlisting language="Java"><![CDATA[
+NodeURL URL = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
+URL.setResource(new NavigationResource("portal", "classic,
"home"));
+String s = URL.toString();
+]]></programlisting>
+ <para>The <code>NodeURL</code> subclass contains specialized
setter to make its usage even easier:</para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+NodeURL URL = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
+URL.setNode(node);
+String s = URL.toString();
+]]></programlisting>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Component URL</emphasis>
+ </title>
+ <para>The <code>ComponentURL</code> subclass is another
specialization of <code>PortalURL</code> that allows the creation of WebUI
components URLs. <code>ComponentURL</code> is commonly used to trigger WebUI
events from client side:</para>
+<programlisting><![CDATA[
+<% def componentURL = uicomponent.event(...); /*or uicomponent.URL(...) */ %>
+ <a href=$componentURL>Click me</a>
+]]></programlisting>
+ <para>Normally you should not have to deal with it as the WebUI framework has
already an abstraction for managing URL known as <code>URLBuilder</code>. The
<code>URLBuilder</code> implementation delegates URL creation to
<code>ComponentURL</code> objects.</para>
+ </section>
+ <section>
+ <title>Portlet URLs</title>
+ <para>Portlet URLs API implementation delegates to the portal
<code>ComponentURL</code> (via the portlet container SPI). It is possible to
control the language in the URL from a <code>PortletURL</code> object by
setting a property named <code>gtn:lang</code>:</para>
+ <itemizedlist>
+ <listitem>
+ <para>when the property value is set to a value returned by
<code>Locale#toString()</code> method for locale objects having a non null
language value and a null variant value, the URL generated by the
<code>PortletURL#toString()</code> method will contain the locale in the
URL.</para>
+ </listitem>
+ <listitem>
+ <para>when the property value is set to an empty string, the generated URL
will not contain a language. If the incoming URL was carrying a language, this language
will be erased.</para>
+ </listitem>
+ <listitem>
+ <para>when the property value is not set, it will not affect the generated
URL.</para>
+ </listitem>
+ </itemizedlist>
+<programlisting language="Java"><![CDATA[
+PortletURL URL = resp.createRenderURL();
+URL.setProperty("gtn:lang", "fr");
+writer.print("<a href='" + URL +
"'>French</a>");
+]]></programlisting>
+ </section>
+ <section>
+ <title>Webui <code>URLBuilder</code>
+ </title>
+ <para>This internal API for creating URL works as before and delegates to the
<code>PortletURL</code> API when the framework is executed in a portlet and to
a <code>ComponentURL</code> API when the framework is executed in the portal
context. The API has been modified to take in account the language in URL with two
properties on the builder:</para>
+ <itemizedlist>
+ <listitem>
+ <para>locale : a locale for setting on the URL</para>
+ </listitem>
+ <listitem>
+ <para>removeLocale : a boolean for removing the locale present on the
URL</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Groovy Templates</title>
+ <para>Within a Groovy template the mechanism is the same, however a splash of
integration has been done to make creation of NodeURL simpler. A closure is bound under
the <code>nodeurl</code> name and is available for invocation anytime. It will
simply create a NodeURL object and return it:</para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+NodeURL URL = nodeurl();
+URL.setNode(node);
+String s = URL.toString();
+]]></programlisting>
+ <para>The closure <code>nodeurl</code> is bound to Groovy
template in <code>WebuiBindingContext</code>
+ </para>
+<programlisting language="Java"><![CDATA[
+// Closure nodeurl()
+put("nodeurl", new Closure(this)
+{
+ @Override
+ public Object call(Object[] args)
+ {
+ return context.createURL(NodeURL.TYPE);
+ }
+});
+]]></programlisting>
+ </section>
+ </section>
+ </section>
+ <section>
+ <title>Changes and migration from JBoss Enterprise Portal Platform
3.1.x</title>
+ <para>The navigation controller implies a migration of the client code that is
coupled to several internal APIs of JBoss Enterprise Portal Platform. As far as we know
the major impact is related to anything dealing with URL:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Creation of an URL representing a resource managed by the portal:
navigation node or ui component.</para>
+ </listitem>
+ <listitem>
+ <para>Using <literal>http</literal> request related
information</para>
+ </listitem>
+ </itemizedlist>
+ <para>There are also changes in the configuration, because there is a change of
how things are internally.</para>
+ <section>
+ <title>Migration of navigation node URL</title>
+ <para>
+ <emphasis role="bold">Using free form node</emphasis>
+ </para>
+ <para>Previously code for creating navigation node was like:</para>
+<programlisting language="Java"><![CDATA[
+String uri = Util.getPortalRequestContext().getPortalURI() + "home";
+]]></programlisting>
+ <para>The new code will look like</para>
+<programlisting language="Java"><![CDATA[
+PortalURL nodeURL = nodeurl();
+NavigationResource resource = new NavigationResource(SiteType.PORTAL,
pcontext.getPortalOwner(), "home");
+String uri = nodeURL.setResource(resource).toString();
+]]></programlisting>
+ <para>
+ <emphasis role="bold">Using UserNode object</emphasis>
+ </para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+String uri = Util.getPortalRequestContext().getPortalURI() + node.getURI()";
+]]></programlisting>
+ <para>The new code will look like</para>
+
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+PortalURL nodeURL = nodeurl();
+String uri = nodeURL.setNode(node).toString();
+]]></programlisting>
+ </section>
+ <section>
+ <title>Security changes</title>
+ <para>Security configuration change in order to keep with the flexibility
added by the navigation controller. In particular the authentication does not depend
anymore on path specified in <code>web.xml</code> but instead rely on the
security mandated by the underlying resource. Here are the noticeable changes for
security</para>
+ <itemizedlist>
+ <listitem>
+ <para>Authentication is now triggered on the /login URL when it does not
have a username or a password specified. Therefore the URL
<code>/login?initialURI=/classic/home</code> is (more or less) equivalent to
<code>/private/classic/home</code>
+ </para>
+ </listitem>
+ <listitem>
+ <para>When a resource cannot be viewed due to security
constraint</para>
+ <itemizedlist>
+ <listitem>
+ <para>If the user is not logged, the authentication will be
triggered</para>
+ </listitem>
+ <listitem>
+ <para>Otherwise a special page (the usual one) will be displayed
instead</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Default handler</title>
+ <para>Redirection to the default portal used to be done by the
<code>index.jsp</code> JSP page. This is not the case anymore, the index.jsp
has been removed and the welcome file in <code>web.xml</code> was removed too.
Instead a specific handler in the routing table has been configured, the sole role of this
handler is to redirect the request to default portal when no other request has been
matched previously:</para>
+
+<programlisting language="XML"><![CDATA[
+<controller>
+ ...
+ <route path="/">
+ <route-param qname="gtn:handler">
+ <value>default</value>
+ </route-param>
+ </route>
+</controller>
+]]></programlisting>
+ </section>
+ <section>
+ <title>Legacy handler</title>
+ <para>Legacy URLs such as <code>/public/...</code> and
<code>/private/...</code> are now emulated to determine the best resource with
the same resolution algorithm than before but instead of displaying the page, will make an
<literal>http</literal> 302 redirection to the correct URL. This handler is
present in the controller configuration. There is a noticeable difference between the two
routes</para>
+ <itemizedlist>
+ <listitem>
+ <para>The public redirection attempt to find a node with the legacy
resolution algorithm without authentication, which means that secured nodes will not be
resolved and the redirection of a secured node will likely redirect to another page. For
instance resolving the URL /public/classic/administration/registry path will likely
resolve to another node if the user is not authenticated and is not part of the platform
administrator group.</para>
+ </listitem>
+ <listitem>
+ <para>The private redirection performs first an authentication before doing
the redirection. In that case the /private/classic/administration/registry path will
resolve be redirected to the
/portal/groups/:platform:administrators/administration/registry page if the user has the
sufficient security rights.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Static resource handler</title>
+ <para>The "/" mapping for "default" servlet is now
replaced by mapping for org.exoplatform.portal.application.PortalController servlet, that
mean we need a handler (<emphasis
role="bold">org.exoplatform.portal.application.StaticResourceRequestHandler</emphasis>)
to serve static resources like image, css or javascript... files in portal.war. And it
should be configured, and extended easily. Thanks to the controller.xml. This file can be
overridden and can be changed and reloaded at runtime (WebAppController is MBean with some
operations such as : reloadConfiguration() ...)</para>
+ <para>Declare StaticResourceHandler in controller.xml</para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+ <route-param qname="gtn:handler">
+ <value>staticResource</value>
+ </route-param>
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*\.(jpg|png|gif|ico|css)</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <para>And we don't need these kind of following mapping in
portal.war's web.xml anymore :</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <URL-pattern>*.jpg</URL-pattern>
+</servlet-mapping>
+...
+]]></programlisting>
+ </section>
+ <section>
+ <title>portal.war's web.xml changes</title>
+ <para>DoLoginServlet declaration</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet>
+ <servlet-name>DoLoginServlet</servlet-name>
+ <servlet-class>org.exoplatform.web.login.DoLoginServlet</servlet-class>
+</servlet>
+<servlet-mapping>
+ <servlet-name>DoLoginServlet</servlet-name>
+ <URL-pattern>/dologin</URL-pattern>
+</servlet-mapping>
+]]></programlisting>
+ <para>Delare <emphasis role="bold">portal
servlet</emphasis> as default servlet</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet-mapping>
+ <servlet-name>portal</servlet-name>
+ <URL-pattern>/</URL-pattern>
+</servlet-mapping>
+]]></programlisting>
+ <para>So there are some mapping declaration for portal servlet are unused, we
should also remove them: <emphasis role="bold">
+ <emphasis role="italic">/private/* /public/* /admin/* /upload/*
/download/*</emphasis>
+ </emphasis>
+ </para>
+ <para>Add some security constraints</para>
+
+<programlisting language="XML"><![CDATA[
+<security-constraint>
+ <web-resource-collection>
+ <web-resource-name>user authentication</web-resource-name>
+ <URL-pattern>/dologin</URL-pattern>
+ <URL-pattern>/groups/*</URL-pattern>
+ <URL-pattern>/users/*</URL-pattern>
+...
+ </web-resource-collection>
+</security-constraint>
+]]></programlisting>
+ <para>We can remove the index.jsp, and its declaration in web.xml now, thank
to the Default request handler</para>
+
+<programlisting language="XML"><![CDATA[
+<welcome-file-list>
+ <welcome-file>/index.jsp</welcome-file>
+</welcome-file-list>
+]]></programlisting>
+ </section>
+ <section>
+ <title>Dashboard changes</title>
+ <para>There are several important changes to take in account</para>
+ <itemizedlist>
+ <listitem>
+ <para>dashboard are now bound to a single URL (/users/root by default) and
dashboard pages are leaf of this path</para>
+ </listitem>
+ <listitem>
+ <para>dashboard life cycle can be decoupled (create / destroy) from the
identity creation in a configurable manner in
<code>UserPortalConfigService</code> and exposed in configuration.properties
under <code>gatein.portal.idm.createuserportal</code> and
<code>gatein.portal.idm.destroyuserportal</code>.</para>
+ </listitem>
+ <listitem>
+ <para>by default dashboard are not created when a user is
registered</para>
+ </listitem>
+ <listitem>
+ <para>a dashboard is created when the user access his dashboard
URL</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Remove unused files</title>
+ <para>1/ portal-unavailable.jsp: this file was presented before if user goes
to a non-available portal. Now the server sends a 404 status code instead.</para>
+ <para>2/ portal-warning.jsp: this file is not used in any place</para>
+ </section>
+ </section>
+</chapter>