JBoss Rich Faces SVN: r19626 - in modules/docs/trunk: Component_Reference/src/main/docbook/en-US and 3 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: SeanRogers
Date: 2010-10-21 02:34:43 -0400 (Thu, 21 Oct 2010)
New Revision: 19626
Added:
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richselectOne-Selection_items.xml_sample
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-Pop-up_positioning.png
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-richcalendar.png
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richselectOne-richselectOne.png
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richtoolTip-richtoolTip.png
Modified:
modules/docs/trunk/
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml
modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml
modules/docs/trunk/Migration_Guide/src/main/docbook/en-US/Changes_and_new_features.xml
Log:
Merged revisions 19591,19610-19612,19623-19624 via svnmerge from
http://svn.jboss.org/repos/richfaces/modules/docs/branches/m4
.......
r19591 | SeanRogers | 2010-10-18 16:53:34 +1000 (Mon, 18 Oct 2010) | 1 line
Started rich:selectOne and rich:calendar
.......
r19610 | SeanRogers | 2010-10-20 13:30:01 +1000 (Wed, 20 Oct 2010) | 1 line
Draft of richselectOne complete
.......
r19611 | SeanRogers | 2010-10-20 13:31:28 +1000 (Wed, 20 Oct 2010) | 1 line
Added selectOne extras
.......
r19612 | SeanRogers | 2010-10-20 16:14:32 +1000 (Wed, 20 Oct 2010) | 1 line
Draft of rich:calendar complete
.......
r19623 | SeanRogers | 2010-10-21 11:32:01 +1000 (Thu, 21 Oct 2010) | 1 line
Draft of rich:calendar complete
.......
r19624 | SeanRogers | 2010-10-21 16:14:48 +1000 (Thu, 21 Oct 2010) | 1 line
Draft of rich:toolTip complete
.......
Property changes on: modules/docs/trunk
___________________________________________________________________
Name: svnmerge-integrated
- /modules/docs/branches/m4:1-19589
+ /modules/docs/branches/m4:1-19625
Modified: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml 2010-10-21 06:29:05 UTC (rev 19625)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml 2010-10-21 06:34:43 UTC (rev 19626)
@@ -369,10 +369,10 @@
</example>
</section>
- <section id="sect-Component_Reference-richaccordion-Update_mode">
+ <section id="sect-Component_Reference-richprogressBar-Update_mode">
<title>Update mode</title>
<para>
- The mode for updating the progress bar is determined by the <code>mode</code> attribute, which can have one of the following values:
+ The mode for updating the progress bar is determined by the <varname>mode</varname> attribute, which can have one of the following values:
</para>
<variablelist>
<varlistentry>
@@ -393,16 +393,256 @@
</varlistentry>
</variablelist>
</section>
+
+ <section id="sect-Component_Reference-richprogressBar-Reference_data">
+ <title>Reference data</title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <parameter>component-type</parameter>: <classname>org.richfaces.ProgressBar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-class</parameter>: <classname>org.richfaces.component.html.HtmlProgressBar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-family</parameter>: <classname>org.richfaces.component.ProgressBar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>renderer-type</parameter>: <classname>org.richfaces.renderkit.ProgressBarRenderer</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>tag-class</parameter>: <classname>org.richfaces.taglib.ProgressBarTag</classname>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
</section>
<!-- <rich:toolTip> -->
- <!--
<section id="sect-Component_Reference-Output_and_messages-richtoolTip">
<title><sgmltag><rich:toolTip></sgmltag></title>
<para>
- Incomplete
+ The <sgmltag><rich:toolTip></sgmltag> component provides an informational tool-tip. The tool-tip can be attached to any control and is displayed when hovering the mouse cursor over the control.
</para>
+ <figure id="figu-Component_Reference-richtoolTip-richtoolTip">
+ <title><sgmltag><rich:toolTip></sgmltag></title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/figu-Component_Reference-richtoolTip-richtoolTip.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <para>
+ A <sgmltag><rich:toolTip></sgmltag> component, displayed while hovering the mouse cursor over a button control.
+ </para>
+ </textobject>
+ </mediaobject>
+ </figure>
+
+ <section id="sect-Component_Reference-richtoolTip-Basic_usage">
+ <title>Basic usage</title>
+ <para>
+ For basic usage, define the tool-tip text using the <varname>value</varname> attribute. The <sgmltag><rich:toolTip></sgmltag> component is then automatically attached to the parent element, and is usually shown when the mouse cursor hovers.
+ </para>
+ <para>
+ Alternatively, the content of the tool-tip can be defined inside the <sgmltag><rich:toolTip></sgmltag> tags, and the <varname>value</varname> attribute is not used. This allows HTML tags to be used to define the content, and provides for rich content such as images, links, buttons, and other RichFaces components.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Defining_tool-tip_content">
+ <title>Defining tool-tip content</title>
+ <variablelist>
+ <varlistentry>
+ <term>Basic content</term>
+ <listitem>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Rich content</term>
+ <listitem>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </example>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Attaching_the_tool-tip_to_another_component">
+ <title>Attaching the tool-tip to another component</title>
+ <para>
+ If not otherwise specified, the tool-tip is attached to the parent element in which it is defined. The <varname>for</varname> attribute is used to attach the tool-tip to another component, pointing to the target component's <varname>id</varname> identifier. This allows the <sgmltag><rich:toolTip></sgmltag> component to be specified outside the target element. This approach is demonstrated in <xref linkend="exam-Component_Reference-richtoolTip-Attaching_the_tool-tip" />.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Attaching_the_tool-tip">
+ <title>Attaching the tool-tip</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ The <sgmltag><rich:toolTip></sgmltag> component can alternatively be left unattached, and is instead invoked through an event handler on the target component. To leave the <sgmltag><rich:toolTip></sgmltag> component unattached, set <code>attached="false"</code>, and define the event handler to trigger the tool-tip on the target component. This approach is demonstrated in <xref linkend="exam-Component_Reference-richtoolTip-Unattached_tool-tips" />. When leaving the <sgmltag><rich:toolTip></sgmltag> component unattached, ensure it has an <varname>id</varname> identifier defined. If the <sgmltag><rich:toolTip></sgmltag> component is nested inside the target element, it must be the last child. If it is defined outside the target element, it must be nested in an <sgmltag><a4j:form></sgmltag> component.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Unattached_tool-tips">
+ <title>Unattached tool-tips</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Appearance">
+ <title>Appearance</title>
+ <para>
+ By default, the <sgmltag><rich:toolTip></sgmltag> component is positioned intelligently based on the position of the mouse cursor. Use the <varname>direction</varname> attribute to specify a corner of the target component at which to display the tool-tip instead. Possible values include <literal>top-left</literal>, <literal>top-right</literal>, <literal>bottom-left</literal>, and <literal>bottom-right</literal>. Use the <varname>horizontalOffset</varname> and <varname>verticalOffset</varname> attributes to specify the horizontal offset and vertical offset at which to display the tool-tip.
+ </para>
+ <para>
+ Use the <varname>hideEvent</varname> attribute to specify when the tool-tip is hidden. The default value is <literal>none</literal>, so the tool-tip remains shown. However, it can be linked to an event on the target component, such as the <literal>mouseout</literal> event.
+ </para>
+ <para>
+ Set <code>followMouse="true"</code> to cause the tool-tip to follow the user's mouse movements.
+ </para>
+ <para>
+ Advanced appearance features are demonstrated in <xref linkend="exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage" />.
+ </para>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Update_mode">
+ <title>Update mode</title>
+ <para>
+ The mode for updating the tool-tip is determined by the <varname>mode</varname> attribute, which can have one of the following values:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>ajax</literal></term>
+ <listitem>
+ <para>
+ The tool-tip content is requested from the server with every activation.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>client</literal></term>
+ <listitem>
+ <para>
+ The tool-tip content is rendered once on the server. An external submit causes the content to re-render.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+ When using <code>mode="ajax"</code>, define the <literal>defaultContent</literal> facet. The tool-tip displays the content of the <literal>defaultContent</literal> facet while loading the actual content from the server.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage">
+ <title>Advanced tool-tip usage</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-richtoolTip_client-side_events">
+ <title><sgmltag><rich:toolTip></sgmltag> client-side events</title>
+ <para>
+ The <sgmltag><rich:toolTip></sgmltag> component supports the following client-side events:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>onclick</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is clicked with the mouse.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ondblclick</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is double-clicked with the mouse.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onmouseout</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the mouse cursor leaves the tool-tip.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onmousemove</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the mouse cursor moves over the tool-tip.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onmouseover</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the mouse cursor hovers over the tool-tip.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onshow</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is shown.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>oncomplete</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is completed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onhide</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is hidden.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Reference_data">
+ <title>Reference data</title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <parameter>component-type</parameter>: <classname>org.richfaces.component.toolTip</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-class</parameter>: <classname>org.richfaces.component.html.HtmlToolTip</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-family</parameter>: <classname>org.richfaces.component.toolTip</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>renderer-type</parameter>: <classname>org.richfaces.renderkit.html.toolTipRenderer</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>tag-class</parameter>: <classname>org.richfaces.taglib.HtmlToolTipTag</classname>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
</section>
- -->
</chapter>
Modified: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml 2010-10-21 06:29:05 UTC (rev 19625)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml 2010-10-21 06:34:43 UTC (rev 19626)
@@ -11,93 +11,188 @@
</para>
</important>
<para>
- This chapter details those components which act as panels and containers to hold groups of other components.
+ This chapter details rich components for user input and interaction.
</para>
- <!-- TODO not in M3 -->
- <!--
- <para>
- This chapter details rich components for user input and interaction.
- </para>
+ <!-- <rich:calendar> -->
<section id="sect-Component_Reference-Rich_inputs-richcalendar">
<title><sgmltag><rich:calendar></sgmltag></title>
<para>
The <sgmltag><rich:calendar></sgmltag> component allows the user to enter a date and time through an in-line or pop-up calendar. The pop-up calendar can navigate through months and years, and its look and feel can be highly customized.
</para>
- <para>
- The <sgmltag><rich:calendar></sgmltag> component supports two different ways of loading data through defining the <varname>mode</varname> attribute. When not specified, the component uses <literal>client</literal> mode, which loads an initial portion of data within a set date range. The range can be defined by using the <varname>preloadDateRangeBegin</varname> and <varname>preloadDateRangeEnd</varname> attributes. Additional data requests are not sent. Alternatively, with <code>mode="ajax"</code> the <sgmltag><rich:calendar></sgmltag> requests portions of data for rendering from a special data model. The data model can be defined through the <varname>dataModel</varname> attribute, which points to an object that implements the <classname>CalendarDataModel</classname> interface. If the <varname>dataModel</varname> attribute is not defined or has a value of <literal>null</literal>, the <literal>ajax</literal> mode functions the same as the <literal>client</liter!
al> mode.
- </para>
- <para>
- The <sgmltag><rich:calendar></sgmltag> component is presented as a pop-up by default, appearing as a text field with a button to expand the full pop-up calendar. Specifying <code>popup="false</code> will render the calendar in-line on the page instead, which displays the full calendar without the text field or display button. The appearance of the display button can be altered from the standard calendar icon by defining the <varname>buttonIcon</varname> and <varname>buttonIconDisabled</varname> attributes to replace the icon with a specified file, or by defining the <varname>buttonLabel</varname> attribute to display text on the button without an icon. If <varname>buttonLabel</varname> is specified then both <varname>buttonIcon</varname> and <varname>buttonIconDisabled</varname> attributes are ignored. The text field box can also be hidden by setting <code>showInput="false"</code>.
- </para>
- <para>
- The position at which the pop-up calendar displays relative to the text field and button can be configured using the <varname>jointPoint</varname> and <varname>direction</varname> attributes. The <varname>jointPoint</varname> attribute refers to the corner of the text field and button with which the calendar will be aligned and the <varname>direction</varname> specifies which direction the pop-up calendar will span relative to the joint point. The default settings are <code>jointPoint="bottom-left"</code> and <code>direction="bottom-right"</code>, causing the pop-up calendar to align with the bottom-left corner of the text field and span to the bottom-right, underneath the text field and button. The diagram shows the joint points and directions that can be used. Alternatively, both <varname>jointPoint</varname> and <varname>direction</varname> can be set to <literal>auto</literal> to allow smart pop-up positioning.
- </para>
- <para>
- The calendar features a <guibutton>Today</guibutton> button for locating today's date on the calendar. This can be set to three different values using the <varname>todayControlMode</varname> attribute:
- </para>
- <itemizedlist>
- <listitem>
+
+ <figure id="figu-Component_Reference-richcalendar-richcalendar">
+ <title><sgmltag><rich:calendar></sgmltag></title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/figu-Component_Reference-richcalendar-richcalendar.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <para>
+ An expanded <sgmltag><rich:calendar></sgmltag> component, displaying the calendar month of December, 2010.
+ </para>
+ </textobject>
+ </mediaobject>
+ </figure>
+
+ <section id="sect-Component_Reference-richcalendar-Basic_usage">
+ <title>Basic usage</title>
+ <para>
+ Basic usage of the <sgmltag><rich:calendar></sgmltag> component requires only the <varname>value</varname> attribute, which holds the currently selected date. <xref linkend="exam-Component_Reference-richcalendar-Basic_usage" /> shows a basic declaration, with the value pointing to a data model.
+ </para>
+ <example id="exam-Component_Reference-richcalendar-Basic_usage">
+ <title>Basic usage</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section id="sect-Component_Reference-richcalendar-Using_a_data_model">
+ <title>Using a data model</title>
+ <para>
+ The <sgmltag><rich:calendar></sgmltag> component supports two different ways of loading data through defining the <varname>mode</varname> attribute. When not specified, the component uses <literal>client</literal> mode, which loads an initial portion of data within a set date range. The range can be defined by using the <varname>preloadDateRangeBegin</varname> and <varname>preloadDateRangeEnd</varname> attributes. Additional data requests are not sent.
+ </para>
+ <para>
+ Alternatively, with <code>mode="ajax"</code> the <sgmltag><rich:calendar></sgmltag> requests portions of data for rendering from a special data model. The data model can be defined through the <varname>dataModel</varname> attribute, which points to an object that implements the <classname>CalendarDataModel</classname> interface. If the <varname>dataModel</varname> attribute is not defined or has a value of <literal>null</literal>, the <literal>ajax</literal> mode functions the same as the <literal>client</literal> mode.
+ </para>
+ </section>
+
+ <section id="sect-Component_Reference-richcalendar-Behavior_and_appearance">
+ <title>Behavior and appearance</title>
+ <para>
+ The <sgmltag><rich:calendar></sgmltag> component is presented as a pop-up by default, appearing as a text field with a button to expand the full pop-up calendar. To render the calendar in-line on the page instead, set <code>popup="false</code>. This displays the full calendar without the text field or display button.
+ </para>
+ <para>
+ To change the appearance of the display button from the standard calendar icon, use the <varname>buttonIcon</varname> and <varname>buttonIconDisabled</varname> attributes to replace the icon with a specified file. Alternatively, use the <varname>buttonLabel</varname> attribute to display text on the button without an icon. If <varname>buttonLabel</varname> is specified then both the <varname>buttonIcon</varname> and <varname>buttonIconDisabled</varname> attributes are ignored. To hide the text field box, set <code>showInput="false"</code>.
+ </para>
+ <para>
+ To change the default position at which the pop-up calendar is shown relative to the text field and button, use the <varname>jointPoint</varname> and <varname>direction</varname> attributes. The <varname>jointPoint</varname> attribute refers to the corner of the text field and button with which the calendar will be aligned and the <varname>direction</varname> specifies which direction the pop-up calendar will span relative to the joint point. The default settings are <code>jointPoint="bottom-left"</code> and <code>direction="bottom-right"</code>, causing the pop-up calendar to align with the bottom-left corner of the text field and span to the bottom-right, underneath the text field and button. The diagram shows the joint points and directions that can be used. Alternatively, set both <varname>jointPoint</varname> and <varname>direction</varname> attributes to <literal>auto</literal> to allow smart pop-up positioning. <xref linkend="figu-Component_Reference-richcalendar!
-Pop-up_positioning" /> shows the different possible settings for the <varname>jointPoint</varname> and <varname>direction</varname> attributes.
+ </para>
+ <figure id="figu-Component_Reference-richcalendar-Pop-up_positioning">
+ <title>Pop-up positioning</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/figu-Component_Reference-richcalendar-Pop-up_positioning.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <para>
+ Pop-up positioning is determined using the <varname>jointPoint</varname> and <varname>direction</varname> attributes.
+ </para>
+ </textobject>
+ </mediaobject>
<para>
- <literal>hidden</literal>, which does not display the button;
+ Pop-up positioning is determined using the <varname>jointPoint</varname> and <varname>direction</varname> attributes. Values for the <varname>jointPoint</varname> attribute are shown in red, while values for the <varname>direction</varname> attribute are shown in black.
</para>
- </listitem>
- <listitem>
- <para>
- <literal>select</literal>, the default setting, which scrolls the calendar to the current month and selects today's date; and
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>scroll</literal>, which scrolls the calendar to the current month but does not select today's date.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The <sgmltag><rich:calendar></sgmltag> component can additionally allow a time of day to be specified with the date. After selecting a date the option to set a time becomes available. The default time can be set with the <varname>defaultTime</varname> attribute. If the time is altered and a new date is selected, it will not reset unless <code>resetTimeOnDateSelect="true"</code> is specified.
- </para>
- <para>
- There are several event handlers that are unique to the <sgmltag><rich:calendar></sgmltag> component.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <varname>ondateselect</varname> is triggered when the date is selected by the user, before the update request is sent.
- </para>
- </listitem>
- <listitem>
- <para>
- <varname>ondateselected</varname> is triggered after the date is selected by the user.
- </para>
- </listitem>
- <listitem>
- <para>
- <varname>oncurrentdateselect</varname> is triggered when any of the year- or month-changing buttons are pressed, before the update request is sent.
- </para>
- </listitem>
- <listitem>
- <para>
- <varname>oncurrentdateselected</varname> is triggered after any of the year- or month-changing buttons are pressed.
- </para>
- </listitem>
- <listitem>
- <para>
- <varname>ontimeselect</varname> is triggered when the time is set by the user, before the update request is sent.
- </para>
- </listitem>
- <listitem>
- <para>
- <varname>ontimeselected</varname> is triggered after the time has been set by the user.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The entire calendar can be set as read-only with <code>readonly="true"</code>. This allows months and years to be browsed through with the arrow controls, but dates and times cannot be selected.
- </para>
+ </figure>
+ <para>
+ The calendar features a <guibutton>Today</guibutton> button for locating today's date on the calendar. This can be set to three different values using the <varname>todayControlMode</varname> attribute:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>hidden</literal>, which does not display the button;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>select</literal>, the default setting, which scrolls the calendar to the current month and selects today's date; and
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>scroll</literal>, which scrolls the calendar to the current month but does not select today's date.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ To make the entire calendar read-only, set <code>readonly="true"</code>. This allows months and years to be browsed through with the arrow controls, but dates and times cannot be selected.
+ </para>
+ <!-- TODO not in M4 -->
+ <!--
+ <para>
+ The styling and appearance of the calendar can be fully customized using facets.
+ </para>
+ -->
+ </section>
+
+ <section id="sect-Component_Reference-richcalendar-Time_of_day">
+ <title>Time of day</title>
+ <para>
+ The <sgmltag><rich:calendar></sgmltag> component can additionally allow a time of day to be specified with the date. After selecting a date the option to set a time becomes available. The default time can be set with the <varname>defaultTime</varname> attribute. If the time is altered and a new date is selected, it will not reset unless <code>resetTimeOnDateSelect="true"</code> is specified.
+ </para>
+ </section>
+
+ <section id="sect-Component_Reference-richcalendar-richcalendar_events">
+ <title><sgmltag><rich:calendar></sgmltag> events</title>
+ <para>
+ There are several event handlers that are unique to the <sgmltag><rich:calendar></sgmltag> component.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <varname>ondateselect</varname> is triggered when the date is selected by the user, before the update request is sent.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <varname>ondateselected</varname> is triggered after the date is selected by the user.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <varname>oncurrentdateselect</varname> is triggered when any of the year- or month-changing buttons are pressed, before the update request is sent.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <varname>oncurrentdateselected</varname> is triggered after any of the year- or month-changing buttons are pressed.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <varname>ontimeselect</varname> is triggered when the time is set by the user, before the update request is sent.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <varname>ontimeselected</varname> is triggered after the time has been set by the user.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="sect-Component_Reference-richcalendar-Reference_data">
+ <title>Reference data</title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <parameter>component-type</parameter>: <classname>org.richfaces.calendar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-class</parameter>: <classname>org.richfaces.component.html.HtmlCalendar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-family</parameter>: <classname>org.richfaces.calendar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>renderer-type</parameter>: <classname>org.richfaces.renderkit.calendarRenderer</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>tag-class</parameter>: <classname>org.richfaces.taglib.calendarTag</classname>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
</section>
- -->
- <!-- TODO not in M3 -->
+ <!-- TODO not in M4 -->
<!--
<section id="sect-Component_Reference-Rich_inputs-richcolorPicker">
<title><sgmltag><rich:colorPicker></sgmltag></title>
@@ -231,7 +326,7 @@
</section>
</section>
- <!-- TODO not in M3 -->
+ <!-- TODO not in M4 -->
<!--<rich:autocompleteBehavior>-->
<!--
<section id="sect-Component_Reference-Rich_inputs-richautocompleteBehavior">
@@ -282,7 +377,7 @@
</section>
-->
- <!-- TODO not in M3 -->
+ <!-- TODO not in M4 -->
<!--
<section id="sect-Component_Reference-Rich_inputs-richeditor">
<title><sgmltag><rich:editor></sgmltag></title>
@@ -402,13 +497,13 @@
</para>
<para>
The user can confirm and save their input by pressing the <keycap>Enter</keycap> key or cancel by pressing the <keycap>Esc</keycap> key. Alternatively, buttons for confirming or canceling can be added to the component by setting <code>showControls="true"</code>.
- <!-- TODO not in M3
+ <!-- TODO not in M4
These buttons can be positioned using the <varname>controlsHorizontalPosition</varname> attribute with settings of <literal>left</literal>, <literal>right</literal>, or <literal>center</literal>, and the <varname>controlsVerticalPosition</varname> attribute with settings <literal>bottom</literal>, <literal>center</literal>, or <literal>top</literal>. The confirmation control icons can be altered using the <varname>saveControlIcon</varname> and <varname>cancelControlIcon</varname>. Further customization is possible through the use of facets.
-->
</para>
</section>
- <!-- TODO not in M3
+ <!-- TODO not in M4
<section id="sect-Component_Reference-richinplaceInput-richinplaceInput_events">
<title><sgmltag><rich:inplaceInput></sgmltag> events</title>
<para>
@@ -471,7 +566,7 @@
</section>
</section>
- <!-- TODO not in M3 -->
+ <!-- TODO not in M4 -->
<!--<rich:inplaceSelect>-->
<!--
<section id="sect-Component_Reference-Rich_inputs-richinplaceSelect">
@@ -725,32 +820,87 @@
</itemizedlist>
</section>
</section>
-
- <!-- TODO not in M3 -->
- <!--<rich:suggestionBox>-->
- <!--
- <section id="sect-Component_Reference-Rich_inputs-richsuggestionBox">
- <title><sgmltag><rich:suggestionBox></sgmltag></title>
+
+ <!-- <rich:selectOne> -->
+ <section id="sect-Component_Reference-Rich_inputs-richselectOne">
+ <title><sgmltag><rich:selectOne></sgmltag></title>
<para>
- The <sgmltag><rich:suggestionBox></sgmltag> component adds a feature-rich drop-down list of suggestions to any text input component.
+ The <sgmltag><rich:selectOne></sgmltag> component provides a drop-down list box for selecting a single value from multiple options. The component supports keyboard navigation and can optionally accept typed input as a combo-box.
</para>
- <para>
- The <sgmltag><rich:suggestionBox></sgmltag> component needs the attributes defined for basic use: <varname>for</varname>, which identifies the component to attach the suggestion box to; <varname>suggestionAction</varname>, which defines the method for getting the collection of suggestion data; and <varname>var</varname>, which defines a collection name for access to the currently highlighted row. Typically the suggestions are presented as a list with one or more columns of suggestion data; the layout of these columns is defined inside the <sgmltag><rich:suggestionBox></sgmltag> tags using <sgmltag><h:column></sgmltag> and other <acronym>JSF</acronym> components.
- </para>
- <para>
- For suggestion lists with multiple columns, the <varname>fetchValue</varname> attribute can be used to specify which column is used when selecting the value for the input component.
- </para>
- <para>
- The <varname>tokens</varname> attribute can be used to define separator characters, which are used when multiple values need to be entered and a new suggestion made for each value. For example, <code>tokens=","</code> (a comma) will begin a new suggestion query each time a comma is typed. Multiple separators can be defined with spaces in between (<code>tokens=", . ; [ ]"</code>) or linking to a bean property that holds the collection of separator tokens.
- </para>
- <para>
- The <varname>minChars</varname> attribute can be used to limit sending the Ajax request until a certain amount of characters has been entered. If the query returns no results, an appropriate message to display can be set with the <varname>nothingLabel</varname> attribute.
- </para>
- <para>
- Instead of returning just one value from an object, the entire object can be returned to the client and handled appropriately. This is done by specifying <code>usingSuggestObjects="true"</code> and setting the <varname>onobjectchange</varname> attribute to a JavaScript method to handle the object, passing the <literal>suggestion</literal> object as a parameter.
- </para>
+
+ <figure id="figu-Component_Reference-richselectOne-richselectOne">
+ <title><sgmltag><rich:selectOne></sgmltag></title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/figu-Component_Reference-richselectOne-richselectOne.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <para>
+ A <sgmltag><rich:selectOne></sgmltag> component used as a combo-box.
+ </para>
+ </textobject>
+ </mediaobject>
+ </figure>
+
+ <section id="sect-Component_Reference-richselectOne-Basic_usage">
+ <title>Basic usage</title>
+ <para>
+ Simple usage of the <sgmltag><rich:selectOne></sgmltag> component does not need any attributes declared, but child tags to manage the list of selections are required. An <sgmltag><f:selectItem></sgmltag> tag manages the currently selected value, while an <sgmltag><f:selectItems></sgmltag> tag points to the list of selection items.
+ </para>
+ <example id="exam-Component_Reference-richselectOne-Selection_items">
+ <title>Selection items</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richselectOne-Selection_items.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ The arrow keys on a keyboard can be used to highlight different items in the list, even if the list is closed with the control still focused. If the control loses focus or the <keycap function="enter">Enter</keycap> key is pressed, the highlighted option is chosen as the value and the list is closed. Pressing the <keycap function="escape">Esc</keycap> key will close the list but not change the value.
+ </para>
+ </section>
+
+ <section id="sect-Component_Reference-richselectOne-Using_richselectOne_as_a_combo-box">
+ <title>Using <sgmltag><rich:selectOne></sgmltag> as a combo-box</title>
+ <para>
+ Combo-boxes are drop-down lists that allow the user to type into a text field to scroll through or filter the list. By default, the <sgmltag><rich:selectOne></sgmltag> component functions as a drop-down list. To add keyboard support to make it function like a combo-box, set <code>enableManualInput="true"</code>.
+ </para>
+ <para>
+ Once the user begins typing, the first available matching option is highlighted. If the typed text does not match any values in the list, no value is chosen and the drop-down list displays as empty. Other keyboard interaction remains the same as the basic drop-down list.
+ </para>
+ <para>
+ Typing text into a combo-box causes the list to scroll to the relevant item by default. This behavior can be changed so that the typed text filters the contents of the list instead, showing only those items that begin with the typed text. To use typed text as a filter for combo-box lists, set <code>filterOnUpdates="true"</code>.
+ </para>
+ </section>
+
+ <section id="sect-Component_Reference-richselectOne-Reference_data">
+ <title>Reference data</title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <parameter>component-type</parameter>: <classname>org.richfaces.selectOne</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-class</parameter>: <classname>org.richfaces.component.html.HtmlSelectOne</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-family</parameter>: <classname>org.richfaces.selectOne</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>renderer-type</parameter>: <classname>org.richfaces.renderkit.selectOneRenderer</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>tag-class</parameter>: <classname>org.richfaces.taglib.selectOneTag</classname>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
</section>
- -->
</chapter>
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample)
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample (rev 0)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample 2010-10-21 06:34:43 UTC (rev 19626)
@@ -0,0 +1 @@
+<rich:calendar value="#{bean.dateTest}" />
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richselectOne-Selection_items.xml_sample (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richselectOne-Selection_items.xml_sample)
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richselectOne-Selection_items.xml_sample (rev 0)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richselectOne-Selection_items.xml_sample 2010-10-21 06:34:43 UTC (rev 19626)
@@ -0,0 +1,4 @@
+<rich:selectOne>
+ <f:selectItem itemLabel="constantOption" itemValue="0">
+ <f:selectItems="#{bean.items}">
+</rich:selectOne>
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample)
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample (rev 0)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample 2010-10-21 06:34:43 UTC (rev 19626)
@@ -0,0 +1,8 @@
+<h:commandLink value="Simple Link" id="link">
+ <rich:toolTip followMouse="true" direction="top-right" mode="ajax" value="#{bean.toolTipContent}"
+ horizontalOffset="5" verticalOffset="5" layout="block">
+ <f:facet name="defaultContent">
+ <f:verbatim>Loading...</f:verbatim>
+ </f:facet>
+ </rich:toolTip>
+</h:commandLink>
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample)
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample (rev 0)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample 2010-10-21 06:34:43 UTC (rev 19626)
@@ -0,0 +1,5 @@
+<rich:panel id="panelId">
+...
+</rich:panel>
+
+<rich:toolTip value="This is a tool-tip." for="panelId"/>
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample)
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample (rev 0)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample 2010-10-21 06:34:43 UTC (rev 19626)
@@ -0,0 +1,3 @@
+<rich:panel>
+ <rich:toolTip value="This is a tool-tip."/>
+</rich:panel>
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample)
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample (rev 0)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample 2010-10-21 06:34:43 UTC (rev 19626)
@@ -0,0 +1,5 @@
+<rich:panel>
+ <rich:toolTip>
+ This is a <b>tool-tip</b>.
+ </rich:toolTip>
+</rich:panel>
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample)
===================================================================
--- modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample (rev 0)
+++ modules/docs/trunk/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample 2010-10-21 06:34:43 UTC (rev 19626)
@@ -0,0 +1,5 @@
+<rich:panel id="panelId" onclick="#{rich:component("tooltipId")}.show(event);" />
+
+<a4j:form>
+ <rich:toolTip id="toolTipId" attached="false" value="This is a tool-tip."/>
+</a4j:form>
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-Pop-up_positioning.png (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-Pop-up_positioning.png)
===================================================================
(Binary files differ)
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-richcalendar.png (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-richcalendar.png)
===================================================================
(Binary files differ)
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richselectOne-richselectOne.png (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richselectOne-richselectOne.png)
===================================================================
(Binary files differ)
Copied: modules/docs/trunk/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richtoolTip-richtoolTip.png (from rev 19624, modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richtoolTip-richtoolTip.png)
===================================================================
(Binary files differ)
Modified: modules/docs/trunk/Migration_Guide/src/main/docbook/en-US/Changes_and_new_features.xml
===================================================================
--- modules/docs/trunk/Migration_Guide/src/main/docbook/en-US/Changes_and_new_features.xml 2010-10-21 06:29:05 UTC (rev 19625)
+++ modules/docs/trunk/Migration_Guide/src/main/docbook/en-US/Changes_and_new_features.xml 2010-10-21 06:34:43 UTC (rev 19626)
@@ -949,7 +949,7 @@
<section id="sect-Migration_Guide-Consolidated_or_renamed_components-richautocomplete">
<title><sgmltag><rich:autocomplete></sgmltag></title>
<para>
- The <sgmltag><rich:autocomplete></sgmltag> component combines and replaces the old <sgmltag><rich:comboBox></sgmltag> and <sgmltag><rich:suggestionBox></sgmltag> components.
+ The <sgmltag><rich:autocomplete></sgmltag> component replaces the old <sgmltag><rich:suggestionBox></sgmltag> component.
</para>
</section>
@@ -993,6 +993,13 @@
The <sgmltag><rich:popupPanel></sgmltag> component replaces the old <sgmltag><rich:modalPanel></sgmltag> component.
</para>
</section>
+
+ <section id="sect-Migration_Guide-Consolidated_or_renamed_components-richselectOne">
+ <title><sgmltag><rich:selectOne></sgmltag></title>
+ <para>
+ The <sgmltag><rich:selectOne></sgmltag> component replaces the old <sgmltag><rich:comboBox></sgmltag> component.
+ </para>
+ </section>
<section id="sect-Migration_Guide-Consolidated_or_renamed_components-richtogglePanel_and_richtogglePanelItem">
<title><sgmltag><rich:togglePanel></sgmltag> and <sgmltag><rich:togglePanelItem></sgmltag></title>
@@ -1037,10 +1044,10 @@
</para>
</section>
- <section id="sect-Migration_Guide-Deprecated_components_and_behaviors-richcomboBox_and_richsuggestionBox">
- <title><sgmltag><rich:comboBox></sgmltag> and <sgmltag><rich:suggestionBox></sgmltag></title>
+ <section id="sect-Migration_Guide-Deprecated_components_and_behaviors-richcomboBox">
+ <title><sgmltag><rich:comboBox></sgmltag></title>
<para>
- The functionality of the old <sgmltag><rich:comboBox></sgmltag> and <sgmltag><rich:suggestionBox></sgmltag> components is now available through the <sgmltag><rich:autocomplete></sgmltag> component.
+ The functionality of the old <sgmltag><rich:comboBox></sgmltag> component is now available through the <sgmltag><rich:selectOne></sgmltag> component.
</para>
</section>
@@ -1079,6 +1086,13 @@
</para>
</section>
+ <section id="sect-Migration_Guide-Deprecated_components_and_behaviors-richsuggestionBox">
+ <title><sgmltag><rich:suggestionBox></sgmltag></title>
+ <para>
+ The functionality of the old <sgmltag><rich:suggestionBox></sgmltag> component is now available through the <sgmltag><rich:autocomplete></sgmltag> component.
+ </para>
+ </section>
+
</section>
</chapter>
13 years, 8 months
JBoss Rich Faces SVN: r19624 - in modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US: extras and 1 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: SeanRogers
Date: 2010-10-21 02:14:48 -0400 (Thu, 21 Oct 2010)
New Revision: 19624
Added:
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richtoolTip-richtoolTip.png
Modified:
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml
Log:
Draft of rich:toolTip complete
Modified: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml 2010-10-21 01:32:01 UTC (rev 19623)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Output_and_messages.xml 2010-10-21 06:14:48 UTC (rev 19624)
@@ -369,10 +369,10 @@
</example>
</section>
- <section id="sect-Component_Reference-richaccordion-Update_mode">
+ <section id="sect-Component_Reference-richprogressBar-Update_mode">
<title>Update mode</title>
<para>
- The mode for updating the progress bar is determined by the <code>mode</code> attribute, which can have one of the following values:
+ The mode for updating the progress bar is determined by the <varname>mode</varname> attribute, which can have one of the following values:
</para>
<variablelist>
<varlistentry>
@@ -393,16 +393,256 @@
</varlistentry>
</variablelist>
</section>
+
+ <section id="sect-Component_Reference-richprogressBar-Reference_data">
+ <title>Reference data</title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <parameter>component-type</parameter>: <classname>org.richfaces.ProgressBar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-class</parameter>: <classname>org.richfaces.component.html.HtmlProgressBar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-family</parameter>: <classname>org.richfaces.component.ProgressBar</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>renderer-type</parameter>: <classname>org.richfaces.renderkit.ProgressBarRenderer</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>tag-class</parameter>: <classname>org.richfaces.taglib.ProgressBarTag</classname>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
</section>
<!-- <rich:toolTip> -->
- <!--
<section id="sect-Component_Reference-Output_and_messages-richtoolTip">
<title><sgmltag><rich:toolTip></sgmltag></title>
<para>
- Incomplete
+ The <sgmltag><rich:toolTip></sgmltag> component provides an informational tool-tip. The tool-tip can be attached to any control and is displayed when hovering the mouse cursor over the control.
</para>
+ <figure id="figu-Component_Reference-richtoolTip-richtoolTip">
+ <title><sgmltag><rich:toolTip></sgmltag></title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/figu-Component_Reference-richtoolTip-richtoolTip.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <para>
+ A <sgmltag><rich:toolTip></sgmltag> component, displayed while hovering the mouse cursor over a button control.
+ </para>
+ </textobject>
+ </mediaobject>
+ </figure>
+
+ <section id="sect-Component_Reference-richtoolTip-Basic_usage">
+ <title>Basic usage</title>
+ <para>
+ For basic usage, define the tool-tip text using the <varname>value</varname> attribute. The <sgmltag><rich:toolTip></sgmltag> component is then automatically attached to the parent element, and is usually shown when the mouse cursor hovers.
+ </para>
+ <para>
+ Alternatively, the content of the tool-tip can be defined inside the <sgmltag><rich:toolTip></sgmltag> tags, and the <varname>value</varname> attribute is not used. This allows HTML tags to be used to define the content, and provides for rich content such as images, links, buttons, and other RichFaces components.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Defining_tool-tip_content">
+ <title>Defining tool-tip content</title>
+ <variablelist>
+ <varlistentry>
+ <term>Basic content</term>
+ <listitem>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Rich content</term>
+ <listitem>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </example>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Attaching_the_tool-tip_to_another_component">
+ <title>Attaching the tool-tip to another component</title>
+ <para>
+ If not otherwise specified, the tool-tip is attached to the parent element in which it is defined. The <varname>for</varname> attribute is used to attach the tool-tip to another component, pointing to the target component's <varname>id</varname> identifier. This allows the <sgmltag><rich:toolTip></sgmltag> component to be specified outside the target element. This approach is demonstrated in <xref linkend="exam-Component_Reference-richtoolTip-Attaching_the_tool-tip" />.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Attaching_the_tool-tip">
+ <title>Attaching the tool-tip</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ The <sgmltag><rich:toolTip></sgmltag> component can alternatively be left unattached, and is instead invoked through an event handler on the target component. To leave the <sgmltag><rich:toolTip></sgmltag> component unattached, set <code>attached="false"</code>, and define the event handler to trigger the tool-tip on the target component. This approach is demonstrated in <xref linkend="exam-Component_Reference-richtoolTip-Unattached_tool-tips" />. When leaving the <sgmltag><rich:toolTip></sgmltag> component unattached, ensure it has an <varname>id</varname> identifier defined. If the <sgmltag><rich:toolTip></sgmltag> component is nested inside the target element, it must be the last child. If it is defined outside the target element, it must be nested in an <sgmltag><a4j:form></sgmltag> component.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Unattached_tool-tips">
+ <title>Unattached tool-tips</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Appearance">
+ <title>Appearance</title>
+ <para>
+ By default, the <sgmltag><rich:toolTip></sgmltag> component is positioned intelligently based on the position of the mouse cursor. Use the <varname>direction</varname> attribute to specify a corner of the target component at which to display the tool-tip instead. Possible values include <literal>top-left</literal>, <literal>top-right</literal>, <literal>bottom-left</literal>, and <literal>bottom-right</literal>. Use the <varname>horizontalOffset</varname> and <varname>verticalOffset</varname> attributes to specify the horizontal offset and vertical offset at which to display the tool-tip.
+ </para>
+ <para>
+ Use the <varname>hideEvent</varname> attribute to specify when the tool-tip is hidden. The default value is <literal>none</literal>, so the tool-tip remains shown. However, it can be linked to an event on the target component, such as the <literal>mouseout</literal> event.
+ </para>
+ <para>
+ Set <code>followMouse="true"</code> to cause the tool-tip to follow the user's mouse movements.
+ </para>
+ <para>
+ Advanced appearance features are demonstrated in <xref linkend="exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage" />.
+ </para>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Update_mode">
+ <title>Update mode</title>
+ <para>
+ The mode for updating the tool-tip is determined by the <varname>mode</varname> attribute, which can have one of the following values:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>ajax</literal></term>
+ <listitem>
+ <para>
+ The tool-tip content is requested from the server with every activation.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>client</literal></term>
+ <listitem>
+ <para>
+ The tool-tip content is rendered once on the server. An external submit causes the content to re-render.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+ When using <code>mode="ajax"</code>, define the <literal>defaultContent</literal> facet. The tool-tip displays the content of the <literal>defaultContent</literal> facet while loading the actual content from the server.
+ </para>
+ <example id="exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage">
+ <title>Advanced tool-tip usage</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-richtoolTip_client-side_events">
+ <title><sgmltag><rich:toolTip></sgmltag> client-side events</title>
+ <para>
+ The <sgmltag><rich:toolTip></sgmltag> component supports the following client-side events:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>onclick</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is clicked with the mouse.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ondblclick</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is double-clicked with the mouse.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onmouseout</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the mouse cursor leaves the tool-tip.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onmousemove</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the mouse cursor moves over the tool-tip.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onmouseover</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the mouse cursor hovers over the tool-tip.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onshow</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is shown.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>oncomplete</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is completed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>onhide</literal></term>
+ <listitem>
+ <para>
+ This event is activated when the tool-tip is hidden.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="sect-Component_Reference-richtoolTip-Reference_data">
+ <title>Reference data</title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <parameter>component-type</parameter>: <classname>org.richfaces.component.toolTip</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-class</parameter>: <classname>org.richfaces.component.html.HtmlToolTip</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>component-family</parameter>: <classname>org.richfaces.component.toolTip</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>renderer-type</parameter>: <classname>org.richfaces.renderkit.html.toolTipRenderer</classname>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <parameter>tag-class</parameter>: <classname>org.richfaces.taglib.HtmlToolTipTag</classname>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
</section>
- -->
</chapter>
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample (rev 0)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Advanced_tool-tip_usage.xml_sample 2010-10-21 06:14:48 UTC (rev 19624)
@@ -0,0 +1,8 @@
+<h:commandLink value="Simple Link" id="link">
+ <rich:toolTip followMouse="true" direction="top-right" mode="ajax" value="#{bean.toolTipContent}"
+ horizontalOffset="5" verticalOffset="5" layout="block">
+ <f:facet name="defaultContent">
+ <f:verbatim>Loading...</f:verbatim>
+ </f:facet>
+ </rich:toolTip>
+</h:commandLink>
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample (rev 0)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Attaching_the_tool-tip.xml_sample 2010-10-21 06:14:48 UTC (rev 19624)
@@ -0,0 +1,5 @@
+<rich:panel id="panelId">
+...
+</rich:panel>
+
+<rich:toolTip value="This is a tool-tip." for="panelId"/>
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample (rev 0)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-0.xml_sample 2010-10-21 06:14:48 UTC (rev 19624)
@@ -0,0 +1,3 @@
+<rich:panel>
+ <rich:toolTip value="This is a tool-tip."/>
+</rich:panel>
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample (rev 0)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Defining_tool-tip_content-1.xml_sample 2010-10-21 06:14:48 UTC (rev 19624)
@@ -0,0 +1,5 @@
+<rich:panel>
+ <rich:toolTip>
+ This is a <b>tool-tip</b>.
+ </rich:toolTip>
+</rich:panel>
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample (rev 0)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richtoolTip-Unattached_tool-tips.xml_sample 2010-10-21 06:14:48 UTC (rev 19624)
@@ -0,0 +1,5 @@
+<rich:panel id="panelId" onclick="#{rich:component("tooltipId")}.show(event);" />
+
+<a4j:form>
+ <rich:toolTip id="toolTipId" attached="false" value="This is a tool-tip."/>
+</a4j:form>
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richtoolTip-richtoolTip.png
===================================================================
(Binary files differ)
Property changes on: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richtoolTip-richtoolTip.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
13 years, 8 months
JBoss Rich Faces SVN: r19623 - in modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US: extras and 1 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: SeanRogers
Date: 2010-10-20 21:32:01 -0400 (Wed, 20 Oct 2010)
New Revision: 19623
Added:
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-Pop-up_positioning.png
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-richcalendar.png
Modified:
modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml
Log:
Draft of rich:calendar complete
Modified: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml 2010-10-21 00:31:11 UTC (rev 19622)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/chap-Component_Reference-Rich_inputs.xml 2010-10-21 01:32:01 UTC (rev 19623)
@@ -21,16 +21,37 @@
The <sgmltag><rich:calendar></sgmltag> component allows the user to enter a date and time through an in-line or pop-up calendar. The pop-up calendar can navigate through months and years, and its look and feel can be highly customized.
</para>
+ <figure id="figu-Component_Reference-richcalendar-richcalendar">
+ <title><sgmltag><rich:calendar></sgmltag></title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/figu-Component_Reference-richcalendar-richcalendar.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <para>
+ An expanded <sgmltag><rich:calendar></sgmltag> component, displaying the calendar month of December, 2010.
+ </para>
+ </textobject>
+ </mediaobject>
+ </figure>
+
<section id="sect-Component_Reference-richcalendar-Basic_usage">
<title>Basic usage</title>
<para>
- The <sgmltag><rich:calendar></sgmltag> component supports two different ways of loading data through defining the <varname>mode</varname> attribute. When not specified, the component uses <literal>client</literal> mode, which loads an initial portion of data within a set date range. The range can be defined by using the <varname>preloadDateRangeBegin</varname> and <varname>preloadDateRangeEnd</varname> attributes. Additional data requests are not sent.
+ Basic usage of the <sgmltag><rich:calendar></sgmltag> component requires only the <varname>value</varname> attribute, which holds the currently selected date. <xref linkend="exam-Component_Reference-richcalendar-Basic_usage" /> shows a basic declaration, with the value pointing to a data model.
</para>
+ <example id="exam-Component_Reference-richcalendar-Basic_usage">
+ <title>Basic usage</title>
+ <programlisting language="XML" role="XML"><xi:include parse="text" href="extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
</section>
<section id="sect-Component_Reference-richcalendar-Using_a_data_model">
<title>Using a data model</title>
<para>
+ The <sgmltag><rich:calendar></sgmltag> component supports two different ways of loading data through defining the <varname>mode</varname> attribute. When not specified, the component uses <literal>client</literal> mode, which loads an initial portion of data within a set date range. The range can be defined by using the <varname>preloadDateRangeBegin</varname> and <varname>preloadDateRangeEnd</varname> attributes. Additional data requests are not sent.
+ </para>
+ <para>
Alternatively, with <code>mode="ajax"</code> the <sgmltag><rich:calendar></sgmltag> requests portions of data for rendering from a special data model. The data model can be defined through the <varname>dataModel</varname> attribute, which points to an object that implements the <classname>CalendarDataModel</classname> interface. If the <varname>dataModel</varname> attribute is not defined or has a value of <literal>null</literal>, the <literal>ajax</literal> mode functions the same as the <literal>client</literal> mode.
</para>
</section>
@@ -44,8 +65,24 @@
To change the appearance of the display button from the standard calendar icon, use the <varname>buttonIcon</varname> and <varname>buttonIconDisabled</varname> attributes to replace the icon with a specified file. Alternatively, use the <varname>buttonLabel</varname> attribute to display text on the button without an icon. If <varname>buttonLabel</varname> is specified then both the <varname>buttonIcon</varname> and <varname>buttonIconDisabled</varname> attributes are ignored. To hide the text field box, set <code>showInput="false"</code>.
</para>
<para>
- To change the default position at which the pop-up calendar is shown relative to the text field and button, use the <varname>jointPoint</varname> and <varname>direction</varname> attributes. The <varname>jointPoint</varname> attribute refers to the corner of the text field and button with which the calendar will be aligned and the <varname>direction</varname> specifies which direction the pop-up calendar will span relative to the joint point. The default settings are <code>jointPoint="bottom-left"</code> and <code>direction="bottom-right"</code>, causing the pop-up calendar to align with the bottom-left corner of the text field and span to the bottom-right, underneath the text field and button. The diagram shows the joint points and directions that can be used. Alternatively, set both <varname>jointPoint</varname> and <varname>direction</varname> attributes to <literal>auto</literal> to allow smart pop-up positioning.
+ To change the default position at which the pop-up calendar is shown relative to the text field and button, use the <varname>jointPoint</varname> and <varname>direction</varname> attributes. The <varname>jointPoint</varname> attribute refers to the corner of the text field and button with which the calendar will be aligned and the <varname>direction</varname> specifies which direction the pop-up calendar will span relative to the joint point. The default settings are <code>jointPoint="bottom-left"</code> and <code>direction="bottom-right"</code>, causing the pop-up calendar to align with the bottom-left corner of the text field and span to the bottom-right, underneath the text field and button. The diagram shows the joint points and directions that can be used. Alternatively, set both <varname>jointPoint</varname> and <varname>direction</varname> attributes to <literal>auto</literal> to allow smart pop-up positioning. <xref linkend="figu-Component_Reference-richcalendar!
-Pop-up_positioning" /> shows the different possible settings for the <varname>jointPoint</varname> and <varname>direction</varname> attributes.
</para>
+ <figure id="figu-Component_Reference-richcalendar-Pop-up_positioning">
+ <title>Pop-up positioning</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/figu-Component_Reference-richcalendar-Pop-up_positioning.png" format="PNG" />
+ </imageobject>
+ <textobject>
+ <para>
+ Pop-up positioning is determined using the <varname>jointPoint</varname> and <varname>direction</varname> attributes.
+ </para>
+ </textobject>
+ </mediaobject>
+ <para>
+ Pop-up positioning is determined using the <varname>jointPoint</varname> and <varname>direction</varname> attributes. Values for the <varname>jointPoint</varname> attribute are shown in red, while values for the <varname>direction</varname> attribute are shown in black.
+ </para>
+ </figure>
<para>
The calendar features a <guibutton>Today</guibutton> button for locating today's date on the calendar. This can be set to three different values using the <varname>todayControlMode</varname> attribute:
</para>
@@ -69,6 +106,12 @@
<para>
To make the entire calendar read-only, set <code>readonly="true"</code>. This allows months and years to be browsed through with the arrow controls, but dates and times cannot be selected.
</para>
+ <!-- TODO not in M4 -->
+ <!--
+ <para>
+ The styling and appearance of the calendar can be fully customized using facets.
+ </para>
+ -->
</section>
<section id="sect-Component_Reference-richcalendar-Time_of_day">
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample
===================================================================
--- modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample (rev 0)
+++ modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/extras/exam-Component_Reference-richcalendar-Basic_usage.xml_sample 2010-10-21 01:32:01 UTC (rev 19623)
@@ -0,0 +1 @@
+<rich:calendar value="#{bean.dateTest}" />
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-Pop-up_positioning.png
===================================================================
(Binary files differ)
Property changes on: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-Pop-up_positioning.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-richcalendar.png
===================================================================
(Binary files differ)
Property changes on: modules/docs/branches/m4/Component_Reference/src/main/docbook/en-US/images/figu-Component_Reference-richcalendar-richcalendar.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
13 years, 8 months
JBoss Rich Faces SVN: r19622 - in branches/RF-7817: core/impl/src/main/java/org/richfaces/application and 13 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2010-10-20 20:31:11 -0400 (Wed, 20 Oct 2010)
New Revision: 19622
Added:
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/MessageException.java
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContext.java
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContextFactory.java
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/SessionFactory.java
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicListener.java
branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DummyPushContextFactory.java
branches/RF-7817/push-redesign-app/src/main/webapp/chat.xhtml
branches/RF-7817/push-redesign-app/src/main/webapp/index.jsp
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AbstractTopic.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmosphereHandlerProvider.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/ConsumingCollection.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/PushResource.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextFactoryImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicsContextImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushFilter.java
branches/RF-7817/push-redesign/src/main/resources/META-INF/services/
branches/RF-7817/push-redesign/src/main/resources/META-INF/services/org.richfaces.application.push.PushContextFactory
Removed:
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Message.java
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PublisherContext.java
branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicImpl.java
branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicsContextImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PublisherContextImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushServlet.java
Modified:
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Request.java
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Topic.java
branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicsContext.java
branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DefaultModule.java
branches/RF-7817/push-redesign-app/pom.xml
branches/RF-7817/push-redesign-app/src/main/java/demo/ChatBean.java
branches/RF-7817/push-redesign-app/src/main/java/demo/TopicsInitializer.java
branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/faces-config.xml
branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/web.xml
branches/RF-7817/push-redesign-app/src/main/webapp/index.xhtml
branches/RF-7817/push-redesign/pom.xml
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmospherePushHandler.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/RequestImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/SessionManagerImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/MessagingContext.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushHandlerImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/SessionImpl.java
branches/RF-7817/push-redesign/src/main/java/org/richfaces/renderkit/PushRendererBase.java
branches/RF-7817/push-redesign/src/main/resources/META-INF/resources/org.richfaces/push.js
Log:
https://jira.jboss.org/browse/RF-7817
Deleted: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Message.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Message.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Message.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -1,88 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.richfaces.application.push;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Nick Belaevski
- *
- */
-public class Message implements Serializable {
-
- private static final long serialVersionUID = -2241242510684986230L;
-
- private final TopicKey topicKey;
-
- private Map<String, Object> attributes = null;
-
- private Object data;
-
- public Message(TopicKey topicKey) {
- this.topicKey = topicKey;
- }
-
- public Object getData() {
- return data;
- }
-
- public void setData(Object data) {
- this.data = data;
- }
-
- public void addAttribute(String key, Object value) {
- if (attributes == null) {
- attributes = new HashMap<String, Object>();
- }
-
- attributes.put(key, value);
- }
-
- public void removeAttribute(String key) {
- if (attributes != null) {
- attributes.remove(key);
- }
- }
-
- public Map<String, Object> getAttributes() {
- if (attributes == null) {
- attributes = new HashMap<String, Object>();
- }
-
- return attributes;
- }
-
- public Object getAttribute(String key) {
- if (attributes != null) {
- return attributes.get(key);
- }
-
- return null;
- }
-
- public TopicKey getTopicKey() {
- return topicKey;
- }
-
-}
Added: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/MessageException.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/MessageException.java (rev 0)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/MessageException.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class MessageException extends Exception {
+
+ private static final long serialVersionUID = -8684363449647232385L;
+
+ public MessageException() {
+ super();
+ }
+
+ public MessageException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public MessageException(String message) {
+ super(message);
+ }
+
+ public MessageException(Throwable cause) {
+ super(cause);
+ }
+
+}
Deleted: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PublisherContext.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PublisherContext.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PublisherContext.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -1,39 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.richfaces.application.push;
-
-
-
-/**
- * @author Nick Belaevski
- *
- */
-public interface PublisherContext {
-
- public static final String ATTRIBUTE_NAME = "__publisherContxt";
-
- //TODO - return Future?
- //TODO - use topic key?
- //TODO - priority?
- public void publish(TopicKey topicKey, Object data);
-
-}
Added: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContext.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContext.java (rev 0)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContext.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface PushContext {
+
+ public static final String INSTANCE_KEY_NAME = PushContext.class.getName();
+
+ public TopicsContext getTopicsContext();
+
+ public SessionFactory getSessionFactory();
+
+ public void init(FacesContext facesContext);
+
+ public void destroy();
+
+}
Added: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContextFactory.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContextFactory.java (rev 0)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/PushContextFactory.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface PushContextFactory {
+
+ public PushContext getPushContext();
+
+}
Modified: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Request.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Request.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Request.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -34,7 +34,7 @@
public void flushMessages() throws IOException;
- public void postMessage(Message message);
+ public void postMessage(TopicKey topicKey, String serializedMessage);
//TODO suspend with timeout?
public void suspend() throws IOException;
Added: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/SessionFactory.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/SessionFactory.java (rev 0)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/SessionFactory.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface SessionFactory {
+
+ public Session createSession(String key);
+
+}
Modified: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Topic.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Topic.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/Topic.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -21,6 +21,7 @@
*/
package org.richfaces.application.push;
+
/**
* @author Nick Belaevski
*
@@ -29,8 +30,18 @@
public TopicKey getKey();
- public MessageDataSerializer getMessageSerializer();
+ public MessageDataSerializer getMessageDataSerializer();
- public void setMessageSerializer(MessageDataSerializer serializer);
+ public void setMessageDataSerializer(MessageDataSerializer serializer);
+ public void addTopicListener(TopicListener topicListener);
+
+ public void removeTopicListener(TopicListener topicListener);
+
+ public void notifySubscription(Session session, TopicKey topicKey) throws AbortSubscriptionException;
+
+ public void notifyUnsubscription(Session session, TopicKey topicKey);
+
+ public void publish(Object messageData) throws MessageException;
+
}
\ No newline at end of file
Added: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicListener.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicListener.java (rev 0)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicListener.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface TopicListener {
+
+ public void onSessionSubscribed(Session session, TopicKey topicKey) throws AbortSubscriptionException;
+
+ public void onSessionUnsubscribed(Session session, TopicKey topicKey);
+
+}
Modified: branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicsContext.java
===================================================================
--- branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicsContext.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/api/src/main/java/org/richfaces/application/push/TopicsContext.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -21,17 +21,57 @@
*/
package org.richfaces.application.push;
+import java.text.MessageFormat;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.richfaces.application.ServiceTracker;
+
/**
* @author Nick Belaevski
*
*/
//TODO annotations for declarative topics registration
-public interface TopicsContext {
+public abstract class TopicsContext {
- public Topic getOrCreateTopic(TopicKey key);
+ private ConcurrentMap<TopicKey, Topic> topics = new ConcurrentHashMap<TopicKey, Topic>();
- public Topic getTopic(TopicKey key);
+ protected abstract Topic createTopic(TopicKey key);
- public void removeTopic(TopicKey key);
+ public Topic getOrCreateTopic(TopicKey key) {
+ Topic result = topics.get(key);
+
+ if (result == null) {
+ Topic newTopic = createTopic(key);
+ result = topics.putIfAbsent(key, newTopic);
+ if (result == null) {
+ result = newTopic;
+ }
+ }
+
+ return result;
+ }
+
+ public Topic getTopic(TopicKey key) {
+ return topics.get(key);
+ }
+
+ public void removeTopic(TopicKey key) {
+ topics.remove(key);
+ }
+
+ public void publish(TopicKey key, Object data) throws MessageException {
+ Topic topic = getTopic(key);
+
+ if (topic == null) {
+ throw new MessageException(MessageFormat.format("Topic {0} not found", key.getTopicName()));
+ }
+
+ topic.publish(data);
+ }
+
+ public static TopicsContext lookup() {
+ return ServiceTracker.getService(PushContextFactory.class).getPushContext().getTopicsContext();
+ }
}
Modified: branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DefaultModule.java
===================================================================
--- branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DefaultModule.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DefaultModule.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -2,8 +2,7 @@
import org.richfaces.application.configuration.ConfigurationService;
import org.richfaces.application.configuration.ConfigurationServiceImpl;
-import org.richfaces.application.push.TopicsContext;
-import org.richfaces.application.push.impl.TopicsContextImpl;
+import org.richfaces.application.push.PushContextFactory;
import org.richfaces.cache.Cache;
import org.richfaces.l10n.BundleLoader;
import org.richfaces.renderkit.AjaxDataSerializer;
@@ -27,7 +26,9 @@
factory.setInstance(DependencyInjector.class, new DependencyInjectionServiceImpl());
factory.setInstance(MessageFactory.class, new MessageFactoryImpl(new BundleLoader()));
factory.setInstance(ResourceLibraryFactory.class, new ResourceLibraryFactoryImpl());
- factory.setInstance(TopicsContext.class, new TopicsContextImpl());
+
+ //TODO add default implementation class name
+ factory.setInstance(PushContextFactory.class, ServiceLoader.loadService(PushContextFactory.class, DummyPushContextFactory.class));
}
}
Added: branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DummyPushContextFactory.java
===================================================================
--- branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DummyPushContextFactory.java (rev 0)
+++ branches/RF-7817/core/impl/src/main/java/org/richfaces/application/DummyPushContextFactory.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application;
+
+import org.richfaces.application.push.PushContext;
+import org.richfaces.application.push.PushContextFactory;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+//TODO - remove after push-redesign project merge
+public class DummyPushContextFactory implements PushContextFactory {
+
+ public PushContext getPushContext() {
+ throw new UnsupportedOperationException();
+ }
+
+}
Deleted: branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicImpl.java
===================================================================
--- branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicImpl.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -1,55 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.richfaces.application.push.impl;
-
-import org.richfaces.application.push.MessageDataSerializer;
-import org.richfaces.application.push.Topic;
-import org.richfaces.application.push.TopicKey;
-
-/**
- * @author Nick Belaevski
- *
- */
-public class TopicImpl implements Topic {
-
- private TopicKey key;
-
- private volatile MessageDataSerializer serializer;
-
- public TopicImpl(TopicKey key) {
- super();
- this.key = key;
- }
-
- public MessageDataSerializer getMessageSerializer() {
- return serializer;
- }
-
- public void setMessageSerializer(MessageDataSerializer serializer) {
- this.serializer = serializer;
- }
-
- public TopicKey getKey() {
- return key;
- }
-
-}
Deleted: branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicsContextImpl.java
===================================================================
--- branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicsContextImpl.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicsContextImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.richfaces.application.push.impl;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.richfaces.application.push.Topic;
-import org.richfaces.application.push.TopicKey;
-import org.richfaces.application.push.TopicsContext;
-
-/**
- * @author Nick Belaevski
- *
- */
-public class TopicsContextImpl implements TopicsContext {
-
- private ConcurrentMap<TopicKey, Topic> topics = new ConcurrentHashMap<TopicKey, Topic>();
-
- public Topic getOrCreateTopic(TopicKey key) {
- Topic result = topics.get(key);
-
- if (result == null) {
- Topic newTopic = new TopicImpl(key);
- result = topics.putIfAbsent(key, newTopic);
- if (result == null) {
- result = newTopic;
- }
- }
-
- return result;
- }
-
- public Topic getTopic(TopicKey key) {
- return topics.get(key);
- }
-
- public void removeTopic(TopicKey key) {
- topics.remove(key);
- }
-
-}
Modified: branches/RF-7817/push-redesign/pom.xml
===================================================================
--- branches/RF-7817/push-redesign/pom.xml 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/pom.xml 2010-10-21 00:31:11 UTC (rev 19622)
@@ -40,11 +40,12 @@
</plugin>
</plugins>
</build>
+
<dependencies>
<dependency>
- <groupId>javax.servlet</groupId>
+ <groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
- <version>3.0-alpha-1</version>
+ <version>3.0.20100224</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -73,7 +74,7 @@
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
- <version>0.6.2</version>
+ <version>0.6.3</version>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
Copied: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AbstractTopic.java (from rev 19577, branches/RF-7817/core/impl/src/main/java/org/richfaces/application/push/impl/TopicImpl.java)
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AbstractTopic.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AbstractTopic.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,116 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl;
+
+import java.util.List;
+import java.util.ListIterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.richfaces.application.push.AbortSubscriptionException;
+import org.richfaces.application.push.MessageDataSerializer;
+import org.richfaces.application.push.MessageException;
+import org.richfaces.application.push.Session;
+import org.richfaces.application.push.Topic;
+import org.richfaces.application.push.TopicKey;
+import org.richfaces.application.push.TopicListener;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public abstract class AbstractTopic implements Topic {
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ private TopicKey key;
+
+ private volatile MessageDataSerializer serializer;
+
+ private List<TopicListener> listeners = new CopyOnWriteArrayList<TopicListener>();
+
+ public AbstractTopic(TopicKey key) {
+ super();
+ this.key = key;
+ }
+
+ public MessageDataSerializer getMessageDataSerializer() {
+ if (serializer == null) {
+ return DefaultMessageDataSerializer.instance();
+ }
+
+ return serializer;
+ }
+
+ public void setMessageDataSerializer(MessageDataSerializer serializer) {
+ this.serializer = serializer;
+ }
+
+ public TopicKey getKey() {
+ return key;
+ }
+
+ public void addTopicListener(TopicListener topicListener) {
+ listeners.add(topicListener);
+ }
+
+ public void removeTopicListener(TopicListener topicListener) {
+ listeners.remove(topicListener);
+ }
+
+
+ public void notifySubscription(Session session, TopicKey topicKey) throws AbortSubscriptionException {
+ ListIterator<TopicListener> itr = listeners.listIterator();
+ while (itr.hasNext()) {
+ TopicListener listener = itr.next();
+ try {
+ listener.onSessionSubscribed(session, topicKey);
+ } catch (AbortSubscriptionException e) {
+ while (itr.hasPrevious()) {
+ try {
+ itr.previous().onSessionUnsubscribed(session, topicKey);
+ } catch (Exception e1) {
+ LOGGER.error(e1.getMessage(), e1);
+ }
+ }
+
+ throw e;
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ public void notifyUnsubscription(Session session, TopicKey topicKey) {
+ for (TopicListener listener : listeners) {
+ try {
+ listener.onSessionUnsubscribed(session, topicKey);
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ public abstract void publish(Object messageData) throws MessageException;
+
+}
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmosphereHandlerProvider.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmosphereHandlerProvider.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmosphereHandlerProvider.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.atmosphere.cpr.AtmosphereHandler;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface AtmosphereHandlerProvider {
+
+ public AtmosphereHandler<HttpServletRequest, HttpServletResponse> getHandler();
+
+}
Modified: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmospherePushHandler.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmospherePushHandler.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/AtmospherePushHandler.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -22,7 +22,6 @@
package org.richfaces.application.push.impl;
import java.io.IOException;
-import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
@@ -38,7 +37,6 @@
import org.richfaces.application.push.Request;
import org.richfaces.application.push.Session;
import org.richfaces.application.push.SessionManager;
-import org.richfaces.application.push.TopicKey;
/**
* @author Nick Belaevski
@@ -110,26 +108,6 @@
//do nothing
}
- public Session doConnect(String[] topicNames) {
- Session pushSession = createSession(UUID.randomUUID().toString());
- sessionManager.putPushSession(pushSession);
-
- for (int i = 0; i < topicNames.length; i++) {
- TopicKey topicKey = new TopicKey(topicNames[i]);
-
- try {
- pushSession.subscribe(topicKey);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- return pushSession;
- }
-
- protected abstract Session createSession(String key);
-
protected Request createRequest(AtmosphereResource<HttpServletRequest, HttpServletResponse> resource, Session session) {
return new RequestImpl(resource, session, worker);
}
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/ConsumingCollection.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/ConsumingCollection.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/ConsumingCollection.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,64 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl;
+
+import java.util.AbstractCollection;
+import java.util.Iterator;
+import java.util.Queue;
+
+import com.google.common.collect.AbstractIterator;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class ConsumingCollection<T> extends AbstractCollection<T> {
+
+ private final class ConsumingIterator extends AbstractIterator<T> {
+ @Override
+ protected T computeNext() {
+ T next = queue.poll();
+ if (next == null) {
+ endOfData();
+ }
+ return next;
+ }
+ }
+
+ private Queue<T> queue;
+
+ public ConsumingCollection(Queue<T> queue) {
+ super();
+ this.queue = queue;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return new ConsumingIterator();
+ }
+
+ @Override
+ public int size() {
+ return queue.size();
+ }
+
+}
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/PushResource.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/PushResource.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/PushResource.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.faces.context.FacesContext;
+
+import org.richfaces.application.ServiceTracker;
+import org.richfaces.application.push.PushContext;
+import org.richfaces.application.push.PushContextFactory;
+import org.richfaces.application.push.Session;
+import org.richfaces.application.push.TopicKey;
+import org.richfaces.resource.DynamicResource;
+import org.richfaces.resource.UserResource;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+@DynamicResource
+public class PushResource implements UserResource {
+
+ private static final String PUSH_TOPIC_PARAM = "pushTopic";
+
+ public Map<String, String> getResponseHeaders() {
+ return null;
+ }
+
+ public Date getLastModified() {
+ return null;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ PushContextFactory pushContextFactory = ServiceTracker.getService(PushContextFactory.class);
+ PushContext pushContext = pushContextFactory.getPushContext();
+
+ Session session = pushContext.getSessionFactory().createSession(UUID.randomUUID().toString());
+
+ String[] topicNames = facesContext.getExternalContext().getRequestParameterValuesMap().get(PUSH_TOPIC_PARAM);
+
+ if (topicNames == null) {
+ throw new IllegalArgumentException();
+ }
+
+ for (int i = 0; i < topicNames.length; i++) {
+ TopicKey topicKey = new TopicKey(topicNames[i]);
+
+ try {
+ session.subscribe(topicKey);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return new ByteArrayInputStream(session.getId().getBytes("UTF-8"));
+ }
+
+ public String getContentType() {
+ return "text/plain";
+ }
+
+ public int getContentLength() {
+ return -1;
+ }
+
+}
Modified: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/RequestImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/RequestImpl.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/RequestImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -36,16 +36,17 @@
import javax.servlet.http.HttpServletResponse;
import org.ajax4jsf.javascript.JSLiteral;
+import org.ajax4jsf.javascript.ScriptString;
import org.ajax4jsf.javascript.ScriptUtils;
import org.atmosphere.cpr.AtmosphereEventLifecycle;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.AtmosphereResourceEventListener;
import org.atmosphere.websocket.WebSocketSupport;
-import org.richfaces.application.push.Message;
import org.richfaces.application.push.Request;
import org.richfaces.application.push.RequestLifecycleListener;
import org.richfaces.application.push.Session;
+import org.richfaces.application.push.TopicKey;
/**
* @author Nick Belaevski
@@ -53,6 +54,36 @@
*/
public class RequestImpl implements Request {
+ private static final String TOPIC_KEY = "topic";
+
+ private static final String DATA_KEY = "data";
+
+ private static final class Message implements ScriptString {
+
+ private TopicKey topicKey;
+
+ private String serializedData;
+
+ public Message(TopicKey topicKey, String serializedData) {
+ super();
+ this.topicKey = topicKey;
+ this.serializedData = serializedData;
+ }
+
+ public String toScript() {
+ Map<String,Object> map = new HashMap<String, Object>(2);
+
+ map.put(TOPIC_KEY, topicKey.getTopicName());
+ map.put(DATA_KEY, new JSLiteral(serializedData));
+
+ return ScriptUtils.toScript(map);
+ }
+
+ public void appendScript(StringBuffer functionString) {
+ functionString.append(toScript());
+ }
+ }
+
private static final class FlushMessagesTask implements Runnable {
private Request request;
@@ -131,38 +162,7 @@
}
private String serializeMessages() {
- StringBuilder sb = new StringBuilder();
-
- sb.append("[");
-
- boolean isFirstElement = true;
-
- while (true) {
- Message message = messagesQueue.poll();
- if (message == null) {
- break;
- }
-
- if (isFirstElement) {
- isFirstElement = false;
- } else {
- sb.append(", ");
- }
-
- //TODO - use MessageSerializer
- String messageDataString = DefaultMessageDataSerializer.instance().serialize(message.getData());
-
- Map<String, Object> map = new HashMap<String, Object>(2);
-
- map.put("data", new JSLiteral(messageDataString));
- map.put("topic", message.getTopicKey().getTopicName());
-
- sb.append(ScriptUtils.toScript(map));
- }
-
- sb.append("]");
-
- return sb.toString();
+ return ScriptUtils.toScript(new ConsumingCollection<Message>(messagesQueue));
}
public void flushMessages() throws IOException {
@@ -184,8 +184,8 @@
}
}
- public void postMessage(Message message) {
- messagesQueue.add(message);
+ public void postMessage(TopicKey topicKey, String serializedMessage) {
+ messagesQueue.add(new Message(topicKey, serializedMessage));
submitToWorker();
}
Modified: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/SessionManagerImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/SessionManagerImpl.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/SessionManagerImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -21,6 +21,7 @@
*/
package org.richfaces.application.push.impl;
+import java.util.Iterator;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
@@ -30,6 +31,8 @@
import org.richfaces.application.push.Session;
import org.richfaces.application.push.SessionListener;
import org.richfaces.application.push.SessionManager;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
import com.google.common.collect.MapMaker;
@@ -39,6 +42,8 @@
*/
public class SessionManagerImpl implements SessionManager {
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
//TODO - implement queue around sessions properly
private final class DelayedSessionHolder implements Delayed {
@@ -109,8 +114,7 @@
sessionMap.remove(sessionHolder.getSession().getId());
sessionHolder.getSession().destroy();
} catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ LOGGER.error(e.getMessage(), e);
}
}
@@ -156,6 +160,16 @@
public void destroy() {
//TODO notify all session
expirationQueue.clear();
+
+ while (!sessionMap.isEmpty()) {
+ for (Iterator<Session> sessionsItr = sessionMap.values().iterator(); sessionsItr.hasNext(); ) {
+ Session session = sessionsItr.next();
+ sessionsItr.remove();
+
+ session.destroy();
+ }
+ }
+
sessionMap.clear();
}
Modified: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/MessagingContext.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/MessagingContext.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/MessagingContext.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -21,8 +21,10 @@
*/
package org.richfaces.application.push.impl.jms;
+import java.util.Map;
import java.util.UUID;
+import javax.faces.context.FacesContext;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
@@ -31,6 +33,7 @@
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
+import javax.servlet.ServletContext;
import org.richfaces.application.push.TopicKey;
@@ -40,6 +43,8 @@
*/
public class MessagingContext {
+ private static final String SHARED_INSTANCE_KEY = MessagingContext.class.getName();
+
private final InitialContext initialContext;
private final Name connectionFactoryName;
@@ -119,4 +124,13 @@
public String getApplicationName() {
return applicationName;
}
+
+ public void shareInstance(FacesContext facesContext) {
+ Map<String, Object> applicationMap = facesContext.getExternalContext().getApplicationMap();
+ applicationMap.put(SHARED_INSTANCE_KEY, this);
+ }
+
+ public static MessagingContext getSharedInstance(ServletContext servletContext) {
+ return (MessagingContext) servletContext.getAttribute(SHARED_INSTANCE_KEY);
+ }
}
Deleted: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PublisherContextImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PublisherContextImpl.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PublisherContextImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -1,75 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.richfaces.application.push.impl.jms;
-
-import java.io.Serializable;
-
-import javax.jms.JMSException;
-import javax.jms.MessageProducer;
-import javax.jms.ObjectMessage;
-import javax.jms.Session;
-import javax.naming.NamingException;
-
-import org.richfaces.application.push.PublisherContext;
-import org.richfaces.application.push.TopicKey;
-
-/**
- * @author Nick Belaevski
- *
- */
-public class PublisherContextImpl implements PublisherContext {
-
- private MessagingContext messagingContext;
-
- public PublisherContextImpl(MessagingContext messagingContext) {
- super();
- this.messagingContext = messagingContext;
- }
-
- public void publish(TopicKey topicKey, Object data) {
- Session session = null;
- try {
- session = messagingContext.createSession();
- MessageProducer producer = session.createProducer(messagingContext.lookup(topicKey));
-
- ObjectMessage objectMessage = session.createObjectMessage();
- objectMessage.setObject((Serializable) data);
-
- producer.send(objectMessage);
- } catch (JMSException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NamingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- if (session != null) {
- try {
- session.close();
- } catch (JMSException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
-}
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextFactoryImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextFactoryImpl.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextFactoryImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,57 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl.jms;
+
+import javax.faces.context.FacesContext;
+
+import org.richfaces.application.push.PushContext;
+import org.richfaces.application.push.PushContextFactory;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class PushContextFactoryImpl implements PushContextFactory {
+
+ private static final class PushContextHolder {
+
+ static final PushContext INSTANCE = createInstance();
+
+ private PushContextHolder() {
+ }
+
+ }
+
+ private static PushContext createInstance() {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ PushContextImpl pushContext = new PushContextImpl();
+ pushContext.init(facesContext);
+
+ return pushContext;
+ }
+
+ public PushContext getPushContext() {
+ return PushContextHolder.INSTANCE;
+ }
+
+}
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextImpl.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushContextImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,119 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl.jms;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.PreDestroyApplicationEvent;
+import javax.faces.event.SystemEvent;
+import javax.faces.event.SystemEventListener;
+import javax.naming.CompositeName;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.atmosphere.cpr.AtmosphereHandler;
+import org.richfaces.application.push.PushContext;
+import org.richfaces.application.push.SessionFactory;
+import org.richfaces.application.push.TopicsContext;
+import org.richfaces.application.push.impl.AtmosphereHandlerProvider;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class PushContextImpl implements PushContext, SystemEventListener, AtmosphereHandlerProvider {
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ private MessagingContext messagingContext;
+
+ private TopicsContext topicsContext;
+
+ private PushHandlerImpl pushHandlerImpl;
+
+ public TopicsContext getTopicsContext() {
+ return topicsContext;
+ }
+
+ public void init(FacesContext facesContext) {
+ try {
+ facesContext.getApplication().subscribeToEvent(PreDestroyApplicationEvent.class, this);
+ facesContext.getExternalContext().getApplicationMap().put(PushContext.INSTANCE_KEY_NAME, this);
+
+ InitialContext initialContext = new InitialContext();
+ Name cnfName = new CompositeName("/ConnectionFactory");
+ Name topicsRootName = new CompositeName("/topic");
+
+ messagingContext = new MessagingContext(initialContext, cnfName, topicsRootName,
+ facesContext.getExternalContext().getContextName());
+
+ messagingContext.shareInstance(facesContext);
+
+ messagingContext.start();
+
+ topicsContext = new TopicsContextImpl(messagingContext);
+
+ pushHandlerImpl = new PushHandlerImpl(messagingContext, topicsContext);
+ } catch (Exception e) {
+ throw new FacesException(e.getMessage(), e);
+ }
+ }
+
+ public void destroy() {
+ try {
+ messagingContext.stop();
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+
+ try {
+ pushHandlerImpl.destroy();
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+
+ public void processEvent(SystemEvent event) throws AbortProcessingException {
+ if (event instanceof PreDestroyApplicationEvent) {
+ destroy();
+ } else {
+ throw new IllegalArgumentException(event.getClass().getName());
+ }
+ }
+
+ public boolean isListenerForSource(Object source) {
+ return true;
+ }
+
+ public SessionFactory getSessionFactory() {
+ return pushHandlerImpl;
+ }
+
+ public AtmosphereHandler<HttpServletRequest, HttpServletResponse> getHandler() {
+ return pushHandlerImpl;
+ }
+}
Modified: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushHandlerImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushHandlerImpl.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/PushHandlerImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -21,57 +21,32 @@
*/
package org.richfaces.application.push.impl.jms;
-import javax.naming.CompositeName;
-import javax.naming.InitialContext;
-import javax.naming.Name;
-import javax.servlet.ServletConfig;
-
-import org.richfaces.application.push.PublisherContext;
import org.richfaces.application.push.Session;
+import org.richfaces.application.push.SessionFactory;
+import org.richfaces.application.push.TopicsContext;
import org.richfaces.application.push.impl.AtmospherePushHandler;
/**
* @author Nick Belaevski
*
*/
-public class PushHandlerImpl extends AtmospherePushHandler {
+public class PushHandlerImpl extends AtmospherePushHandler implements SessionFactory {
private MessagingContext messagingContext;
- private ServletConfig servletConfig;
+ private TopicsContext topicsContext;
- @Override
- protected Session createSession(String key) {
- return new SessionImpl(key, messagingContext);
+ public PushHandlerImpl(MessagingContext messagingContext, TopicsContext topicsContext) {
+ super();
+ this.messagingContext = messagingContext;
+ this.topicsContext = topicsContext;
}
- @Override
- public void init(ServletConfig servletConfig) throws Exception {
- super.init(servletConfig);
-
- this.servletConfig = servletConfig;
+ public Session createSession(String key) {
+ Session session = new SessionImpl(key, messagingContext, topicsContext);
+ getSessionManager().putPushSession(session);
- InitialContext initialContext = new InitialContext();
- Name cnfName = new CompositeName("/ConnectionFactory");
- Name topicsRootName = new CompositeName("/topic");
-
- messagingContext = new MessagingContext(initialContext, cnfName, topicsRootName,
- servletConfig.getServletContext().getContextPath());
-
- messagingContext.start();
-
- PublisherContext publisherContext = new PublisherContextImpl(messagingContext);
- servletConfig.getServletContext().setAttribute(PublisherContext.ATTRIBUTE_NAME, publisherContext);
+ return session;
}
-
- @Override
- public void destroy() throws Exception {
- super.destroy();
- this.servletConfig.getServletContext().removeAttribute(PublisherContext.ATTRIBUTE_NAME);
- this.servletConfig = null;
-
- messagingContext.stop();
- messagingContext = null;
- }
}
Modified: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/SessionImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/SessionImpl.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/SessionImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -29,13 +29,18 @@
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Session;
+import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicSubscriber;
+import org.richfaces.application.push.AbortSubscriptionException;
import org.richfaces.application.push.Request;
import org.richfaces.application.push.RequestLifecycleListener;
import org.richfaces.application.push.TopicKey;
+import org.richfaces.application.push.TopicsContext;
import org.richfaces.application.push.impl.AbstractSession;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
/**
* @author Nick Belaevski
@@ -43,39 +48,50 @@
*/
public class SessionImpl extends AbstractSession implements RequestLifecycleListener, MessageListener {
- private MessagingContext messagingContext;
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+ private final MessagingContext messagingContext;
+
+ private final TopicsContext topicsContext;
+
private Collection<TopicKey> subscribedTopics = new HashSet<TopicKey>();
private volatile Session jmsSession;
- public SessionImpl(String id, MessagingContext messagingContext) {
+ public SessionImpl(String id, MessagingContext messagingContext, TopicsContext topicsContext) {
super(id);
this.messagingContext = messagingContext;
+ this.topicsContext = topicsContext;
}
- private String getSubscriptionClientId(TopicKey topic) {
- //TODO add application name
- return "rf-push:" + messagingContext.getApplicationName() + ":" + topic.getTopicName() + ":" + getId();
+ private String getSubscriptionClientId(TopicKey topicKey) {
+ return "rf-push:" + messagingContext.getApplicationName() + ":" + topicKey.getTopicName() + ":" + getId();
}
- public void subscribe(TopicKey topic) throws Exception {
+ public void subscribe(TopicKey topicKey) throws Exception {
Session session = null;
try {
session = messagingContext.createSession();
- //TODO send event to check subscription permissions
- session.createDurableSubscriber(messagingContext.lookup(topic), getSubscriptionClientId(topic));
- subscribedTopics.add(topic);
+ org.richfaces.application.push.Topic topic = topicsContext.getTopic(topicKey);
+ try {
+ topic.notifySubscription(this, topicKey);
+
+ //TODO send event to check subscription permissions
+ session.createDurableSubscriber(messagingContext.lookup(topicKey), getSubscriptionClientId(topicKey));
+ subscribedTopics.add(topicKey);
+ } catch (AbortSubscriptionException e) {
+ // TODO: handle exception
+ }
+
} finally {
if (session != null) {
try {
session.close();
} catch (JMSException e) {
- // TODO: handle exception
- e.printStackTrace();
+ LOGGER.error(e.getMessage(), e);
}
}
}
@@ -83,6 +99,11 @@
@Override
public void destroy() {
+ for (TopicKey topicKey : subscribedTopics) {
+ org.richfaces.application.push.Topic topic = topicsContext.getTopic(topicKey);
+ topic.notifyUnsubscription(this, topicKey);
+ }
+
// TODO Auto-generated method stub
super.destroy();
@@ -116,16 +137,12 @@
super.disconnect(request);
}
- /* (non-Javadoc)
- * @see org.richfaces.application.push.RequestLifecycleListener#onFlush(org.richfaces.application.push.Request)
- */
public void onFlush(Request request) {
if (request.isPolling()) {
try {
jmsSession.close();
} catch (JMSException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ LOGGER.error(e.getMessage(), e);
}
}
}
@@ -169,24 +186,38 @@
* @see javax.jms.MessageListener#onMessage(javax.jms.Message)
*/
public void onMessage(Message message) {
- if (!(message instanceof ObjectMessage)) {
- //TODO log
- return;
- }
+ String messageData = null;
try {
- ObjectMessage objectMessage = (ObjectMessage) message;
- String topicName = ((Topic) objectMessage.getJMSDestination()).getTopicName();
+ String topicName = ((Topic) message.getJMSDestination()).getTopicName();
- org.richfaces.application.push.Message pushMessage = new org.richfaces.application.push.Message(new TopicKey(topicName));
- pushMessage.setData(objectMessage.getObject());
+ org.richfaces.application.push.Topic topic = topicsContext.getTopic(new TopicKey(topicName));
+ if (topic == null) {
+ //TODO log
+ return;
+ }
- getRequest().postMessage(pushMessage);
+ if (message.getBooleanProperty(TopicImpl.SERIALIZED_DATA_INDICATOR)) {
+ messageData = ((TextMessage) message).getText();
+ } else if (message instanceof ObjectMessage) {
+ ObjectMessage objectMessage = (ObjectMessage) message;
+ messageData = topic.getMessageDataSerializer().serialize(objectMessage.getObject());
+ } else if (message instanceof TextMessage) {
+ TextMessage textMessage = (TextMessage) message;
+ messageData = topic.getMessageDataSerializer().serialize(textMessage.getText());
+ }
- objectMessage.acknowledge();
+
+ if (messageData == null) {
+ //TODO log
+ return;
+ }
+
+ getRequest().postMessage(new TopicKey(topicName), messageData);
+
+ message.acknowledge();
} catch (JMSException e) {
- // TODO: handle exception
- e.printStackTrace();
+ LOGGER.error(e.getMessage(), e);
}
}
}
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicImpl.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl.jms;
+
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.NamingException;
+
+import org.richfaces.application.push.MessageException;
+import org.richfaces.application.push.TopicKey;
+import org.richfaces.application.push.impl.AbstractTopic;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class TopicImpl extends AbstractTopic {
+
+ static final String SERIALIZED_DATA_INDICATOR = "org_richfaces_push_SerializedData";
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ private MessagingContext messagingContext;
+
+ public TopicImpl(TopicKey key, MessagingContext messagingContext) {
+ super(key);
+
+ this.messagingContext = messagingContext;
+ }
+
+ @Override
+ public void publish(Object messageData) throws MessageException {
+ String serializedData = getMessageDataSerializer().serialize(messageData);
+
+ Session session = null;
+ try {
+ session = messagingContext.createSession();
+ MessageProducer producer = session.createProducer(messagingContext.lookup(getKey()));
+
+ TextMessage textMessage = session.createTextMessage();
+ textMessage.setText(serializedData);
+ textMessage.setBooleanProperty(SERIALIZED_DATA_INDICATOR, true);
+
+ producer.send(textMessage);
+ } catch (JMSException e) {
+ throw new MessageException(e.getMessage(), e);
+ } catch (NamingException e) {
+ throw new MessageException(e.getMessage(), e);
+ } finally {
+ if (session != null) {
+ try {
+ session.close();
+ } catch (JMSException e) {
+ LOGGER.debug(e.getMessage(), e);
+ }
+ }
+ }
+ }
+}
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicsContextImpl.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicsContextImpl.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/application/push/impl/jms/TopicsContextImpl.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application.push.impl.jms;
+
+import org.richfaces.application.push.Topic;
+import org.richfaces.application.push.TopicKey;
+import org.richfaces.application.push.TopicsContext;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class TopicsContextImpl extends TopicsContext {
+
+ private MessagingContext messagingContext;
+
+ public TopicsContextImpl(MessagingContext messagingContext) {
+ super();
+ this.messagingContext = messagingContext;
+ }
+
+ protected Topic createTopic(TopicKey key) {
+ return new TopicImpl(key, messagingContext);
+ }
+
+}
Modified: branches/RF-7817/push-redesign/src/main/java/org/richfaces/renderkit/PushRendererBase.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/renderkit/PushRendererBase.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/renderkit/PushRendererBase.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -21,16 +21,17 @@
*/
package org.richfaces.renderkit;
-import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
+import javax.faces.application.Resource;
+import javax.faces.application.ResourceHandler;
import javax.faces.component.UIComponent;
-import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.render.Renderer;
import org.ajax4jsf.javascript.ScriptUtils;
+import org.richfaces.application.push.impl.PushResource;
import org.richfaces.component.AbstractPush;
/**
@@ -42,11 +43,10 @@
private static final String PUSH_URL_ENCODED_ATTRIBUTE = PushRendererBase.class.getName();
protected String getPushUrl(FacesContext context) {
- ExternalContext ec = context.getExternalContext();
+ ResourceHandler resourceHandler = context.getApplication().getResourceHandler();
+ Resource pushResource = resourceHandler.createResource(PushResource.class.getName());
- return MessageFormat.format("{0}://{1}:{2,number,#####}{3}/push",
- ec.getRequestScheme(), ec.getRequestServerName(),
- ec.getRequestServerPort(), ec.getRequestContextPath());
+ return pushResource.getRequestPath();
}
protected boolean shouldEncodePushUrl(FacesContext context) {
Added: branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushFilter.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushFilter.java (rev 0)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushFilter.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,143 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.webapp;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.atmosphere.cpr.AtmosphereServlet;
+import org.richfaces.application.push.PushContext;
+import org.richfaces.application.push.impl.AtmosphereHandlerProvider;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+//TODO override broadcaster
+public class PushFilter implements Filter {
+
+ private static final String PUSH_HUB_MAPPING = "/*";
+
+ private static final long serialVersionUID = 7616370505508715222L;
+
+ /**
+ * @author Nick Belaevski
+ *
+ */
+ private final class ServletConfigFacade implements ServletConfig {
+ /**
+ *
+ */
+ private final FilterConfig filterConfig;
+
+ /**
+ * @param filterConfig
+ */
+ private ServletConfigFacade(FilterConfig filterConfig) {
+ this.filterConfig = filterConfig;
+ }
+
+ public String getServletName() {
+ return filterConfig.getFilterName();
+ }
+
+ public ServletContext getServletContext() {
+ return filterConfig.getServletContext();
+ }
+
+ public String getInitParameter(String name) {
+ return filterConfig.getInitParameter(name);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Enumeration<String> getInitParameterNames() {
+ return filterConfig.getInitParameterNames();
+ }
+ }
+
+ private AtmosphereServlet atmosphereServlet;
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ AtmosphereHandlerProvider handlerProvider = (AtmosphereHandlerProvider) filterConfig.getServletContext().getAttribute(PushContext.INSTANCE_KEY_NAME);
+
+ if (handlerProvider == null) {
+ return;
+ }
+
+ atmosphereServlet = new AtmosphereServlet() {
+
+ private static final long serialVersionUID = -8719394110408476331L;
+
+ protected boolean detectSupportedFramework(ServletConfig sc) throws ClassNotFoundException, IllegalAccessException, InstantiationException ,NoSuchMethodException ,java.lang.reflect.InvocationTargetException {
+ return false;
+ };
+ };
+ ServletConfigFacade servletConfig = new ServletConfigFacade(filterConfig);
+ atmosphereServlet.init(servletConfig);
+
+ atmosphereServlet.addAtmosphereHandler(PUSH_HUB_MAPPING, handlerProvider.getHandler());
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+ */
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+ ServletException {
+
+ if (atmosphereServlet != null && request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
+ HttpServletRequest httpReq = (HttpServletRequest) request;
+ HttpServletResponse httpResp = (HttpServletResponse) response;
+
+ if ("GET".equals(httpReq.getMethod()) && httpReq.getQueryString() != null && httpReq.getQueryString().contains("__richfacesPushAsync")) {
+ atmosphereServlet.doGet(httpReq, httpResp);
+ return;
+ }
+ }
+
+ // TODO Auto-generated method stub
+ chain.doFilter(request, response);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Filter#destroy()
+ */
+ public void destroy() {
+ if (atmosphereServlet != null) {
+ atmosphereServlet.removeAtmosphereHandler(PUSH_HUB_MAPPING);
+ atmosphereServlet.destroy();
+ atmosphereServlet = null;
+ }
+ // TODO Auto-generated method stub
+ }
+
+}
Deleted: branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushServlet.java
===================================================================
--- branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushServlet.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/java/org/richfaces/webapp/PushServlet.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -1,104 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.richfaces.webapp;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.atmosphere.cpr.AtmosphereServlet;
-import org.richfaces.application.push.Session;
-import org.richfaces.application.push.impl.AtmospherePushHandler;
-import org.richfaces.application.push.impl.jms.PushHandlerImpl;
-
-/**
- * @author Nick Belaevski
- *
- */
-//TODO override broadcaster
-public class PushServlet extends AtmosphereServlet {
-
- private static final String PUSH_HUB_MAPPING = "/push/hub/*";
-
- private static final long serialVersionUID = 7616370505508715222L;
-
- private static final String PUSH_TOPIC_PARAM = "pushTopic[]";
-
- private AtmospherePushHandler pushHandler;
-
- @Override
- public void init(ServletConfig config) throws ServletException {
- super.init(config);
-
- pushHandler = new PushHandlerImpl();
- try {
- pushHandler.init(config);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- addAtmosphereHandler(PUSH_HUB_MAPPING, pushHandler);
- }
-
- @Override
- public void destroy() {
- super.destroy();
-
- try {
- pushHandler.destroy();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- pushHandler = null;
-
- removeAtmosphereHandler(PUSH_HUB_MAPPING);
- }
-
- @Override
- public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String[] topicNames = req.getParameterValues(PUSH_TOPIC_PARAM);
- Session pushSession = pushHandler.doConnect(topicNames);
-
- resp.setStatus(HttpServletResponse.SC_OK);
- resp.getWriter().write(pushSession.getId());
- }
-
- @Override
- public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
- doCometSupport(req, res);
- }
-
- /* (non-Javadoc)
- * @see org.atmosphere.cpr.AtmosphereServlet#detectSupportedFramework(javax.servlet.ServletConfig)
- */
- @Override
- protected boolean detectSupportedFramework(ServletConfig sc) throws ClassNotFoundException, IllegalAccessException,
- InstantiationException, NoSuchMethodException, InvocationTargetException {
-
- return false;
- }
-}
Modified: branches/RF-7817/push-redesign/src/main/resources/META-INF/resources/org.richfaces/push.js
===================================================================
--- branches/RF-7817/push-redesign/src/main/resources/META-INF/resources/org.richfaces/push.js 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign/src/main/resources/META-INF/resources/org.richfaces/push.js 2010-10-21 00:31:11 UTC (rev 19622)
@@ -56,7 +56,7 @@
var connect = function() {
var pushSessionIdRequestHandler = function(data) {
pushSessionId = data;
- _$.atmosphere.subscribe(pushUrl + "/hub?pushSessionId=" + pushSessionId, messageCallback, {
+ _$.atmosphere.subscribe(pushUrl + "?__richfacesPushAsync=1&pushSessionId=" + pushSessionId, messageCallback, {
transport: 'websocket'
});
};
@@ -68,7 +68,14 @@
//TODO handle request errors
//TODO separate URLs
- _$.post(pushUrl + "/connect", {"pushTopic": topics}, pushSessionIdRequestHandler, 'text');
+ _$.ajax({
+ data: {"pushTopic": topics},
+ dataType: 'text',
+ success: pushSessionIdRequestHandler,
+ traditional: true,
+ type: 'POST',
+ url: pushUrl
+ });
};
var disconnect = function() {
Added: branches/RF-7817/push-redesign/src/main/resources/META-INF/services/org.richfaces.application.push.PushContextFactory
===================================================================
--- branches/RF-7817/push-redesign/src/main/resources/META-INF/services/org.richfaces.application.push.PushContextFactory (rev 0)
+++ branches/RF-7817/push-redesign/src/main/resources/META-INF/services/org.richfaces.application.push.PushContextFactory 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1 @@
+org.richfaces.application.push.impl.jms.PushContextFactoryImpl
\ No newline at end of file
Modified: branches/RF-7817/push-redesign-app/pom.xml
===================================================================
--- branches/RF-7817/push-redesign-app/pom.xml 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign-app/pom.xml 2010-10-21 00:31:11 UTC (rev 19622)
@@ -62,15 +62,15 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>javax.servlet</groupId>
+ <groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
- <version>3.0-alpha-1</version>
+ <version>3.0.20100224</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
- <version>0.6.2</version>
+ <version>0.6.3</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
Modified: branches/RF-7817/push-redesign-app/src/main/java/demo/ChatBean.java
===================================================================
--- branches/RF-7817/push-redesign-app/src/main/java/demo/ChatBean.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign-app/src/main/java/demo/ChatBean.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -25,12 +25,15 @@
import java.text.MessageFormat;
import java.util.Date;
+import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
-import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
-import org.richfaces.application.push.PublisherContext;
+import org.richfaces.application.push.MessageException;
import org.richfaces.application.push.TopicKey;
+import org.richfaces.application.push.TopicsContext;
+import org.richfaces.log.LogFactory;
+import org.richfaces.log.Logger;
/**
* @author Nick Belaevski
@@ -42,15 +45,21 @@
private static final long serialVersionUID = -6377543444437645751L;
+ private static final Logger LOGGER = LogFactory.getLogger(ChatBean.class);
+
private String userName;
private String message;
private boolean chatJoined;
- @ManagedProperty("#{" + PublisherContext.ATTRIBUTE_NAME + "}")
- private transient PublisherContext publisherContext;
+ private transient TopicsContext topicsContext;
+ @PostConstruct
+ public void init() {
+ topicsContext = TopicsContext.lookup();
+ }
+
public String getMessage() {
return message;
}
@@ -74,20 +83,26 @@
}
chatJoined = true;
- publisherContext.publish(new TopicKey("chat"), MessageFormat.format("*** {0} joined chat in {1,time,medium}",
- userName, new Date()));
+ try {
+ topicsContext.publish(new TopicKey("chat"), MessageFormat.format("*** {0} joined chat in {1,time,medium}",
+ userName, new Date()));
+ } catch (MessageException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
}
}
public void say() {
- publisherContext.publish(new TopicKey("chat"), MessageFormat.format("{0,time,medium} {1}: {2}", new Date(),
- userName, message));
+ try {
+ topicsContext.publish(new TopicKey("chat"), MessageFormat.format("{0,time,medium} {1}: {2}", new Date(),
+ userName, message));
+ } catch (MessageException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
}
- /**
- * @param publisherContext the publisherContext to set
- */
- public void setPublisherContext(PublisherContext publisherContext) {
- this.publisherContext = publisherContext;
+ public void setTopicsContext(TopicsContext topicsContext) {
+ this.topicsContext = topicsContext;
}
+
}
Modified: branches/RF-7817/push-redesign-app/src/main/java/demo/TopicsInitializer.java
===================================================================
--- branches/RF-7817/push-redesign-app/src/main/java/demo/TopicsInitializer.java 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign-app/src/main/java/demo/TopicsInitializer.java 2010-10-21 00:31:11 UTC (rev 19622)
@@ -21,13 +21,18 @@
*/
package demo;
+import java.text.MessageFormat;
+
+import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
+import javax.servlet.http.HttpServletRequest;
-import org.richfaces.application.ServiceTracker;
+import org.richfaces.application.push.Session;
import org.richfaces.application.push.Topic;
import org.richfaces.application.push.TopicKey;
+import org.richfaces.application.push.TopicListener;
import org.richfaces.application.push.TopicsContext;
import org.richfaces.application.push.impl.DefaultMessageDataSerializer;
@@ -39,11 +44,28 @@
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
- TopicsContext topicsContext = ServiceTracker.getService(TopicsContext.class);
+ TopicsContext topicsContext = TopicsContext.lookup();
- Topic topic = topicsContext.getOrCreateTopic(new TopicKey("chatTopic"));
+ Topic topic = topicsContext.getOrCreateTopic(new TopicKey("chat"));
- topic.setMessageSerializer(DefaultMessageDataSerializer.instance());
+ topic.setMessageDataSerializer(DefaultMessageDataSerializer.instance());
+
+ topic.addTopicListener(new TopicListener() {
+
+ @Override
+ public void onSessionUnsubscribed(Session session, TopicKey topicKey) {
+ System.out.println(MessageFormat.format("Session {0} disconnected from {1}", session.getId(), topicKey.getTopicName()));
+ }
+
+ @Override
+ public void onSessionSubscribed(Session session, TopicKey topicKey) {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ HttpServletRequest hsr = (HttpServletRequest) facesContext.getExternalContext().getRequest();
+
+ System.out.println(MessageFormat.format("Session {0} connected to {1} from {2}", session.getId(),
+ topicKey.getTopicName(), hsr.getRemoteAddr()));
+ }
+ });
}
@Override
Modified: branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
--- branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/faces-config.xml 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/faces-config.xml 2010-10-21 00:31:11 UTC (rev 19622)
@@ -14,5 +14,19 @@
<system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
</system-event-listener>
</application>
+
+ <navigation-rule>
+ <from-view-id>*</from-view-id>
+ <navigation-case>
+ <from-outcome>chat</from-outcome>
+ <to-view-id>/chat.xhtml</to-view-id>
+ <redirect>
+ <view-param>
+ <name>username</name>
+ <value>#{username}</value>
+ </view-param>
+ </redirect>
+ </navigation-case>
+ </navigation-rule>
</faces-config>
\ No newline at end of file
Modified: branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/web.xml
===================================================================
--- branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/web.xml 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign-app/src/main/webapp/WEB-INF/web.xml 2010-10-21 00:31:11 UTC (rev 19622)
@@ -12,6 +12,19 @@
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
+
+ <filter-mapping>
+ <filter-name>PushFilter</filter-name>
+ <url-pattern>/faces/*</url-pattern>
+ </filter-mapping>
+
+ <filter>
+ <filter-name>PushFilter</filter-name>
+ <filter-class>org.richfaces.webapp.PushFilter</filter-class>
+ <async-supported>true</async-supported>
+ </filter>
+
+ <!--
<servlet>
<servlet-name>push</servlet-name>
<servlet-class>org.richfaces.webapp.PushServlet</servlet-class>
@@ -26,7 +39,7 @@
<servlet-name>push</servlet-name>
<url-pattern>/push/*</url-pattern>
</servlet-mapping>
-
+ -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
Copied: branches/RF-7817/push-redesign-app/src/main/webapp/chat.xhtml (from rev 19574, branches/RF-7817/push-redesign-app/src/main/webapp/index.xhtml)
===================================================================
--- branches/RF-7817/push-redesign-app/src/main/webapp/chat.xhtml (rev 0)
+++ branches/RF-7817/push-redesign-app/src/main/webapp/chat.xhtml 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,41 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:p="http://richfaces.org/push-redesign">
+
+ <f:view>
+ <f:metadata>
+ <f:viewParam name="username" value="#{chatBean.userName}" />
+ <f:event type="preRenderView" listener="#{chatBean.joinChat}"/>
+ </f:metadata>
+ <h:head>
+ </h:head>
+ <h:body>
+ <h:form id="form">
+ <p:push topic="chat" ondataavailable="jQuery('<div />').prependTo('.chatOutput').text(data)" />
+
+ You are: #{chatBean.userName} <br />
+
+ <h:inputText styleClass="messageInput" value="#{chatBean.message}" size="40" />
+
+ <script type="text/javascript">
+ function clearInput(event) {
+ if (event.status == 'success') {
+ jQuery('.messageInput').val('');
+ }
+ }
+ </script>
+
+ <h:commandLink value="ajax" action="#{chatBean.say}">
+ <f:ajax execute="@form" onevent="clearInput" />
+ </h:commandLink>
+
+ <h:panelGroup id="group" styleClass="chatOutput" layout="block" />
+ </h:form>
+ </h:body>
+ </f:view>
+</html>
\ No newline at end of file
Added: branches/RF-7817/push-redesign-app/src/main/webapp/index.jsp
===================================================================
--- branches/RF-7817/push-redesign-app/src/main/webapp/index.jsp (rev 0)
+++ branches/RF-7817/push-redesign-app/src/main/webapp/index.jsp 2010-10-21 00:31:11 UTC (rev 19622)
@@ -0,0 +1,6 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+
+<%
+ response.sendRedirect(request.getContextPath() + "/faces/index.xhtml");
+%>
\ No newline at end of file
Modified: branches/RF-7817/push-redesign-app/src/main/webapp/index.xhtml
===================================================================
--- branches/RF-7817/push-redesign-app/src/main/webapp/index.xhtml 2010-10-21 00:19:03 UTC (rev 19621)
+++ branches/RF-7817/push-redesign-app/src/main/webapp/index.xhtml 2010-10-21 00:31:11 UTC (rev 19622)
@@ -4,37 +4,15 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
- xmlns:f="http://java.sun.com/jsf/core"
- xmlns:p="http://richfaces.org/push-redesign">
+ xmlns:f="http://java.sun.com/jsf/core">
<f:view>
- <f:metadata>
- <f:viewParam name="username" value="#{chatBean.userName}" />
- <f:event type="preRenderView" listener="#{chatBean.joinChat}"/>
- </f:metadata>
<h:head>
</h:head>
<h:body>
<h:form id="form">
- <p:push topic="chat" ondataavailable="jQuery('<div />').prependTo('.chatOutput').text(data)" />
-
- You are: #{chatBean.userName} <br />
-
- <h:inputText styleClass="messageInput" value="#{chatBean.message}" size="40" />
-
- <script type="text/javascript">
- function clearInput(event) {
- if (event.status == 'success') {
- jQuery('.messageInput').val('');
- }
- }
- </script>
-
- <h:commandLink value="ajax" action="#{chatBean.say}">
- <f:ajax execute="@form" onevent="clearInput" />
- </h:commandLink>
-
- <h:panelGroup id="group" styleClass="chatOutput" layout="block" />
+ Enter username: <h:inputText value="#{username}" required="true" />
+ <h:commandLink action="chat" value="Enter chat" />
</h:form>
</h:body>
</f:view>
13 years, 8 months
JBoss Rich Faces SVN: r19621 - in branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces: renderkit/html and 1 other directory.
by richfaces-svn-commits@lists.jboss.org
Author: alexsmirnov
Date: 2010-10-20 20:19:03 -0400 (Wed, 20 Oct 2010)
New Revision: 19621
Added:
branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/AjaxOnlyScript.java
branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientAndAjaxScript.java
branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientOnlyScript.java
branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/NoSuchComponentException.java
Modified:
branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/component/UIValidatorScript.java
branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientValidatorRenderer.java
branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ComponentValidatorScript.java
Log:
OPEN - issue RF-9507: ClientValidatorRendererunit tests and implementation.
https://jira.jboss.org/browse/RF-9507
Modified: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/component/UIValidatorScript.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/component/UIValidatorScript.java 2010-10-20 18:32:23 UTC (rev 19620)
+++ branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/component/UIValidatorScript.java 2010-10-21 00:19:03 UTC (rev 19621)
@@ -43,8 +43,9 @@
return null;
}
- public String addScript(ComponentValidatorScript script){
+
+ public ComponentValidatorScript addOrFindScript(ComponentValidatorScript validatorScript) {
+ // TODO Auto-generated method stub
return null;
-
}
}
Added: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/AjaxOnlyScript.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/AjaxOnlyScript.java (rev 0)
+++ branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/AjaxOnlyScript.java 2010-10-21 00:19:03 UTC (rev 19621)
@@ -0,0 +1,34 @@
+package org.richfaces.renderkit.html;
+
+import java.util.Collection;
+
+import org.richfaces.validator.LibraryResource;
+
+public class AjaxOnlyScript implements ComponentValidatorScript {
+
+ public String toScript() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void appendScript(StringBuffer functionString) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String getName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Collection<LibraryResource> getResources() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String createCallScript(String clientId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Property changes on: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/AjaxOnlyScript.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientAndAjaxScript.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientAndAjaxScript.java (rev 0)
+++ branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientAndAjaxScript.java 2010-10-21 00:19:03 UTC (rev 19621)
@@ -0,0 +1,39 @@
+package org.richfaces.renderkit.html;
+
+import java.util.Collection;
+
+import org.richfaces.validator.LibraryResource;
+
+public class ClientAndAjaxScript implements ComponentValidatorScript {
+
+ public ClientAndAjaxScript(LibraryScriptFunction clientSideConverterScript,
+ Collection<LibraryScriptFunction> validatorScripts, String ajaxScript) {
+ // TODO Auto-generated constructor stub
+ }
+
+ public String toScript() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void appendScript(StringBuffer functionString) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String getName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Collection<LibraryResource> getResources() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String createCallScript(String clientId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Property changes on: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientAndAjaxScript.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientOnlyScript.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientOnlyScript.java (rev 0)
+++ branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientOnlyScript.java 2010-10-21 00:19:03 UTC (rev 19621)
@@ -0,0 +1,39 @@
+package org.richfaces.renderkit.html;
+
+import java.util.Collection;
+
+import org.richfaces.validator.LibraryResource;
+
+public class ClientOnlyScript implements ComponentValidatorScript {
+
+ public ClientOnlyScript(LibraryScriptFunction clientSideConverterScript,
+ Collection<LibraryScriptFunction> validatorScripts) {
+ // TODO Auto-generated constructor stub
+ }
+
+ public String toScript() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void appendScript(StringBuffer functionString) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String getName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Collection<LibraryResource> getResources() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String createCallScript(String clientId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Property changes on: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientOnlyScript.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientValidatorRenderer.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientValidatorRenderer.java 2010-10-20 18:32:23 UTC (rev 19620)
+++ branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ClientValidatorRenderer.java 2010-10-21 00:19:03 UTC (rev 19621)
@@ -3,86 +3,223 @@
//
// Imports
//
+import java.util.Collection;
+import java.util.List;
+
import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.context.FacesContext;
import javax.faces.render.ClientBehaviorRenderer;
+import org.ajax4jsf.javascript.JSLiteral;
+import org.richfaces.application.ServiceTracker;
import org.richfaces.component.UIValidatorScript;
import org.richfaces.component.behavior.ClientValidatorBehavior;
+import org.richfaces.component.behavior.ConverterNotFoundException;
+import org.richfaces.validator.ClientScriptService;
import org.richfaces.validator.ConverterDescriptor;
+import org.richfaces.validator.LibraryScript;
import org.richfaces.validator.ScriptNotFoundException;
import org.richfaces.validator.ValidatorDescriptor;
+import com.google.common.collect.Lists;
+
/**
* Renderer for component class org.richfaces.renderkit.html.AjaxValidatorRenderer
*/
public class ClientValidatorRenderer extends ClientBehaviorRenderer {
+
public static final String RENDERER_TYPE = "org.richfaces.ClientValidatorRenderer";
-
+
public static final String VALUE_VAR = "value";
public static final String CONVERTED_VALUE_VAR = "convertedValue";
+ public static final JSLiteral VALUE_LITERAL = new JSLiteral("value");
+
+ public static final JSLiteral CONVERTED_VALUE_LITERAL = new JSLiteral("convertedValue");
+
public ClientValidatorRenderer() {
super();
}
@Override
public String getScript(ClientBehaviorContext behaviorContext, ClientBehavior behavior) {
+ if (null == behaviorContext) {
+ throw new NullPointerException();
+ }
+ if (null == behavior) {
+ throw new NullPointerException();
+ }
if (behavior instanceof ClientValidatorBehavior) {
ClientValidatorBehavior clientValidator = (ClientValidatorBehavior) behavior;
-
+ return buildAndStoreValidatorScript(behaviorContext, clientValidator);
} else {
throw new FacesException(
"ClientBehavior for ClientValidatorRenderer does not implement ClientValidatorBehavior interface");
}
- return null;
}
-
+
/**
- * <p class="changed_added_4_0">This method builds client-side validation script and stores it in View resource component</p>
+ * <p class="changed_added_4_0">
+ * This method builds client-side validation script and stores it in View resource component
+ * </p>
+ *
* @param behaviorContext
* @param behavior
- * @return name of the JavaScript function to call
+ * @return name of the JavaScript function to call
*/
- String buildAndStoreValidatorScript(ClientBehaviorContext behaviorContext, ClientValidatorBehavior behavior){
- return null;
+ String buildAndStoreValidatorScript(ClientBehaviorContext behaviorContext, ClientValidatorBehavior behavior) {
+ ComponentValidatorScript validatorScript = createValidatorScript(behaviorContext, behavior);
+ if (null != validatorScript) {
+ FacesContext facesContext = behaviorContext.getFacesContext();
+ UIValidatorScript scriptResource = getOrCreateValidatorScriptResource(facesContext);
+ validatorScript = scriptResource.addOrFindScript(validatorScript);
+ return validatorScript.createCallScript(behaviorContext.getComponent().getClientId(facesContext));
+ } else {
+ return null;
+ }
}
-
- UIValidatorScript getOrCreateValidatorScriptResource(FacesContext facesContext){
- return null;
+
+ /**
+ * <p class="changed_added_4_0">
+ * This method looks for {@link UIValidatorScript} component in view resource. If such resource not found, it
+ * creates a new instance and stores it in {@link UIViewRoot} view resource with default target.
+ * </p>
+ *
+ * @param facesContext
+ * @return
+ */
+ UIValidatorScript getOrCreateValidatorScriptResource(FacesContext facesContext) {
+ UIViewRoot viewRoot = facesContext.getViewRoot();
+ if (null == viewRoot) {
+ throw new FacesException("View is not created");
+ }
+ List<UIComponent> componentResources = viewRoot.getComponentResources(facesContext, "form");
+ try {
+ return findScriptResource(componentResources);
+ } catch (NoSuchComponentException e) {
+ componentResources = viewRoot.getComponentResources(facesContext, "body");
+ try {
+ return findScriptResource(componentResources);
+ } catch (NoSuchComponentException e1) {
+ UIValidatorScript component =
+ (UIValidatorScript) facesContext.getApplication().createComponent(UIValidatorScript.COMPONENT_TYPE);
+ viewRoot.addComponentResource(facesContext, component);
+ return component;
+ }
+ }
}
-
+ private UIValidatorScript findScriptResource(List<UIComponent> componentResources) throws NoSuchComponentException {
+ for (UIComponent uiComponent : componentResources) {
+ if (uiComponent instanceof UIValidatorScript) {
+ UIValidatorScript script = (UIValidatorScript) uiComponent;
+ return script;
+ }
+ }
+ throw new NoSuchComponentException();
+ }
+
ComponentValidatorScript createValidatorScript(ClientBehaviorContext behaviorContext,
ClientValidatorBehavior behavior) {
- return null;
+ Collection<ValidatorDescriptor> validators = behavior.getValidators(behaviorContext);
+ if (!validators.isEmpty()) {
+ try {
+ ConverterDescriptor converter = behavior.getConverter(behaviorContext);
+ if (null != converter) {
+ try {
+ LibraryScriptFunction clientSideConverterScript =
+ getClientSideConverterScript(behaviorContext, converter);
+ return createValidatorScript(behaviorContext, behavior, validators, clientSideConverterScript);
+ } catch (ScriptNotFoundException e) {
+ // ajax-only validation
+ return new AjaxOnlyScript();
+ }
+ } else {
+ return createValidatorScript(behaviorContext, behavior, validators, null);
+ }
+ } catch (ConverterNotFoundException e) {
+ throw new FacesException(e);
+ }
+ } else {
+ // No validation required.
+ return null;
+ }
}
+ private ComponentValidatorScript createValidatorScript(ClientBehaviorContext behaviorContext,
+ ClientValidatorBehavior behavior, Collection<ValidatorDescriptor> validators,
+ LibraryScriptFunction clientSideConverterScript) {
+ Collection<LibraryScriptFunction> validatorScripts = getClientSideValidatorScript(behaviorContext, validators);
+ if (validatorScripts.isEmpty()) {
+ return new AjaxOnlyScript();
+ } else if (validatorScripts.size() < validators.size()) {
+ return new ClientAndAjaxScript(clientSideConverterScript, validatorScripts,
+ behavior.getAjaxScript(behaviorContext));
+ } else {
+ return new ClientOnlyScript(clientSideConverterScript, validatorScripts);
+ }
+ }
+
/**
- * <p class="changed_added_4_0">Build client-side function call for Server-side component descriptor.</p>
+ * <p class="changed_added_4_0">
+ * Build client-side function call for Server-side component descriptor.
+ * </p>
+ *
* @param behaviorContext
* @param validator
* @return
* @throws ScriptNotFoundException
*/
- LibraryScriptFunction getClientSideConverterScript(ClientBehaviorContext behaviorContext, ConverterDescriptor converter)
- throws ScriptNotFoundException {
- return null;
+ /**
+ * <p class="changed_added_4_0">
+ * </p>
+ *
+ * @param behaviorContext
+ * @param converter
+ * @return
+ * @throws ScriptNotFoundException
+ */
+ LibraryScriptFunction getClientSideConverterScript(ClientBehaviorContext behaviorContext,
+ ConverterDescriptor converter) throws ScriptNotFoundException {
+ ClientScriptService clientScriptService =
+ ServiceTracker.getService(behaviorContext.getFacesContext(), ClientScriptService.class);
+ return createClientFunction(converter, VALUE_LITERAL, clientScriptService);
}
+ private LibraryScriptFunction createClientFunction(ValidatorDescriptor descriptor, JSLiteral variable,
+ ClientScriptService clientScriptService) throws ScriptNotFoundException {
+ LibraryScript script = clientScriptService.getScript(descriptor.getValidatorClass());
+ return new LibraryScriptFunction(script, variable, descriptor.getMessage(), descriptor.getValidatorParameters());
+ }
+
/**
- * <p class="changed_added_4_0">Build client-side function call for Server-side component descriptor.</p>
+ * <p class="changed_added_4_0">
+ * Build client-side function call for Server-side component descriptor.
+ * </p>
+ *
* @param behaviorContext
- * @param validator
+ * @param validators
* @return
* @throws ScriptNotFoundException
*/
- LibraryScriptFunction getClientSideValidatorScript(ClientBehaviorContext behaviorContext, ValidatorDescriptor validator)
- throws ScriptNotFoundException {
- return null;
+ Collection<LibraryScriptFunction> getClientSideValidatorScript(ClientBehaviorContext behaviorContext,
+ Collection<ValidatorDescriptor> validators) {
+ ClientScriptService clientScriptService =
+ ServiceTracker.getService(behaviorContext.getFacesContext(), ClientScriptService.class);
+ List<LibraryScriptFunction> scripts = Lists.newArrayList();
+ for (ValidatorDescriptor validator : validators) {
+ try {
+ scripts.add(createClientFunction(validator, CONVERTED_VALUE_LITERAL, clientScriptService));
+ } catch (ScriptNotFoundException e) {
+ // Skip this validator for AJAX call.
+ }
+ }
+ return scripts;
}
}
Modified: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ComponentValidatorScript.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ComponentValidatorScript.java 2010-10-20 18:32:23 UTC (rev 19620)
+++ branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/ComponentValidatorScript.java 2010-10-21 00:19:03 UTC (rev 19621)
@@ -9,6 +9,13 @@
String getName();
- Collection<LibraryResource> getResources();
+ Collection<LibraryResource> getResources();
+
+ /**
+ * <p class="changed_added_4_0">Creates JavasCript that calls validator function.</p>
+ * @param clientId
+ * @return
+ */
+ String createCallScript(String clientId);
}
Added: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/NoSuchComponentException.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/NoSuchComponentException.java (rev 0)
+++ branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/NoSuchComponentException.java 2010-10-21 00:19:03 UTC (rev 19621)
@@ -0,0 +1,24 @@
+package org.richfaces.renderkit.html;
+
+public class NoSuchComponentException extends Exception {
+
+ public NoSuchComponentException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public NoSuchComponentException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public NoSuchComponentException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public NoSuchComponentException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+}
Property changes on: branches/RF-8742/ui/validator/ui/src/main/java/org/richfaces/renderkit/html/NoSuchComponentException.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
13 years, 8 months
JBoss Rich Faces SVN: r19620 - in sandbox/trunk/ui/fileupload: api and 2 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: konstantin.mishin
Date: 2010-10-20 14:32:23 -0400 (Wed, 20 Oct 2010)
New Revision: 19620
Added:
sandbox/trunk/ui/fileupload/api/pom.xml
sandbox/trunk/ui/fileupload/api/src/
Removed:
sandbox/trunk/ui/fileupload/src/
Modified:
sandbox/trunk/ui/fileupload/api/
sandbox/trunk/ui/fileupload/api/src/main/java/org/richfaces/event/FileUploadListener.java
sandbox/trunk/ui/fileupload/api/src/main/java/org/richfaces/event/UploadEvent.java
sandbox/trunk/ui/fileupload/pom.xml
sandbox/trunk/ui/fileupload/ui/pom.xml
Log:
RF-9497
Property changes on: sandbox/trunk/ui/fileupload/api
___________________________________________________________________
Name: svn:ignore
+ .settings
target
.classpath
.project
Added: sandbox/trunk/ui/fileupload/api/pom.xml
===================================================================
--- sandbox/trunk/ui/fileupload/api/pom.xml (rev 0)
+++ sandbox/trunk/ui/fileupload/api/pom.xml 2010-10-20 18:32:23 UTC (rev 19620)
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ JBoss, Home of Professional Open Source Copyright 2010, Red Hat,
+ Inc. and individual contributors by the @authors tag. See the
+ copyright.txt in the distribution for a full listing of
+ individual contributors. This is free software; you can
+ redistribute it and/or modify it under the terms of the GNU
+ Lesser General Public License as published by the Free Software
+ Foundation; either version 2.1 of the License, or (at your
+ option) any later version. This software is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ for more details. You should have received a copy of the GNU
+ Lesser General Public License along with this software; if not,
+ write to the Free Software Foundation, Inc., 51 Franklin St,
+ Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site:
+ http://www.fsf.org.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.richfaces.ui</groupId>
+ <artifactId>richfaces-ui-parent</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.richfaces.ui.fileupload</groupId>
+ <artifactId>richfaces-ui-fileupload-api</artifactId>
+ <name>Richfaces UI Components: FileUpload API</name>
+ <packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.richfaces.cdk</groupId>
+ <artifactId>maven-cdk-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <!-- runtime -->
+ <dependency>
+ <groupId>org.richfaces.core</groupId>
+ <artifactId>richfaces-core-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.richfaces.ui.common</groupId>
+ <artifactId>richfaces-ui-common-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
Copied: sandbox/trunk/ui/fileupload/api/src (from rev 19616, sandbox/trunk/ui/fileupload/src)
Modified: sandbox/trunk/ui/fileupload/api/src/main/java/org/richfaces/event/FileUploadListener.java
===================================================================
--- sandbox/trunk/ui/fileupload/src/main/java/org/richfaces/event/FileUploadListener.java 2010-10-20 14:34:47 UTC (rev 19616)
+++ sandbox/trunk/ui/fileupload/api/src/main/java/org/richfaces/event/FileUploadListener.java 2010-10-20 18:32:23 UTC (rev 19620)
@@ -25,5 +25,5 @@
public interface FileUploadListener extends FacesListener {
- public void processUpload(UploadEvent event);
+ public void processUpload(UploadEvent event);
}
Modified: sandbox/trunk/ui/fileupload/api/src/main/java/org/richfaces/event/UploadEvent.java
===================================================================
--- sandbox/trunk/ui/fileupload/src/main/java/org/richfaces/event/UploadEvent.java 2010-10-20 14:34:47 UTC (rev 19616)
+++ sandbox/trunk/ui/fileupload/api/src/main/java/org/richfaces/event/UploadEvent.java 2010-10-20 18:32:23 UTC (rev 19620)
@@ -28,51 +28,53 @@
import org.richfaces.model.UploadItem;
-public class UploadEvent extends FacesEvent{
-
- private static final long serialVersionUID = -7645197191376210068L;
- private List<UploadItem> uploadItems = null;
+public class UploadEvent extends FacesEvent {
- public UploadEvent(UIComponent component, List<UploadItem> uploadItems) {
- super(component);
- this.uploadItems = uploadItems;
- }
-
-
- public boolean isAppropriateListener(FacesListener listener) {
- return false;
- }
+ private static final long serialVersionUID = -7645197191376210068L;
+ private List<UploadItem> uploadItems = null;
-
- public void processListener(FacesListener listener) {
-
- }
+ public UploadEvent(UIComponent component, List<UploadItem> uploadItems) {
+ super(component);
+ this.uploadItems = uploadItems;
+ }
- /**Returns UploadItem instance.
- * Returns first element of list of UploadItems in case of multiple upload.
- * @return the uploadItem
- */
- public UploadItem getUploadItem() {
- if (uploadItems != null && uploadItems.size() > 0) {
- return uploadItems.get(0);
- }
- return null;
- }
-
- /**
- * Return list of UploadItems
- * @return the uploadItem
- * @since 3.2.2
- */
- public List<UploadItem> getUploadItems() {
- return uploadItems;
- }
-
- /** Return true if multiple files were uploaded with form
- * @return boolean
- * @since 3.2.2
- */
- public boolean isMultiUpload() {
- return (uploadItems != null && uploadItems.size() > 1);
- }
+ public boolean isAppropriateListener(FacesListener listener) {
+ return false;
+ }
+
+ public void processListener(FacesListener listener) {
+
+ }
+
+ /**
+ * Returns UploadItem instance. Returns first element of list of UploadItems in case of multiple upload.
+ *
+ * @return the uploadItem
+ */
+ public UploadItem getUploadItem() {
+ if (uploadItems != null && uploadItems.size() > 0) {
+ return uploadItems.get(0);
+ }
+ return null;
+ }
+
+ /**
+ * Return list of UploadItems
+ *
+ * @return the uploadItem
+ * @since 3.2.2
+ */
+ public List<UploadItem> getUploadItems() {
+ return uploadItems;
+ }
+
+ /**
+ * Return true if multiple files were uploaded with form
+ *
+ * @return boolean
+ * @since 3.2.2
+ */
+ public boolean isMultiUpload() {
+ return uploadItems != null && uploadItems.size() > 1;
+ }
}
Modified: sandbox/trunk/ui/fileupload/pom.xml
===================================================================
--- sandbox/trunk/ui/fileupload/pom.xml 2010-10-20 18:18:50 UTC (rev 19619)
+++ sandbox/trunk/ui/fileupload/pom.xml 2010-10-20 18:32:23 UTC (rev 19620)
@@ -35,6 +35,7 @@
<name>Richfaces UI Components: FileUpload Aggregator</name>
<modules>
+ <module>api</module>
<module>ui</module>
</modules>
</project>
Modified: sandbox/trunk/ui/fileupload/ui/pom.xml
===================================================================
--- sandbox/trunk/ui/fileupload/ui/pom.xml 2010-10-20 18:18:50 UTC (rev 19619)
+++ sandbox/trunk/ui/fileupload/ui/pom.xml 2010-10-20 18:32:23 UTC (rev 19620)
@@ -55,5 +55,10 @@
<groupId>org.richfaces.ui.common</groupId>
<artifactId>richfaces-ui-common-ui</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.richfaces.ui.fileupload</groupId>
+ <artifactId>richfaces-ui-fileupload-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
13 years, 8 months
JBoss Rich Faces SVN: r19618 - in branches/RF-8742: ui/validator/ui and 2 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2010-10-20 13:54:06 -0400 (Wed, 20 Oct 2010)
New Revision: 19618
Added:
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTestRule.java
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestData.java
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestDataHolder.java
Modified:
branches/RF-8742/bom/pom.xml
branches/RF-8742/ui/validator/ui/pom.xml
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTest.java
branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/DateTimeConverterTest.java
branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/test.xhtml
branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/testConverter.js
Log:
https://jira.jboss.org/browse/RF-9511
Modified: branches/RF-8742/bom/pom.xml
===================================================================
--- branches/RF-8742/bom/pom.xml 2010-10-20 15:39:47 UTC (rev 19617)
+++ branches/RF-8742/bom/pom.xml 2010-10-20 17:54:06 UTC (rev 19618)
@@ -194,11 +194,6 @@
<artifactId>cssparser</artifactId>
<version>0.9.5</version>
</dependency>
- <dependency>
- <groupId>org.testng</groupId>
- <artifactId>testng</artifactId>
- <version>5.14</version>
- </dependency>
<!-- Optional cache dependencies -->
<dependency>
Modified: branches/RF-8742/ui/validator/ui/pom.xml
===================================================================
--- branches/RF-8742/ui/validator/ui/pom.xml 2010-10-20 15:39:47 UTC (rev 19617)
+++ branches/RF-8742/ui/validator/ui/pom.xml 2010-10-20 17:54:06 UTC (rev 19618)
@@ -89,11 +89,6 @@
<version>1.0.5-SNAPSHOT</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.testng</groupId>
- <artifactId>testng</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
Modified: branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTest.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTest.java 2010-10-20 15:39:47 UTC (rev 19617)
+++ branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTest.java 2010-10-20 17:54:06 UTC (rev 19618)
@@ -40,17 +40,20 @@
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
+import junit.framework.AssertionFailedError;
import net.sourceforge.htmlunit.corejs.javascript.Scriptable;
import org.ajax4jsf.javascript.JSFunction;
import org.ajax4jsf.javascript.ScriptUtils;
import org.jboss.test.faces.htmlunit.HtmlUnitEnvironment;
-import org.testng.Assert;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeTest;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.google.common.base.Strings;
/**
* @author Nick Belaevski
@@ -68,8 +71,6 @@
private String clientConverterClassName;
- private String submittedValue;
-
private String convertedValueAsScript;
private String conversionErrorMessage;
@@ -112,10 +113,6 @@
attributes.put(name, value);
}
- public void setSubmittedValue(String submittedValue) {
- this.submittedValue = submittedValue;
- }
-
public String getConverterParametersString() {
return converterParametersString;
}
@@ -178,17 +175,24 @@
}
}
+ @Rule
+ public BaseConverterTestRule rule = new BaseConverterTestRule();
+
private TestBean testBean;
private HtmlUnitEnvironment environment;
private String converterScriptName;
+ private String submittedValue;
+
+ private String failureMessage;
+
public BaseConverterTest(String converterScriptName) {
this.converterScriptName = converterScriptName;
}
- @BeforeTest
+ @Before
public void setUp() throws Exception {
testBean = new TestBean();
@@ -208,14 +212,53 @@
environment.start();
}
- @AfterTest
+ @After
public void tearDown() throws Exception {
+ submittedValue = null;
+ failureMessage = null;
+
testBean = null;
environment.release();
environment = null;
}
+ private String formattedParametersData() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("TestData {");
+
+ sb.append("submittedValue=\"");
+ sb.append(submittedValue);
+ sb.append("\"");
+
+ if (!Strings.isNullOrEmpty(failureMessage)) {
+ sb.append(", failureMessage=\"");
+ sb.append(failureMessage);
+ sb.append("\"");
+ }
+
+ sb.append("}");
+
+ return sb.toString();
+ }
+
+ private void fail(String message) {
+ Assert.fail(MessageFormat.format("{0}: {1}", formattedParametersData(), message));
+ }
+
+ private void assertEquals(Object expected, Object actual) {
+ if (expected == null && actual == null) {
+ return;
+ }
+ if (expected != null && expected.equals(actual)) {
+ return;
+ }
+
+ throw new AssertionFailedError(MessageFormat.format("{0}: expected {1} but was {2}",
+ formattedParametersData(), expected, actual));
+ }
+
protected String serializeObjectToScript(Object object) {
if (object instanceof Date) {
Calendar calendar = Calendar.getInstance();
@@ -246,21 +289,25 @@
testBean.setAttribute(name, value);
}
- public void assertConversionOk(String submittedValue) throws Exception {
- testBean.setSubmittedValue(submittedValue);
-
+ public void setSubmittedValue(String submittedValue) {
+ this.submittedValue = submittedValue;
+ }
+
+ public void setFailureMessage(String failureMessage) {
+ this.failureMessage = failureMessage;
+ }
+
+ public void assertConversionOk() throws Exception {
HtmlPage page = environment.getPage("/test.jsf");
Assert.assertTrue(page.getWebClient().isJavaScriptEnabled());
ScriptResult conversionMessageResult = page.executeJavaScript("verifyConversion()");
if (!ScriptResult.isUndefined(conversionMessageResult)) {
- Assert.fail(conversionMessageResult.getJavaScriptResult().toString());
+ fail(conversionMessageResult.getJavaScriptResult().toString());
}
}
- public void assertConversionFailure(String submittedValue, String failureMessage) throws Exception {
- testBean.setSubmittedValue(submittedValue);
-
+ public void assertConversionFailure() throws Exception {
HtmlPage page = environment.getPage("/test.jsf");
Assert.assertNotNull(testBean.getConverterException());
@@ -270,12 +317,12 @@
ScriptResult conversionErrorResult = page.executeJavaScript("window.conversionError");
if (ScriptResult.isUndefined(conversionErrorResult)) {
- Assert.fail("converter has not thrown an error");
+ fail("converter has not thrown an error");
return;
}
Scriptable conversionError = (Scriptable) conversionErrorResult.getJavaScriptResult();
- Assert.assertEquals(conversionError.get("message", conversionError), failureMessage);
+ assertEquals(conversionError.get("message", conversionError), failureMessage);
}
Added: branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTestRule.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTestRule.java (rev 0)
+++ branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/BaseConverterTestRule.java 2010-10-20 17:54:06 UTC (rev 19618)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class BaseConverterTestRule implements MethodRule {
+
+ public Statement apply(final Statement base, FrameworkMethod method, final Object target) {
+ final List<TestData> testDataList = Lists.newArrayList();
+
+ TestDataHolder testDataHolder = method.getAnnotation(TestDataHolder.class);
+ if (testDataHolder != null) {
+ testDataList.addAll(Arrays.asList(testDataHolder.value()));
+ }
+
+ TestData testData = method.getAnnotation(TestData.class);
+ if (testData != null) {
+ testDataList.add(testData);
+ }
+
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ BaseConverterTest baseConverterTest = (BaseConverterTest) target;
+
+ for (TestData testData : testDataList) {
+ baseConverterTest.setSubmittedValue(testData.submittedValue());
+
+ if (!Strings.isNullOrEmpty(testData.failureMessage())) {
+ baseConverterTest.setFailureMessage(testData.failureMessage());
+ }
+
+ base.evaluate();
+ }
+ }
+ };
+ }
+
+}
Modified: branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/DateTimeConverterTest.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/DateTimeConverterTest.java 2010-10-20 15:39:47 UTC (rev 19617)
+++ branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/DateTimeConverterTest.java 2010-10-20 17:54:06 UTC (rev 19618)
@@ -23,10 +23,8 @@
import javax.faces.convert.DateTimeConverter;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import org.junit.Test;
-
/**
* @author Nick Belaevski
*
@@ -37,35 +35,28 @@
super("org/richfaces/convert/testConverter.js");
}
- @DataProvider(name = "successTest")
- public Object[][] getSuccessTestData() {
- return new Object[][]{
- {"17-10-2010"}
- };
- }
-
- @DataProvider(name = "failuresTest")
- public Object[][] getFailuresTestData() {
- return new Object[][]{
- {"10/17/2010", "Date should be in dd-MM-yyyy format"}
- };
- }
-
- @Test(dataProvider = "successTest")
- public void testSuccess(String submittedValue) throws Exception {
+ @Test
+ @TestDataHolder({
+ @TestData(submittedValue = "18-10-2010"),
+ @TestData(submittedValue = "17-10-2010"),
+ })
+ public void testSuccess() throws Exception {
setClientConverterClassName("org.rf.DateTimeConverter");
setConverterId(DateTimeConverter.CONVERTER_ID);
setAttribute("pattern", "dd-MM-yyyy");
- assertConversionOk(submittedValue);
+ assertConversionOk();
}
- @Test(dataProvider = "failuresTest")
- public void testFailures(String submittedValue, String conversionErrorMessage) throws Exception {
+ @Test
+ @TestDataHolder({
+ @TestData(submittedValue = "10/17/2010", failureMessage = TEST_COMPONENT_LABEL + ": '10/17/2010' could not be understood as a date.")
+ })
+ public void testFailures() throws Exception {
setClientConverterClassName("org.rf.DateTimeConverter");
setConverterId(DateTimeConverter.CONVERTER_ID);
setAttribute("pattern", "dd-MM-yyyy");
- assertConversionFailure(submittedValue, conversionErrorMessage);
+ assertConversionFailure();
}
}
Added: branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestData.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestData.java (rev 0)
+++ branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestData.java 2010-10-20 17:54:06 UTC (rev 19618)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Test data annotation for {@link BaseConverterTest}
+ * @author Nick Belaevski
+ *
+ */
+(a)Retention(RetentionPolicy.RUNTIME)
+(a)Target(ElementType.METHOD)
+public @interface TestData {
+
+ public String submittedValue();
+
+ public String failureMessage() default "";
+
+}
Added: branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestDataHolder.java
===================================================================
--- branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestDataHolder.java (rev 0)
+++ branches/RF-8742/ui/validator/ui/src/test/java/org/richfaces/convert/TestDataHolder.java 2010-10-20 17:54:06 UTC (rev 19618)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.convert;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Holder element for multiple {@link TestData} elements
+ * @author Nick Belaevski
+ *
+ */
+(a)Retention(RetentionPolicy.RUNTIME)
+(a)Target(ElementType.METHOD)
+public @interface TestDataHolder {
+
+ public TestData[] value();
+
+}
Modified: branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/test.xhtml
===================================================================
--- branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/test.xhtml 2010-10-20 15:39:47 UTC (rev 19617)
+++ branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/test.xhtml 2010-10-20 17:54:06 UTC (rev 19618)
@@ -12,7 +12,7 @@
<h:outputScript name="converter.js" />
</h:head>
<h:body>
- <script type="text/javascript">
+ <script type="text/javascript">/* <![CDATA[ */
window.expected = #{testBean.convertedValueAsScript};
try {
@@ -22,17 +22,29 @@
window.conversionError = e;
}
+ function equals(a, b) {
+ if (a === b) {
+ return true;
+ }
+
+ if (a instanceof Date && b instanceof Date) {
+ return a.getTime() === b.getTime();
+ }
+
+ //TODO - implement equality checking for all supported objects in a proper way
+ return false;
+ }
+
function verifyConversion() {
if (window.conversionError) {
return "conversion error caught: " + window.conversionError.message;
}
- //TODO - implement equality checking for all supported objects in a proper way
- if (window.actual != window.expected) {
+ if (!equals(window.actual, window.expected)) {
return "expected [" + window.expected + "] but was [" + window.actual + "]";
}
}
- </script>
+ /* ]]> */</script>
</h:body>
</f:view>
</html>
\ No newline at end of file
Modified: branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/testConverter.js
===================================================================
--- branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/testConverter.js 2010-10-20 15:39:47 UTC (rev 19617)
+++ branches/RF-8742/ui/validator/ui/src/test/resources/org/richfaces/convert/testConverter.js 2010-10-20 17:54:06 UTC (rev 19618)
@@ -1,6 +1,7 @@
window.org = {
rf: {
DateTimeConverter: function() {
+ return new Date(2010, 9, 18);
}
}
}
\ No newline at end of file
13 years, 8 months
JBoss Rich Faces SVN: r19617 - in sandbox/trunk/ui/fileupload/ui/src/main/java: org and 4 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: konstantin.mishin
Date: 2010-10-20 11:39:47 -0400 (Wed, 20 Oct 2010)
New Revision: 19617
Added:
sandbox/trunk/ui/fileupload/ui/src/main/java/org/
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/application/
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/application/FileUploadPhaselistener.java
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/exception/
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/exception/FileUploadException.java
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ByteSequenceMatcher.java
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/FileParam.java
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequest.java
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequestRegistry.java
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/Param.java
sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ValueParam.java
Log:
RF-9497
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/application/FileUploadPhaselistener.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/application/FileUploadPhaselistener.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/application/FileUploadPhaselistener.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,229 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.application;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.net.URLDecoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.richfaces.exception.FileUploadException;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+import org.richfaces.request.MultipartRequest;
+
+/**
+ * @author Konstantin Mishin
+ *
+ */
+public class FileUploadPhaselistener implements PhaseListener {
+
+ private static final long serialVersionUID = 138000954953175986L;
+
+ /** Multipart request start */
+ private static final String MULTIPART = "multipart/";
+
+ private static final Pattern AMPERSAND = Pattern.compile("&+");
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ /** Flag indicating whether a temporary file should be used to cache the uploaded file */
+ private boolean createTempFiles = false;
+
+ private String tempFilesDirectory;
+
+ /** The maximum size of a file upload request. 0 means no limit. */
+ private int maxRequestSize = 0;
+
+ public FileUploadPhaselistener() {
+ ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
+ String param = context.getInitParameter("createTempFiles");
+ if (param != null) {
+ this.createTempFiles = Boolean.parseBoolean(param);
+ } else {
+ this.createTempFiles = true;
+ }
+
+ this.tempFilesDirectory = context.getInitParameter("tempFilesDirectory");
+
+ param = context.getInitParameter("maxRequestSize");
+ if (param != null) {
+ this.maxRequestSize = Integer.parseInt(param);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
+ */
+ public void afterPhase(PhaseEvent event) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
+ */
+ public void beforePhase(PhaseEvent event) {
+ FacesContext facesContext = event.getFacesContext();
+ ExternalContext externalContext = facesContext.getExternalContext();
+ HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
+ Map<String, String> queryParamMap = parseQueryString(request.getQueryString());
+ String uid = queryParamMap.get(MultipartRequest.UPLOAD_FILES_ID);
+ if (uid != null && isMultipartRequest(request)) {
+ if (maxRequestSize != 0 && request.getContentLength() > maxRequestSize) {
+ boolean sendError = Boolean.parseBoolean(queryParamMap.get(MultipartRequest.SEND_HTTP_ERROR));
+ if (sendError) {
+ printResponse(facesContext, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, null);
+ } else {
+ printResponse(facesContext, HttpServletResponse.SC_OK,
+ "<html id=\"_richfaces_file_upload_size_restricted\"></html>");
+ }
+ } else if (!checkFileCount(request, queryParamMap.get("id"))) {
+ printResponse(facesContext, HttpServletResponse.SC_OK,
+ "<html id=\"_richfaces_file_upload_forbidden\"></html>");
+ } else {
+ MultipartRequest multipartRequest = new MultipartRequest(request, createTempFiles,
+ tempFilesDirectory, maxRequestSize, uid);
+ try {
+ multipartRequest.parseRequest();
+ if (!multipartRequest.isDone()) {
+ printResponse(facesContext, HttpServletResponse.SC_OK,
+ "<html id=\"_richfaces_file_upload_stopped\"></html>");
+ }
+ } catch (FileUploadException e) {
+ printResponse(facesContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, null);
+ throw e; //TODO remove it
+ } finally {
+ multipartRequest.clearRequestData();
+ }
+ }
+ }
+ }
+
+ private boolean checkFileCount(HttpServletRequest request, String idParameter) {
+ //TODO implement this method
+// HttpSession session = request.getSession(false);
+//
+// if (session != null) {
+// Map<String, Integer> map = (Map<String, Integer>) session
+// .getAttribute(FileUploadConstants.UPLOADED_COUNTER);
+//
+// if (map != null) {
+// String id = idParameter;
+// if (id != null) {
+// Integer i = map.get(id);
+// if (i != null && i == 0) {
+// return false;
+// }
+// }
+// }
+// }
+ return true;
+ }
+
+ private Map<String, String> parseQueryString(String queryString) {
+ if (queryString != null) {
+ Map<String, String> parameters = new HashMap<String, String>();
+ String[] nvPairs = AMPERSAND.split(queryString);
+ for (String nvPair : nvPairs) {
+ if (nvPair.length() == 0) {
+ continue;
+ }
+
+ int eqIdx = nvPair.indexOf('=');
+ if (eqIdx >= 0) {
+ try {
+ String name = URLDecoder.decode(nvPair.substring(0, eqIdx), "UTF-8");
+ if (!parameters.containsKey(name)) {
+ String value = URLDecoder.decode(nvPair.substring(eqIdx + 1), "UTF-8");
+
+ parameters.put(name, value);
+ }
+ } catch (UnsupportedEncodingException e) {
+ //log warning and skip this parameter
+ LOGGER.warn(e.getLocalizedMessage(), e);
+ }
+ }
+ }
+ return parameters;
+ } else {
+ return Collections.emptyMap();
+ }
+ }
+
+ private boolean isMultipartRequest(HttpServletRequest request) {
+ if (!"post".equals(request.getMethod().toLowerCase())) {
+ return false;
+ }
+
+ String contentType = request.getContentType();
+ if (contentType == null) {
+ return false;
+ }
+
+ if (contentType.toLowerCase().startsWith(MULTIPART)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private void printResponse(FacesContext facesContext, int statusCode, String message) {
+ facesContext.responseComplete();
+ ExternalContext externalContext = facesContext.getExternalContext();
+ externalContext.setResponseStatus(statusCode);
+ if (statusCode == HttpServletResponse.SC_OK) {
+ externalContext.setResponseContentType(MultipartRequest.TEXT_HTML);
+ try {
+ Writer writer = externalContext.getResponseOutputWriter();
+ writer.write(message);
+ writer.close();
+ } catch (IOException e) {
+ LOGGER.error(e);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.faces.event.PhaseListener#getPhaseId()
+ */
+ public PhaseId getPhaseId() {
+ return PhaseId.RESTORE_VIEW;
+ }
+
+}
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/exception/FileUploadException.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/exception/FileUploadException.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/exception/FileUploadException.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.exception;
+
+/**
+ * Thrown when an exception occurs while uploading a file.
+ *
+ */
+public class FileUploadException extends RuntimeException {
+
+ private static final long serialVersionUID = -3579917878909990838L;
+
+ public FileUploadException() {
+ this(null, null);
+ }
+
+ public FileUploadException(String message) {
+ this(message, null);
+ }
+
+ public FileUploadException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ByteSequenceMatcher.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ByteSequenceMatcher.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ByteSequenceMatcher.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,191 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ByteSequenceMatcher {
+
+ public interface BytesHandler {
+
+ void handle(byte[] bytes, int length) throws IOException;
+
+ }
+
+ private static final int ZERO_READS_NUMBER = 20;
+
+ private byte[] buffer;
+
+ private int readLength = 0;
+
+ private int zeroReadCounter = ZERO_READS_NUMBER;
+
+ private boolean bufferEOF = false;
+
+ private boolean isEOF = false;
+
+ private boolean isMatched = false;
+
+ private InputStream inputStream;
+
+ private BytesHandler bytesHandler;
+
+ public ByteSequenceMatcher(InputStream inputStream, int bufferSize) {
+ this.inputStream = inputStream;
+ this.buffer = new byte[bufferSize];
+ }
+
+ public BytesHandler getBytesHandler() {
+ return bytesHandler;
+ }
+
+ public void setBytesHandler(BytesHandler bytesHandler) {
+ this.bytesHandler = bytesHandler;
+ }
+
+ protected void prefillBuffer(int usedLength) throws IOException {
+ if (usedLength > readLength) {
+ throw new IllegalArgumentException();
+ }
+
+ if (usedLength != readLength && usedLength != 0) {
+ System.arraycopy(buffer, usedLength, buffer, 0, readLength - usedLength);
+ }
+
+ readLength -= usedLength;
+
+
+ while (!bufferEOF) {
+ int remaining = buffer.length - readLength;
+ if (remaining <= 0) {
+ break;
+ }
+ int read = inputStream.read(buffer, readLength, remaining);
+
+ if (read > 0) {
+ readLength += read;
+ } else if (read == 0) {
+ --zeroReadCounter;
+
+ if (zeroReadCounter == 0) {
+ throw new IllegalStateException("Maximum number of zero reads reached");
+ }
+ } else if (read < 0) {
+ bufferEOF = true;
+ }
+ }
+ }
+
+ private boolean match(int startOffset, byte[]... sequences) {
+ int index = startOffset;
+
+ for (byte[] bs : sequences) {
+ for (byte b : bs) {
+
+ if (index >= readLength) {
+ return false;
+ }
+
+ if (buffer[index] != b) {
+ return false;
+ }
+
+ index++;
+ }
+ }
+
+ return true;
+ }
+
+ public void findSequence(int limit, byte[]... sequences) throws IOException {
+ isMatched = false;
+
+ int userLimit = limit;
+ if (userLimit <= 0) {
+ userLimit = Integer.MAX_VALUE;
+ }
+
+ prefillBuffer(0);
+
+ int sequencesLength = 0;
+ for (byte[] bs : sequences) {
+ sequencesLength += bs.length;
+ }
+
+ int i = 0;
+
+ while (!isMatched && i <= readLength - sequencesLength) {
+ if (match(i, sequences)) {
+ isMatched = true;
+ bytesHandler.handle(buffer, i);
+ prefillBuffer(i + sequencesLength);
+ } else {
+ int sequenceLimit = readLength - sequencesLength + 1;
+ int realLimit;
+
+ if (sequenceLimit < userLimit) {
+ realLimit = sequenceLimit;
+ } else {
+ realLimit = userLimit;
+ }
+
+ if (realLimit > 0 && i == realLimit - 1) {
+ // report limit
+ bytesHandler.handle(buffer, realLimit);
+ prefillBuffer(realLimit);
+
+ i = 0;
+ } else {
+ i++;
+ }
+ }
+ }
+
+ flushUnmatchedBytes();
+
+ if (this.readLength == 0) {
+ this.isEOF = true;
+ }
+ }
+
+ private void flushUnmatchedBytes() throws IOException {
+ if (!isMatched) {
+ if (readLength > 0) {
+ bytesHandler.handle(buffer, readLength);
+ prefillBuffer(readLength);
+ }
+ }
+ }
+
+ public boolean isEOF() {
+ return isEOF;
+ }
+
+ public boolean isMatched() {
+ return isMatched;
+ }
+
+ public boolean isMatchedAndNotEOF() {
+ return isMatched() && !isEOF();
+ }
+}
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/FileParam.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/FileParam.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/FileParam.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,206 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.rmi.server.UID;
+
+import org.richfaces.exception.FileUploadException;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+
+class FileParam extends Param {
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ private String filename;
+ private String contentType;
+ private int fileSize;
+
+ private ByteArrayOutputStream bOut = null;
+ private FileOutputStream fOut = null;
+ private File tempFile = null;
+
+ public FileParam(String name) {
+ super(name);
+ }
+
+ public Object getFile() {
+ if (null != tempFile) {
+ return tempFile;
+ } else if (null != bOut) {
+ return bOut.toByteArray();
+ }
+ return null;
+ }
+
+ public String getFilename() {
+ return filename;
+ }
+
+ public void setFilename(String filename) {
+ this.filename = filename;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public int getFileSize() {
+ return fileSize;
+ }
+
+ public File createTempFile(String tempFilesDirectory) {
+ try {
+ File dir = null;
+ if (tempFilesDirectory != null) {
+ dir = new File(tempFilesDirectory);
+ }
+ tempFile = File.createTempFile(new UID().toString().replace(":", "-"), ".upload", dir);
+ fOut = new FileOutputStream(tempFile);
+ } catch (IOException ex) {
+ if (fOut != null) {
+ try {
+ fOut.close();
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+
+ throw new FileUploadException("Could not create temporary file");
+ }
+ return tempFile;
+ }
+
+ public void deleteFile() {
+ try {
+ if (fOut != null) {
+ fOut.close();
+ }
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+ } catch (Exception e) {
+ throw new FileUploadException("Could not delete temporary file");
+ }
+ }
+
+ public byte[] getData() {
+ if (bOut != null) {
+ return bOut.toByteArray();
+ } else if (tempFile != null) {
+ if (tempFile.exists()) {
+ FileInputStream fIn = null;
+ try {
+ long fileLength = tempFile.length();
+ if (fileLength > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("File content is too long to be allocated as byte[]");
+ }
+
+ fIn = new FileInputStream(tempFile);
+
+ byte[] fileData = new byte[(int) fileLength];
+ int totalRead = 0;
+ int read = 0;
+ do {
+ read = fIn.read(fileData, totalRead, fileData.length - totalRead);
+ if (read > 0) {
+ totalRead += read;
+ }
+ } while (read > 0);
+
+ return fileData;
+ } catch (IOException ex) { /* too bad? */
+ LOGGER.error(ex.getMessage(), ex);
+ } finally {
+ if (fIn != null) {
+ try {
+ fIn.close();
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public InputStream getInputStream() {
+ if (bOut != null) {
+ return new ByteArrayInputStream(bOut.toByteArray());
+ } else if (tempFile != null) {
+ try {
+ return new FileInputStream(tempFile) {
+ @Override
+ public void close() throws IOException {
+ super.close();
+ tempFile.delete();
+ }
+ };
+ } catch (FileNotFoundException ex) {
+ LOGGER.error(ex.getMessage(), ex);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public void complete() throws IOException {
+ if (fOut != null) {
+ try {
+ fOut.close();
+ } catch (IOException ex) {
+ LOGGER.error(ex.getMessage(), ex);
+ }
+ fOut = null;
+ }
+ }
+
+ public void handle(byte[] bytes, int length) throws IOException {
+ // read += length;
+ if (fOut != null) {
+ fOut.write(bytes, 0, length);
+ fOut.flush();
+ } else {
+ if (bOut == null) {
+ bOut = new ByteArrayOutputStream();
+ }
+ bOut.write(bytes, 0, length);
+ }
+
+ fileSize += length;
+ }
+}
\ No newline at end of file
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequest.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequest.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequest.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,746 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.richfaces.exception.FileUploadException;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+import org.richfaces.model.UploadItem;
+import org.richfaces.request.ByteSequenceMatcher.BytesHandler;
+
+public class MultipartRequest extends HttpServletRequestWrapper {
+
+ /**
+ * Request parameter that allow to send HTTP error instead of html message
+ */
+ public static final String SEND_HTTP_ERROR = "_richfaces_send_http_error";
+
+ /** Request parameter that indicates if multipart request forced by rich file upload component */
+ public static final String UPLOAD_FILES_ID = "_richfaces_upload_uid";
+
+ public static final String TEXT_HTML = "text/html";
+
+ private static final BytesHandler NOOP_HANDLER = new BytesHandler() {
+ public void handle(byte[] bytes, int length) {
+ // do nothing
+ }
+ };
+
+ /** Session bean name where request size will be stored */
+ private static final String REQUEST_SIZE_BEAN_NAME = "_richfaces_request_size";
+
+ /** Session bean name where progress bar's percent map will be stored */
+ private static final String PERCENT_BEAN_NAME = "_richfaces_upload_percents";
+
+ /** Session bean name where stop keys will be stored */
+ private static final String REQUEST_KEYS_BEAN_NAME = "_richfaces_request_keys";
+
+ private static final String PARAM_NAME = "name";
+ private static final String PARAM_FILENAME = "filename";
+ private static final String PARAM_CONTENT_TYPE = "Content-Type";
+
+ private static final int BUFFER_SIZE = 2048;
+ private static final int CHUNK_SIZE = 1024;
+ private static final int MAX_HEADER_SIZE = 32768;
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ private static final byte CR = 0x0d;
+ private static final byte LF = 0x0a;
+ private static final byte[] CR_LF = {CR, LF};
+ private static final byte[] HYPHENS = {0x2d, 0x2d}; // '--'
+
+ private static final Pattern PARAM_VALUE_PATTERN = Pattern.compile("^\\s*([^\\s=]+)\\s*[=:]\\s*(.+)\\s*$");
+
+ private static final Pattern FILE_NAME_PATTERN = Pattern.compile(".*filename=\"(.*)\"");
+
+ private boolean createTempFiles;
+
+ private String tempFilesDirectory;
+
+ private String uid;
+
+ private String encoding = null;
+
+ private Integer contentLength = 0;
+
+ private int bytesRead = 0;
+
+ // we shouldn't allow to stop until request reaches PhaseListener because of portlets
+ private volatile boolean canStop = false;
+
+ private Map<String, Param> parameters = null;
+
+ private Map<String, Object> percentMap = null;
+
+ private Map<String, Integer> requestSizeMap = null;
+
+ private Map<String, String> requestKeysMap = null;
+
+ private String requestKey = null;
+
+ private MultipartRequestRegistry requestRegistry;
+
+ private List<String> keys = new ArrayList<String>();
+
+ private byte[] boundaryMarker;
+
+ private ByteSequenceMatcher sequenceMatcher;
+
+ private boolean shouldStop = false;
+ private boolean canceled;
+
+ private boolean initialized = false;
+
+ private HeadersHandler headersHandler = null;
+
+ public MultipartRequest(HttpServletRequest request, boolean createTempFiles, String tempFilesDirectory,
+ int maxRequestSize, String uid) {
+ super(request);
+ this.createTempFiles = createTempFiles;
+ this.tempFilesDirectory = tempFilesDirectory;
+ this.uid = uid;
+
+ String contentLengthStr = request.getHeader("Content-Length");
+ this.contentLength = Integer.parseInt(contentLengthStr);
+ if (contentLengthStr != null && maxRequestSize > 0 && contentLength > maxRequestSize) {
+ // TODO : we should make decision if can generate exception in this
+ // place
+ // throw new FileUploadException(
+ // "Multipart request is larger than allowed size");
+ }
+ }
+
+ private class ControlledProgressInputStream extends FilterInputStream {
+
+ protected ControlledProgressInputStream(InputStream in) {
+ super(in);
+ }
+
+ @Override
+ public int read() throws IOException {
+ int read = super.read();
+ if (read >= 0) {
+ bytesRead++;
+ fillProgressInfo();
+ }
+ return read;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ int read = super.read(b);
+ if (read > 0) {
+ bytesRead += read;
+ fillProgressInfo();
+ }
+ return read;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ int read = super.read(b, off, len);
+ if (read > 0) {
+ bytesRead += read;
+ fillProgressInfo();
+ }
+ return read;
+ }
+ }
+
+ private String decodeFileName(String name) {
+ String fileName = null;
+
+ try {
+ if (getRequest().getParameter(SEND_HTTP_ERROR) != null) {
+ fileName = new String(name.getBytes(encoding), "UTF-8");
+ } else {
+ StringBuffer buffer = new StringBuffer();
+ String[] codes = name.split(";");
+ if (codes != null) {
+ for (String code : codes) {
+ if (code.startsWith("&")) {
+ String sCode = code.replaceAll("[&#]*", "");
+ Integer iCode = Integer.parseInt(sCode);
+ buffer.append(Character.toChars(iCode));
+ } else {
+ buffer.append(code);
+ }
+ }
+ fileName = buffer.toString();
+ }
+ }
+ } catch (Exception e) {
+ fileName = name;
+ }
+
+ return fileName;
+ }
+
+ public void cancel() {
+ this.canceled = true;
+
+ if (parameters != null) {
+ Iterator<Param> it = parameters.values().iterator();
+ while (it.hasNext()) {
+ Param p = it.next();
+ if (p instanceof FileParam) {
+ ((FileParam) p).deleteFile();
+ }
+ }
+ }
+ }
+
+ private void readNext() throws IOException {
+ Param p = readHeader();
+ if (p != null) {
+ try {
+ readData(p);
+ } finally {
+ try {
+ p.complete();
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ private Param createParam(Map<String, String> headers) {
+ Param param = null;
+ String paramName = headers.get(PARAM_NAME);
+ if (paramName != null) {
+ if (headers.containsKey(PARAM_FILENAME)) {
+ FileParam fp = new FileParam(paramName);
+ this.keys.add(paramName);
+
+ if (createTempFiles) {
+ fp.createTempFile(tempFilesDirectory);
+ }
+ fp.setContentType(headers.get(PARAM_CONTENT_TYPE));
+ fp.setFilename(decodeFileName(headers.get(PARAM_FILENAME)));
+ param = fp;
+ } else {
+ if (parameters.containsKey(paramName)) {
+ param = parameters.get(paramName);
+ } else {
+ param = new ValueParam(paramName, encoding);
+ }
+ }
+
+ if (!parameters.containsKey(paramName)) {
+ parameters.put(paramName, param);
+ }
+ }
+
+ return param;
+ }
+
+ private class HeadersHandler implements BytesHandler {
+
+ private ByteArrayOutputStream baos = new ByteArrayOutputStream(BUFFER_SIZE);
+
+ public void handle(byte[] bytes, int length) throws IOException {
+ if (length != 0) {
+ if (baos.size() + length > MAX_HEADER_SIZE) {
+ throw new IOException("Header section is too big");
+ }
+
+ baos.write(bytes, 0, length);
+ }
+ }
+
+ public boolean dataEquals(byte[] bytes) {
+ return (baos.size() == bytes.length) && Arrays.equals(HYPHENS, baos.toByteArray());
+ }
+
+ public String asString() throws UnsupportedEncodingException {
+ if (encoding != null) {
+ return baos.toString(encoding);
+ } else {
+ return baos.toString();
+ }
+ }
+
+ public void reset() {
+ baos.reset();
+ }
+
+ }
+
+ private Param readHeader() throws IOException {
+ if (sequenceMatcher.isEOF()) {
+ return null;
+ }
+
+ if (headersHandler == null) {
+ headersHandler = new HeadersHandler();
+ } else {
+ headersHandler.reset();
+ }
+
+ sequenceMatcher.setBytesHandler(headersHandler);
+ sequenceMatcher.findSequence(-1, CR_LF);
+
+ if (sequenceMatcher.isMatchedAndNotEOF() && !headersHandler.dataEquals(HYPHENS)) {
+ headersHandler.reset();
+
+ sequenceMatcher.findSequence(-1, CR_LF, CR_LF);
+
+ if (!sequenceMatcher.isMatchedAndNotEOF()) {
+ throw new IOException("Request header cannot be read");
+ }
+
+ String headersString = headersHandler.asString();
+ Map<String, String> headers = new HashMap<String, String>();
+ String[] split = headersString.split("\r\n");
+ for (String headerString : split) {
+ parseParams(headerString, "; ", headers);
+ }
+
+ return createParam(headers);
+ }
+
+ return null;
+ }
+
+ private void readProlog() throws IOException {
+ sequenceMatcher.setBytesHandler(NOOP_HANDLER);
+ sequenceMatcher.findSequence(-1, HYPHENS, boundaryMarker);
+ if (!sequenceMatcher.isMatchedAndNotEOF()) {
+ throw new IOException("Request prolog cannot be read");
+ }
+ }
+
+ private void readData(final Param param) throws IOException {
+ sequenceMatcher.setBytesHandler(param);
+ sequenceMatcher.findSequence(CHUNK_SIZE, CR_LF, HYPHENS, boundaryMarker);
+ if (!this.sequenceMatcher.isMatchedAndNotEOF()) {
+ throw new IOException("Request data cannot be read");
+ }
+ }
+
+ private void initialize() throws IOException {
+ if (!initialized) {
+ initialized = true;
+
+ this.boundaryMarker = getBoundaryMarker(super.getContentType());
+ if (this.boundaryMarker == null) {
+ throw new FileUploadException("The request was rejected because " + "no multipart boundary was found");
+ }
+
+ if (HYPHENS.length + boundaryMarker.length + CHUNK_SIZE + CR_LF.length > BUFFER_SIZE) {
+ throw new FileUploadException("Boundary marker is too long");
+ }
+
+ this.encoding = getCharacterEncoding();
+
+ this.parameters = new HashMap<String, Param>();
+
+ InputStream input = new ControlledProgressInputStream(getInputStream());
+
+ this.sequenceMatcher = new ByteSequenceMatcher(input, BUFFER_SIZE);
+
+ setupProgressData();
+
+ readProlog();
+ }
+ }
+
+ public void parseRequest() {
+ canStop = true;
+
+ setupProgressData();
+
+ try {
+ initialize();
+
+ while (!sequenceMatcher.isEOF()) {
+ readNext();
+ }
+ } catch (IOException e) {
+ this.cancel();
+
+ if (!this.shouldStop) {
+ throw new FileUploadException("IO Error parsing multipart request", e);
+ }
+ } finally {
+ canStop = false;
+ }
+ }
+
+ public static MultipartRequest lookupRequest(FacesContext context, String uploadId) {
+ Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
+ @SuppressWarnings("unchecked")
+ Map<String, String> requestKeys = (Map<String, String>) sessionMap.get(REQUEST_KEYS_BEAN_NAME);
+ if (requestKeys != null) {
+ String requestKey = requestKeys.get(uploadId);
+ if (requestKey != null) {
+ MultipartRequestRegistry requestRegistry = MultipartRequestRegistry.getInstance(context);
+ if (requestRegistry != null) {
+ MultipartRequest request = requestRegistry.getRequest(requestKey);
+ if (request != null) {
+ return request;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void setupProgressData() {
+ if (percentMap == null || requestSizeMap == null || requestKeysMap == null) {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ if (facesContext != null) {
+ ExternalContext externalContext = facesContext.getExternalContext();
+ if (externalContext != null) {
+ Map<String, Object> sessionMap = externalContext.getSessionMap();
+ if (sessionMap != null) {
+ String uploadId = getUploadId();
+
+ synchronized (sessionMap) {
+ if (percentMap == null) {
+ percentMap = (Map<String, Object>) sessionMap.get(PERCENT_BEAN_NAME);
+ if (percentMap == null) {
+ percentMap = new ConcurrentHashMap<String, Object>();
+ sessionMap.put(PERCENT_BEAN_NAME, percentMap);
+ }
+ }
+
+ if (requestSizeMap == null) {
+ requestSizeMap = (Map<String, Integer>) sessionMap.get(REQUEST_SIZE_BEAN_NAME);
+ if (requestSizeMap == null) {
+ requestSizeMap = new ConcurrentHashMap<String, Integer>();
+ sessionMap.put(REQUEST_SIZE_BEAN_NAME, requestSizeMap);
+ }
+ }
+
+ if (requestKeysMap == null) {
+ requestKeysMap = (Map<String, String>) sessionMap.get(REQUEST_KEYS_BEAN_NAME);
+ if (requestKeysMap == null) {
+ requestKeysMap = new ConcurrentHashMap<String, String>();
+ sessionMap.put(REQUEST_KEYS_BEAN_NAME, requestKeysMap);
+ }
+
+ }
+ }
+
+ percentMap.put(uploadId, Double.valueOf(0));
+
+ requestSizeMap.put(uploadId, getSize());
+
+ requestRegistry = MultipartRequestRegistry.getInstance(facesContext);
+ requestKey = requestRegistry.registerRequest(this);
+ requestKeysMap.put(uploadId, requestKey);
+
+ }
+ }
+ }
+ }
+ }
+
+ private void fillProgressInfo() {
+ setupProgressData();
+
+ if (percentMap != null) {
+ Double percent = (Double) (100.0 * this.bytesRead / this.contentLength);
+ percentMap.put(uid, percent);
+ // this.percent = percent;
+ }
+ }
+
+ private byte[] getBoundaryMarker(String contentType) {
+ Map<String, String> params = parseParams(contentType, ";");
+ String boundaryStr = (String) params.get("boundary");
+
+ if (boundaryStr == null) {
+ return null;
+ }
+
+ try {
+ return boundaryStr.getBytes("ISO-8859-1");
+ } catch (UnsupportedEncodingException e) {
+ return boundaryStr.getBytes();
+ }
+ }
+
+ private Map<String, String> parseParams(String paramStr, String separator) {
+ Map<String, String> paramMap = new HashMap<String, String>();
+ parseParams(paramStr, separator, paramMap);
+ return paramMap;
+ }
+
+ private void parseParams(String paramStr, String separator, Map<String, String> paramMap) {
+ String[] parts = paramStr.split(separator);
+
+ for (String part : parts) {
+ Matcher m = PARAM_VALUE_PATTERN.matcher(part);
+ if (m.matches()) {
+ String key = m.group(1);
+ String value = m.group(2);
+
+ // Strip double quotes
+ if (value.startsWith("\"") && value.endsWith("\"")) {
+ value = value.substring(1, value.length() - 1);
+ }
+ if (!"filename".equals(key)) {
+ paramMap.put(key, value);
+ } else {
+ paramMap.put(key, parseFileName(paramStr));
+ }
+ }
+ }
+ }
+
+ private String parseFileName(String parseStr) {
+ Matcher m = FILE_NAME_PATTERN.matcher(parseStr);
+ if (m.matches()) {
+ String name = m.group(1);
+ if (name.startsWith("&")) {
+ return decodeFileName(name);
+ } else {
+ return name;
+ }
+ }
+ return null;
+ }
+
+ private Param getParam(String name) {
+ Param param = null;
+ if (parameters != null) {
+ param = parameters.get(name);
+ }
+
+ if (param == null) {
+ if (!canceled) {
+ try {
+ initialize();
+
+ while (param == null && !sequenceMatcher.isEOF()) {
+ readNext();
+ param = parameters.get(name);
+ }
+ } catch (IOException e) {
+ this.cancel();
+ throw new FileUploadException("IO Error parsing multipart request", e);
+ }
+ }
+ }
+
+ return param;
+ }
+
+ public Integer getSize() {
+ return contentLength;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Enumeration getParameterNames() {
+ if (parameters == null) {
+ parseRequest();
+ }
+
+ return Collections.enumeration(parameters.keySet());
+ }
+
+ public byte[] getFileBytes(String name) {
+ Param p = getParam(name);
+ return (p != null && p instanceof FileParam) ? ((FileParam) p).getData() : null;
+ }
+
+ public InputStream getFileInputStream(String name) {
+ Param p = getParam(name);
+ return (p != null && p instanceof FileParam) ? ((FileParam) p).getInputStream() : null;
+ }
+
+ public String getFileContentType(String name) {
+ Param p = getParam(name);
+ return (p != null && p instanceof FileParam) ? ((FileParam) p).getContentType() : null;
+ }
+
+ public Object getFile(String name) {
+ Param p = getParam(name);
+ return (p != null && p instanceof FileParam) ? ((FileParam) p).getFile() : null;
+ }
+
+ public String getFileName(String name) {
+ Param p = getParam(name);
+ return (p != null && p instanceof FileParam) ? ((FileParam) p).getFilename() : null;
+ }
+
+ public int getFileSize(String name) {
+ Param p = getParam(name);
+ return (p != null && p instanceof FileParam) ? ((FileParam) p).getFileSize() : -1;
+ }
+
+ @Override
+ public String getParameter(String name) {
+ Param p = getParam(name);
+ if (p != null && p instanceof ValueParam) {
+ ValueParam vp = (ValueParam) p;
+ if (vp.getValue() instanceof String) {
+ return (String) vp.getValue();
+ }
+ } else if (p != null && p instanceof FileParam) {
+ return "---BINARY DATA---";
+ } else {
+ return super.getParameter(name);
+ }
+
+ return null;
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ parseRequest();
+
+ Param p = getParam(name);
+ if (p != null && p instanceof ValueParam) {
+ ValueParam vp = (ValueParam) p;
+ if (vp.getValue() instanceof List<?>) {
+ @SuppressWarnings("unchecked")
+ List<String> vals = (List<String>) vp.getValue();
+ String[] values = new String[vals.size()];
+ vals.toArray(values);
+ return values;
+ } else {
+ return new String[] {(String) vp.getValue() };
+ }
+ } else {
+ return super.getParameterValues(name);
+ }
+ }
+
+ @Override
+ public Map<String, Object> getParameterMap() {
+ if (parameters == null) {
+ parseRequest();
+ }
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> params = new HashMap<String, Object>(super.getParameterMap());
+
+ for (String name : parameters.keySet()) {
+ Param p = parameters.get(name);
+ if (p instanceof ValueParam) {
+ ValueParam vp = (ValueParam) p;
+ if (vp.getValue() instanceof String) {
+ params.put(name, vp.getValue());
+ } else if (vp.getValue() instanceof List) {
+ params.put(name, getParameterValues(name));
+ }
+ }
+ }
+
+ return params;
+ }
+
+ public List<UploadItem> getUploadItems() {
+ List<UploadItem> uploadItems = new ArrayList<UploadItem>();
+ for (String k : keys) {
+ uploadItems.add(new UploadItem(getFileName(k), getFileSize(k), getFileContentType(k), getFile(k)));
+ }
+ return uploadItems;
+ }
+
+ public boolean isFormUpload() {
+ return "_richfaces_form_upload".equals(uid);
+ }
+
+ @Override
+ public String getHeader(String name) {
+ if (!"Accept".equals(name)) {
+ return super.getHeader(name);
+ } else {
+ return TEXT_HTML;
+ }
+ }
+
+ public void stop() {
+ if (canStop) {
+ shouldStop = true;
+ }
+ }
+
+ public boolean isStopped() {
+ return this.shouldStop;
+ }
+
+ public boolean isDone() {
+ return !(this.shouldStop && (this.canceled || this.contentLength != null
+ && this.contentLength.intValue() != this.bytesRead));
+ }
+
+ @Override
+ public String getContentType() {
+ return "application/x-www-form-urlencoded";
+ }
+
+ protected String getUploadId() {
+ return uid;
+ }
+
+ public void clearRequestData() {
+ String uploadId = getUploadId();
+
+ if (percentMap != null) {
+ percentMap.remove(uploadId);
+ }
+
+ if (requestSizeMap != null) {
+ requestSizeMap.remove(uploadId);
+ }
+
+ if (requestKeysMap != null) {
+ requestKeysMap.remove(uploadId);
+ }
+
+ if (requestRegistry != null) {
+ requestRegistry.removeRequest(requestKey);
+ }
+ }
+}
\ No newline at end of file
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequestRegistry.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequestRegistry.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/MultipartRequestRegistry.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.faces.context.FacesContext;
+
+final class MultipartRequestRegistry {
+
+ private static final String REGISTRY_ATTRIBUTE_NAME = MultipartRequestRegistry.class.getName();
+
+ private AtomicInteger atomicInteger = new AtomicInteger(0);
+
+ private String registryId = UUID.randomUUID().toString();
+
+ private Map<String, MultipartRequest> requestsMap = new ConcurrentHashMap<String, MultipartRequest>();
+
+ private MultipartRequestRegistry() {
+
+ }
+
+ public static MultipartRequestRegistry getInstance(FacesContext context) {
+ Map<String, Object> applicationMap = context.getExternalContext().getApplicationMap();
+ // MultipartRequestRegistry requestRegistry = (MultipartRequestRegistry) applicationMap
+ // .get(REGISTRY_ATTRIBUTE_NAME);
+ // if (requestRegistry == null) {
+ synchronized (applicationMap) {
+ MultipartRequestRegistry requestRegistry = (MultipartRequestRegistry) applicationMap
+ .get(REGISTRY_ATTRIBUTE_NAME);
+ if (requestRegistry == null) {
+ requestRegistry = new MultipartRequestRegistry();
+ applicationMap.put(REGISTRY_ATTRIBUTE_NAME, requestRegistry);
+ }
+ // }
+ return requestRegistry;
+ }
+ }
+
+ public String registerRequest(MultipartRequest request) {
+ String key = registryId + ":" + atomicInteger.incrementAndGet();
+ requestsMap.put(key, request);
+
+ return key;
+ }
+
+ public void removeRequest(String key) {
+ requestsMap.remove(key);
+ }
+
+ public MultipartRequest getRequest(String key) {
+ return requestsMap.get(key);
+ }
+}
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/Param.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/Param.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/Param.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+
+import org.richfaces.request.ByteSequenceMatcher.BytesHandler;
+
+abstract class Param implements BytesHandler {
+ private String name;
+
+ public Param(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public abstract void complete() throws IOException;
+}
\ No newline at end of file
Added: sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ValueParam.java
===================================================================
--- sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ValueParam.java (rev 0)
+++ sandbox/trunk/ui/fileupload/ui/src/main/java/org/richfaces/request/ValueParam.java 2010-10-20 15:39:47 UTC (rev 19617)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+class ValueParam extends Param {
+
+ private Object value = null;
+ private ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ private String encoding;
+
+ public ValueParam(String name, String encoding) {
+ super(name);
+ this.encoding = encoding;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void complete() throws IOException {
+ String val = this.encoding == null ? new String(buf.toByteArray()) : new String(buf.toByteArray(),
+ this.encoding);
+ if (value == null) {
+ value = val;
+ } else {
+ if (!(value instanceof List<?>)) {
+ List<String> v = new ArrayList<String>();
+ v.add((String) value);
+ value = v;
+ }
+
+ ((List<String>) value).add(val);
+ }
+ buf.reset();
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void handle(byte[] bytes, int length) throws IOException {
+ // read += length;
+ buf.write(bytes, 0, length);
+ }
+}
\ No newline at end of file
13 years, 8 months