JBoss Rich Faces SVN: r4764 - in branches/3.1.x/test-applications/jsp/src/main/webapp: ContextMenu and 3 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: ayanul
Date: 2007-12-12 06:00:23 -0500 (Wed, 12 Dec 2007)
New Revision: 4764
Modified:
branches/3.1.x/test-applications/jsp/src/main/webapp/Calendar/CalendarProperty.jsp
branches/3.1.x/test-applications/jsp/src/main/webapp/ContextMenu/ContextMenuProperty.jsp
branches/3.1.x/test-applications/jsp/src/main/webapp/Insert/InsertProperty.jsp
branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttle.jsp
branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttleProperty.jsp
branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingList.jsp
branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingListStraightforward.jsp
Log:
Modified: branches/3.1.x/test-applications/jsp/src/main/webapp/Calendar/CalendarProperty.jsp
===================================================================
--- branches/3.1.x/test-applications/jsp/src/main/webapp/Calendar/CalendarProperty.jsp 2007-12-12 10:49:42 UTC (rev 4763)
+++ branches/3.1.x/test-applications/jsp/src/main/webapp/Calendar/CalendarProperty.jsp 2007-12-12 11:00:23 UTC (rev 4764)
@@ -42,13 +42,15 @@
</h:selectOneRadio>
<h:outputText value="Select Date Pattern:" />
- <h:selectOneMenu value="MMM d, yyyy" onchange="submit()">
+ <h:selectOneMenu value="#{calendarBean.pattern}" onchange="submit()">
<f:selectItem itemLabel="d/M/yy" itemValue="d/M/yy" />
<f:selectItem itemLabel="dd/M/yy" itemValue="dd/M/yy" />
<f:selectItem itemLabel="d/MMM/y" itemValue="d/MMM/y" />
<f:selectItem itemLabel="dd.MM.yyyy" itemValue="dd.MM.yyyy" />
<f:selectItem itemLabel="MMM d, yyyy" itemValue="MMM d, yyyy" />
<f:selectItem itemLabel="dd-MM-yyyy" itemValue="dd-MM-yyyy" />
+ <f:selectItem itemLabel="dd/M/yy HH:mm" itemValue="dd/M/yy HH:mm"/>
+ <f:selectItem itemLabel="MMM d, yyyy h:mm a" itemValue="MMM d, yyyy h:mm a"/>
</h:selectOneMenu>
<h:outputText value="Preload date range begin(d.m.y)" />
Modified: branches/3.1.x/test-applications/jsp/src/main/webapp/ContextMenu/ContextMenuProperty.jsp
===================================================================
--- branches/3.1.x/test-applications/jsp/src/main/webapp/ContextMenu/ContextMenuProperty.jsp 2007-12-12 10:49:42 UTC (rev 4763)
+++ branches/3.1.x/test-applications/jsp/src/main/webapp/ContextMenu/ContextMenuProperty.jsp 2007-12-12 11:00:23 UTC (rev 4764)
@@ -6,7 +6,6 @@
<f:subview id="contextMenuPropertySubviewID">
<a4j:commandButton value="reRender" reRender="cmInfoID"></a4j:commandButton>
- <a4j:commandButton action="submit();" value="a4j submit();"></a4j:commandButton>
<a4j:commandButton action="submit();" immediate="true" value="immediate submit(); (a4j)"></a4j:commandButton>
<h:commandButton action="submit();" value="submit();" />
<h:commandButton action="submit();" immediate="true" value="immediate submit();" />
Modified: branches/3.1.x/test-applications/jsp/src/main/webapp/Insert/InsertProperty.jsp
===================================================================
--- branches/3.1.x/test-applications/jsp/src/main/webapp/Insert/InsertProperty.jsp 2007-12-12 10:49:42 UTC (rev 4763)
+++ branches/3.1.x/test-applications/jsp/src/main/webapp/Insert/InsertProperty.jsp 2007-12-12 11:00:23 UTC (rev 4764)
@@ -30,7 +30,7 @@
<f:selectItem itemValue="/Insert/Insert.xhtml" itemLabel="XHTML" />
<f:selectItem itemValue="/Insert/src/test.lzx" itemLabel="LZX" />
<f:selectItem itemValue="/Insert/src/test.cpp" itemLabel="CPP,CXX" />
- <a4j:support event="onclick" action="submit();" reRender="panelID,insertID"></a4j:support>
+ <a4j:support event="onclick" reRender="panelID,insertID"></a4j:support>
</h:selectOneMenu>
<h:outputText value="Rendered" />
Modified: branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttle.jsp
===================================================================
--- branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttle.jsp 2007-12-12 10:49:42 UTC (rev 4763)
+++ branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttle.jsp 2007-12-12 11:00:23 UTC (rev 4764)
@@ -63,7 +63,7 @@
<f:selectItem itemLabel="select2" itemValue="select2" />
<f:selectItem itemLabel="select3" itemValue="select3" />
<f:selectItem itemLabel="select4" itemValue="select4" />
- <a4j:support event="onclick" action="submit();"></a4j:support>
+ <a4j:support event="onclick" reRender="listShuttleID"></a4j:support>
</h:selectOneMenu>
</h:column>
Modified: branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttleProperty.jsp
===================================================================
--- branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttleProperty.jsp 2007-12-12 10:49:42 UTC (rev 4763)
+++ branches/3.1.x/test-applications/jsp/src/main/webapp/ListShuttle/ListShuttleProperty.jsp 2007-12-12 11:00:23 UTC (rev 4764)
@@ -8,7 +8,6 @@
<h:column></h:column>
<h:panelGroup>
<a4j:commandButton value="reRender" reRender="listShuttleID"></a4j:commandButton>
- <a4j:commandButton action="submit();" value="a4j submit();"></a4j:commandButton>
<a4j:commandButton action="submit();" immediate="true" value="immediate submit(); (a4j)"></a4j:commandButton>
<h:commandButton action="submit();" value="submit();" />
<h:commandButton action="submit();" immediate="true" value="immediate submit();" />
Modified: branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingList.jsp
===================================================================
--- branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingList.jsp 2007-12-12 10:49:42 UTC (rev 4763)
+++ branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingList.jsp 2007-12-12 11:00:23 UTC (rev 4764)
@@ -59,14 +59,14 @@
<f:facet name="header">
<h:outputText value="Link" />
</f:facet>
- <a4j:commandLink action="#{orderingList.clAction}" onclick="submit()" value="#{item.str1} submit()" reRender="orderingListID"></a4j:commandLink>
+ <a4j:commandLink action="#{orderingList.clAction}" value="#{item.str1} submit()" reRender="orderingListID"></a4j:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="select" />
</f:facet>
- <h:selectOneMenu value="#{item.str2}">
+ <h:selectOneMenu value="#{item.str2}" reRender="orderingListID">
<f:selectItem itemLabel="select0" itemValue="select0" />
<f:selectItem itemLabel="select1" itemValue="select1" />
<f:selectItem itemLabel="select2" itemValue="select2" />
Modified: branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingListStraightforward.jsp
===================================================================
--- branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingListStraightforward.jsp 2007-12-12 10:49:42 UTC (rev 4763)
+++ branches/3.1.x/test-applications/jsp/src/main/webapp/OrderingList/OrderingListStraightforward.jsp 2007-12-12 11:00:23 UTC (rev 4764)
@@ -104,7 +104,6 @@
<h:panelGroup>
<a4j:commandButton value="reRender" reRender="orderingListID"></a4j:commandButton>
- <a4j:commandButton action="submit();" value="a4j submit();"></a4j:commandButton>
<a4j:commandButton action="submit();" immediate="true" value="immediate submit(); (a4j)"></a4j:commandButton>
<h:commandButton action="submit();" value="submit();" />
<h:commandButton action="submit();" immediate="true" value="immediate submit();" />
18 years, 4 months
JBoss Rich Faces SVN: r4763 - branches/3.1.x/docs/userguide/en/src/main/docbook/included.
by richfaces-svn-commits@lists.jboss.org
Author: vkorluzhenko
Date: 2007-12-12 05:49:42 -0500 (Wed, 12 Dec 2007)
New Revision: 4763
Modified:
branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml
Log:
http://jira.jboss.com/jira/browse/RF-1196 - timing description
Modified: branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml 2007-12-12 09:49:53 UTC (rev 4762)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml 2007-12-12 10:49:42 UTC (rev 4763)
@@ -292,7 +292,7 @@
<para>This is a result:</para>
<figure>
- <title>Using facets </title>
+ <title>Facets usage</title>
<mediaobject>
<imageobject>
@@ -311,8 +311,26 @@
</emphasis> facet, {nextYearControl}, {previousYearControl} are absent. Numbers of weeks are
red colored.</para>
- <para>It's possible to program events for calendar from JavaScript code. A simplest example of
- usage JavaScript API is placed below:</para>
+ <para>The <emphasis role="bold">
+ <property><rich:calendar></property>
+ </emphasis> component allows to show and manage time. It's necessary to define time
+ in a pattern (for example, it could be defined as "d/M/yy HH:mm"). Then after
+ you choose some data in the calendar, it becomes possible to manage time for this date. For time editing
+ it's necessary to click on its field (see a picture below). To clean the field click
+ on the "Clean".</para>
+
+ <figure>
+ <title>Timing</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/calendar4.png"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>It's possible to program events for calendar from JavaScript code. A simplest
+ example of usage JavaScript API is placed below:</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
@@ -324,7 +342,7 @@
</a4j:form>
...
]]></programlisting>
-
+
<para>Also the discussion about this problem can be found on the <ulink
url="http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4078301#..."
>RichFaces Users Forum</ulink>.</para>
@@ -382,8 +400,8 @@
<row>
<entry>selectDate(date)</entry>
- <entry>Selects the date specified. If the date isn't in current month - performs
- request to select</entry>
+ <entry>Selects the date specified. If the date isn't in current month -
+ performs request to select</entry>
</row>
<row>
18 years, 4 months
JBoss Rich Faces SVN: r4762 - branches/3.1.x/docs/userguide/en/src/main/docbook/included.
by richfaces-svn-commits@lists.jboss.org
Author: artdaw
Date: 2007-12-12 04:49:53 -0500 (Wed, 12 Dec 2007)
New Revision: 4762
Modified:
branches/3.1.x/docs/userguide/en/src/main/docbook/included/listShuttle.xml
Log:
http://jira.jboss.com/jira/browse/RF-1174 - edit Skin Parameters Redefinition; Definition of Custom Style Classes
Modified: branches/3.1.x/docs/userguide/en/src/main/docbook/included/listShuttle.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/listShuttle.xml 2007-12-12 09:13:25 UTC (rev 4761)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/listShuttle.xml 2007-12-12 09:49:53 UTC (rev 4762)
@@ -436,7 +436,7 @@
<entry>background-color</entry>
</row>
<row>
- <entry>panelBorderColor</entry>
+ <entry>tableBorderColor</entry>
<entry>border-color</entry>
</row>
<row>
@@ -474,6 +474,24 @@
</table>
<table>
+ <title>Skin parameters redefinition for a selected rows in the source and target lists</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Skin parameters</entry>
+ <entry>CSS properties</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>additionalBackgroundColor</entry>
+ <entry>background-color</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table>
<title>Skin parameters redefinition for a header cell</title>
<tgroup cols="2">
<thead>
@@ -499,10 +517,10 @@
<entry>headerSizeFont</entry>
<entry>font-size</entry>
</row>
- <row>
+ <!--row>
<entry>headerWeightFont</entry>
<entry>font-weight</entry>
- </row>
+ </row-->
<row>
<entry>tableBorderWidth</entry>
<entry>border-width</entry>
@@ -549,6 +567,8 @@
</tgroup>
</table>
+
+
<table>
<title>Skin parameters redefinition for an active cell</title>
<tgroup cols="2">
@@ -582,7 +602,7 @@
</thead>
<tbody>
<row>
- <entry>panelBorderColor</entry>
+ <entry>tableBorderColor</entry>
<entry>border-color</entry>
</row>
</tbody>
@@ -870,11 +890,11 @@
<entry>Defines styles for a row in a source list</entry>
</row>
<row>
- <entry>rich-shuttle-row-source-selected</entry>
+ <entry>rich-shuttle-source-row-selected</entry>
<entry>Defines styles for a selected row in a source list</entry>
</row>
<row>
- <entry>rich-shuttle-row-source-active</entry>
+ <entry>rich-shuttle-source-row-active</entry>
<entry>Defines styles for an active row in a source list</entry>
</row>
</tbody>
@@ -895,11 +915,11 @@
<entry>Defines styles for a row in a target list</entry>
</row>
<row>
- <entry>rich-shuttle-row-target-selected</entry>
+ <entry>rich-shuttle-target-row-selected</entry>
<entry>Defines styles for a selected row in a target list</entry>
</row>
<row>
- <entry>rich-shuttle-row-target-active</entry>
+ <entry>rich-shuttle-target-row-active</entry>
<entry>Defines styles for an active row in a target list</entry>
</row>
</tbody>
18 years, 4 months
JBoss Rich Faces SVN: r4761 - branches/3.1.x/ui/listShuttle/src/main/config/component.
by richfaces-svn-commits@lists.jboss.org
Author: artdaw
Date: 2007-12-12 04:13:25 -0500 (Wed, 12 Dec 2007)
New Revision: 4761
Modified:
branches/3.1.x/ui/listShuttle/src/main/config/component/listShuttle.xml
Log:
http://jira.jboss.com/jira/browse/RF-1174 - add attributes to the table of attributes
Modified: branches/3.1.x/ui/listShuttle/src/main/config/component/listShuttle.xml
===================================================================
--- branches/3.1.x/ui/listShuttle/src/main/config/component/listShuttle.xml 2007-12-12 08:38:57 UTC (rev 4760)
+++ branches/3.1.x/ui/listShuttle/src/main/config/component/listShuttle.xml 2007-12-12 09:13:25 UTC (rev 4761)
@@ -25,7 +25,13 @@
&ui_component_attributes;
&html_style_attributes;
&ui_data_attributes;
-
+ <property>
+ <name>columnClasses</name>
+ <classname>java.lang.String</classname>
+ <description>
+ Comma-separated list of CSS classes for columns
+ </description>
+ </property>
<property hidden="true" exist="true">
<name>value</name>
</property>
@@ -41,10 +47,10 @@
<property elonly="true">
<name>validator</name>
<classname>javax.faces.el.MethodBinding</classname>
- <methodargs>java.lang.Object.class</methodargs>
<description>
MethodBinding pointing at a method that is called during Process Validations phase of the request processing lifecycle, to validate the current value of this component
</description>
+ <methodargs>java.lang.Object.class</methodargs>
</property>
<property hidden="true">
<name>value</name>
@@ -125,11 +131,15 @@
</description>
<defaultvalue>true</defaultvalue>
</property>
-
+ <property>
+ <name>onlistchanged</name>
+ <classname>java.lang.String</classname>
+ <description>A JavaScript event handler called on a list change operation</description>
+ </property>
<property>
<name>onorderchanged</name>
<classname>java.lang.String</classname>
- <description>HTML: script expression; called after ordering action</description>
+ <description>A JavaScript event handler called on an order operation</description>
</property>
<property>
@@ -223,8 +233,8 @@
<property attachedstate="true">
<name>valueChangeListener</name>
<classname>javax.faces.el.MethodBinding</classname>
+ <description>Listener for value changes</description>
<methodargs>javax.faces.event.ValueChangeEvent.class</methodargs>
- <description>Listener for value changes</description>
</property>
<property>
<name>immediate</name>
@@ -260,6 +270,14 @@
<description>Defines strings that are updated after an Ajax request</description>
</property>
<property>
+ <name>rowClasses</name>
+ <classname>java.lang.String</classname>
+ <description>
+ CSS class for a row
+ </description>
+ <defaultvalue><![CDATA[""]]></defaultvalue>
+ </property>
+ <property>
<name>rowKey</name>
<classname>java.lang.Object</classname>
<description>RowKey is a representation of an identifier for a specific data row</description>
@@ -304,20 +322,5 @@
If "true", dragging between lists realized by click
</description>
</property>
-
- <property>
- <name>rowClasses</name>
- <classname>java.lang.String</classname>
- </property>
-
- <property>
- <name>columnClasses</name>
- <classname>java.lang.String</classname>
- </property>
-
- <property>
- <name>onlistchanged</name>
- <classname>java.lang.String</classname>
- </property>
</component>
</components>
18 years, 4 months
JBoss Rich Faces SVN: r4759 - branches/3.1.x/docs/userguide/en/src/main/resources/images.
by richfaces-svn-commits@lists.jboss.org
Author: artdaw
Date: 2007-12-12 03:06:14 -0500 (Wed, 12 Dec 2007)
New Revision: 4759
Modified:
branches/3.1.x/docs/userguide/en/src/main/resources/images/listShuttle_classes_s.png
branches/3.1.x/docs/userguide/en/src/main/resources/images/listShuttle_classes_t.png
Log:
http://jira.jboss.com/jira/browse/RF-1174 - edit screenshots
Modified: branches/3.1.x/docs/userguide/en/src/main/resources/images/listShuttle_classes_s.png
===================================================================
(Binary files differ)
Modified: branches/3.1.x/docs/userguide/en/src/main/resources/images/listShuttle_classes_t.png
===================================================================
(Binary files differ)
18 years, 4 months
JBoss Rich Faces SVN: r4758 - branches/3.1.x/ui/orderingList/src/main/java/org/richfaces/renderkit.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2007-12-11 19:47:35 -0500 (Tue, 11 Dec 2007)
New Revision: 4758
Modified:
branches/3.1.x/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java
Log:
blank submits ignored for OL & LS
Modified: branches/3.1.x/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java
===================================================================
--- branches/3.1.x/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java 2007-12-12 00:47:30 UTC (rev 4757)
+++ branches/3.1.x/ui/orderingList/src/main/java/org/richfaces/renderkit/OrderingListRendererBase.java 2007-12-12 00:47:35 UTC (rev 4758)
@@ -1,7 +1,6 @@
package org.richfaces.renderkit;
import java.io.IOException;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -256,8 +255,6 @@
map.put(key, value);
}
orderingList.setSubmittedString(map, selection, activeItem);
- } else {
- orderingList.setSubmittedString(new HashMap(0), null, null);
}
}
}
18 years, 5 months
JBoss Rich Faces SVN: r4757 - branches/3.1.x/ui/listShuttle/src/main/java/org/richfaces/renderkit.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2007-12-11 19:47:30 -0500 (Tue, 11 Dec 2007)
New Revision: 4757
Modified:
branches/3.1.x/ui/listShuttle/src/main/java/org/richfaces/renderkit/ListShuttleRendererBase.java
Log:
blank submits ignored for OL & LS
Modified: branches/3.1.x/ui/listShuttle/src/main/java/org/richfaces/renderkit/ListShuttleRendererBase.java
===================================================================
--- branches/3.1.x/ui/listShuttle/src/main/java/org/richfaces/renderkit/ListShuttleRendererBase.java 2007-12-12 00:45:15 UTC (rev 4756)
+++ branches/3.1.x/ui/listShuttle/src/main/java/org/richfaces/renderkit/ListShuttleRendererBase.java 2007-12-12 00:47:30 UTC (rev 4757)
@@ -345,8 +345,6 @@
map.put(key, value);
}
listShuttle.setSubmittedStrings(map, sourceSelection, targetSelection, activeItem);
- } else {
- listShuttle.setSubmittedStrings(new HashMap(0), null, null, null);
}
}
18 years, 5 months
JBoss Rich Faces SVN: r4756 - in branches/3.1.x: docs/faq and 5 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: alexsmirnov
Date: 2007-12-11 19:45:15 -0500 (Tue, 11 Dec 2007)
New Revision: 4756
Added:
branches/3.1.x/docs/faq/
branches/3.1.x/docs/highlight/
branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.desc.xml
branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.xml
branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.desc.xml
branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.xml
Removed:
branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.desc.xml
branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.xml
branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.desc.xml
branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.xml
Modified:
branches/3.1.x/docs/faq/en/pom.xml
branches/3.1.x/docs/faq/pom.xml
branches/3.1.x/docs/highlight/pom.xml
branches/3.1.x/docs/pom.xml
branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml
branches/3.1.x/docs/xslt/en/src/main/xslt/f.xsl
branches/3.1.x/ui/assembly/pom.xml
Log:
Merged "faq" and "highlight" documentation modules from a trunk.
Fix filenames registry for a tags descriptions.
Copied: branches/3.1.x/docs/faq (from rev 4755, trunk/docs/faq)
Modified: branches/3.1.x/docs/faq/en/pom.xml
===================================================================
--- trunk/docs/faq/en/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/faq/en/pom.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -5,12 +5,12 @@
<parent>
<groupId>org.richfaces.docs</groupId>
<artifactId>faq</artifactId>
- <version>3.2.0-SNAPSHOT</version>
+ <version>3.1.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.richfaces.docs.faq</groupId>
<artifactId>${translation}</artifactId>
- <version>3.2.0-SNAPSHOT</version>
+ <version>3.1.3-SNAPSHOT</version>
<packaging>jdocbook</packaging>
<name>Richfaces Manual (${translation})</name>
Modified: branches/3.1.x/docs/faq/pom.xml
===================================================================
--- trunk/docs/faq/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/faq/pom.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -2,13 +2,13 @@
<parent>
<artifactId>docs</artifactId>
<groupId>org.richfaces</groupId>
- <version>3.2.0-SNAPSHOT</version>
+ <version>3.1.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces.docs</groupId>
<artifactId>faq</artifactId>
<packaging>pom</packaging>
- <version>3.2.0-SNAPSHOT</version>
+ <version>3.1.3-SNAPSHOT</version>
<name>FAQ</name>
<description>Frequently asked questions</description>
<pluginRepositories>
Copied: branches/3.1.x/docs/highlight (from rev 4755, trunk/docs/highlight)
Modified: branches/3.1.x/docs/highlight/pom.xml
===================================================================
--- trunk/docs/highlight/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/highlight/pom.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -5,12 +5,12 @@
<parent>
<artifactId>docs</artifactId>
<groupId>org.richfaces</groupId>
- <version>3.2.0-SNAPSHOT</version>
+ <version>3.1.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces.docs</groupId>
<artifactId>highlight</artifactId>
- <version>3.2.0-SNAPSHOT</version>
+ <version>3.1.3-SNAPSHOT</version>
<name>RichFaces Code Highlighting</name>
<dependencyManagement>
Modified: branches/3.1.x/docs/pom.xml
===================================================================
--- branches/3.1.x/docs/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/pom.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -34,17 +34,17 @@
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
- <id>maven2-snapshots.exadel.com</id>
- <name>Exadel Repository for Maven Snapshots</name>
- <url>http://maven.exadel.com/</url>
+ <id>maven2-snapshots.jboss.org</id>
+ <name>Jboss Repository for Maven Snapshots</name>
+ <url>http://snapshots.jboss.org/maven2</url>
<layout>default</layout>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
- <id>maven2-snapshots.exadel.com</id>
+ <id>maven2-snapshots.jboss.org</id>
<name>Exadel Repository for Maven Snapshots</name>
- <url>http://maven.exadel.com/</url>
+ <url>http://snapshots.jboss.org/maven2</url>
<releases>
<enabled>false</enabled>
</releases>
@@ -78,10 +78,8 @@
<modules>
<module>xslt</module>
- <!--
- <module>docbook</module>
- <module>maven-docbook-plugin</module>
- -->
+ <module>highlight</module>
+ <module>faq</module>
<module>userguide</module>
</modules>
</project>
\ No newline at end of file
Modified: branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/calendar.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -98,38 +98,64 @@
</mediaobject>
</figure>
<para>Usage <emphasis>
- <property>"currentDate"</property>
- </emphasis> attribute isn't available in the popup
- mode.</para>
+ <property>"currentDate"</property>
+ </emphasis> attribute isn't available in the popup mode.</para>
<para>The <emphasis role="bold">
<property><rich:calendar></property>
- </emphasis> component ables to render pages of days in two modes. Switching mode
- could be defined with the <emphasis>
+ </emphasis> component ables to render pages of days in two modes. Switching mode could be
+ defined with the <emphasis>
<property>"mode"</property>
- </emphasis> attribute with two possible parameters: Ajax and Client. Default value is set to
- "Client".</para>
+ </emphasis> attribute with two possible parameters: ajax and client. Default value is set to
+ the "client".</para>
<itemizedlist>
<listitem>
<para>Ajax</para>
</listitem>
</itemizedlist>
-
- <para>Calendar requests portions of data from Data Model for a page rendering. If
- <emphasis>
+ <para>Calendar requests portions of data from Data Model for a page rendering. If <emphasis>
<property>"dataModel"</property>
- </emphasis> attribute has <property>"null"</property> value, data requests are
- not sent. In this case the "Ajax" mode is equal to the
- "Client" mode. </para>
-
+ </emphasis> attribute has <property>"null"</property> value, data requests
+ are not sent. In this case the "ajax" mode is equal to the
+ "client". </para>
<itemizedlist>
<listitem>
<para>Client</para>
</listitem>
</itemizedlist>
-
- <para>Calendar loads an initial portion of data in a specified range and use this data to
- render months. Additional data requests are not sent.</para>
-
+ <para>Calendar loads an initial portion of data in a specified range and use this data to render
+ months. Additional data requests are not sent.</para>
+ <note>
+ <title>Note:</title><emphasis>
+ <property>"preloadDateRangeBegin"</property>
+ </emphasis> and <emphasis>
+ <property>"preloadDateRangeEnd"</property>
+ </emphasis> attributes was designed only for the
+ <property>"client"</property> mode to load some data initially.</note>
+ <para><emphasis>
+ <property>"ondataselect"</property>
+ </emphasis> attribute is used to define an event that is triggered before date selection.</para>
+ <para><emphasis>
+ <property>"ondateselected"</property>
+ </emphasis> attribute is used to define an event that is triggered after date selection. </para>
+ <para>For example, to fire some event after date selection you should use <emphasis role="bold">
+ <property><a4j:support></property>
+ </emphasis>. And it should be bound to <emphasis>
+ <property>"ondateselected"</property>
+ </emphasis> event as it's shown in the example below:</para>
+ <programlisting role="XML"><![CDATA[...
+ <rich:calendar id="date" value="#{bean.dateTest}">
+ <a4j:support event="ondateselected" reRender="mainTable"/>
+ </rich:calendar>
+...]]></programlisting>
+ <para><emphasis>
+ <property>"ondataselect"</property>
+ </emphasis> could be used for possibility of date selection canceling. See an example below:</para>
+ <programlisting role="XML"><![CDATA[...
+ <rich:calendar id="date" value="#{bean.dateTest}" ondateselect="if (!confirm('Are you sure to change date?')){return false;}"/>
+...]]></programlisting>
+ <para>How to use these attributes see also on the <ulink
+ url="http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4092275#..."
+ >RichFaces Users Forum</ulink>.</para>
<para>There are three button-related attributes:</para>
<itemizedlist>
<listitem>
@@ -186,97 +212,139 @@
</emphasis> attribute is set to "bottom-left".</para>
<para>The <emphasis role="bold">
<property><rich:calendar></property>
- </emphasis> component provides to use <emphasis>
+ </emphasis> component allows to use <emphasis>
<property>"header"</property>
- </emphasis> facet. For example, you can add following scrolling elements to the facet:
- {currentMonthControl}, {nextMonthControl}, {nextYearControl}, {previousYearControl},
- {previousMonthControl}.</para>
- <para>Simple example is placed below.</para>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
- <f:facet name="header">
- <f:verbatim>
- {previousMonthControl} | {nextMonthControl}
- </f:verbatim>
- </f:facet>
-...]]></programlisting>
- <para>It's possible to define <emphasis>
+ </emphasis>, <emphasis>
<property>"footer"</property>
- </emphasis> facet and replace in it (in the same way how it was described for <emphasis>
- <property>"header"</property>
- </emphasis> facet), for example, following today bar elements: {todayControl},
- {selectedDateControl}, {helpControl}.</para>
- <para>Also you can use <emphasis>
+ </emphasis>, <emphasis>
<property>"optionalHeader"</property>
- </emphasis> and <emphasis>
+ </emphasis>, <emphasis>
<property>"optionalFooter"</property>
- </emphasis> facets. These facets define the top and the bottom elements of the calendar. They
- are not attached to the control parts of the calendar. You can replace in them any content.</para>
- <para>The <emphasis role="bold">
- <property><rich:calendar></property>
- </emphasis> component provides the possibility to use <emphasis>
+ </emphasis> facets. The following elements are available in these facets:
+ {currentMonthControl}, {nextMonthControl}, {nextYearControl}, {previousYearControl},
+ {previousMonthControl}, {todayControl}, {selectedDateControl}. These elements could be used
+ for labels output.</para>
+ <para>Also you can use <emphasis>
<property>"weekNumber"</property>
- </emphasis> and <emphasis>
+ </emphasis> facet with available {weekNumber}, {elementId} elements and <emphasis>
<property>"weekDay"</property>
- </emphasis> facets. For example, using these facets you can change text style for the elements
- of the calendar as it's shown in the example below:</para>
+ </emphasis> facet with {weekDayLabel}, {weekDayLabelShort}, {weekDayNumber}, {isWeekend},
+ {elementId} elements. {weekNumber}, {weekDayLabel}, {weekDayLabelShort}, {weekDayNumber}
+ elements could be used for labels output, {isWeekend}, {elementId} - for additional processing
+ in JavaScript code.</para>
+ <para>These elements are shown on the picture below.</para>
+
+ <figure>
+ <title>Available elements</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/calendar3.png"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>Simple example of usage is placed below.</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<programlisting role="XML"><![CDATA[...
- <f:facet name="weekNumber">
- <h:outputText style="font-weight: bold;" value="{weekNumber}" />
- </f:facet>
+<!--Styles for cells -->
+<style>
+ .width100{
+ width:100%;
+ }
+ .talign{
+ text-align:center;
+ }
+</style>
+
+<rich:calendar id="myCalendar" popup="true" locale="#{calendarBean.locale}" value="#{bean.date}"
+ preloadRangeBegin="#{bean.date}" preloadRangeEnd="#{bean.date}" selectedDate="#{bean.date}" cellWidth="40px" cellHeight="40px">
+
+<!-- Customization with usage of facets and accessible elements -->
+ <f:facet name="header">
+ <h:panelGrid columns="2" width="100%" columnClasses="width100, fake">
+ <h:outputText value="{selectedDateControl}" />
+ <h:outputText value="{todayControl}" style="font-weight:bold; text-align:left"/>
+ </h:panelGrid>
+ </f:facet>
+ <f:facet name="weekDay">
+ <h:panelGroup style="width:60px; overflow:hidden;" layout="block">
+ <h:outputText value="{weekDayLabelShort}"/>
+ </h:panelGroup>
+ </f:facet>
+ <f:facet name="weekNumber">
+ <h:panelGroup>
+ <h:outputText value="{weekNumber}" style="color:red"/>
+ </h:panelGroup>
+ </f:facet>
+ <f:facet name="footer">
+ <h:panelGrid columns="3" width="100%" columnClasses="fake, width100 talign">
+ <h:outputText value="{previousMonthControl}" style="font-weight:bold;"/>
+ <h:outputText value="{currentMonthControl}" style="font-weight:bold;"/>
+ <h:outputText value="{nextMonthControl}" style="font-weight:bold;"/>
+ </h:panelGrid>
+ </f:facet>
+ <h:outputText value="{day}"></h:outputText>
+</rich:calendar>
...]]></programlisting>
- <para>The example of using JavaScript API is placed below:</para>
+ <para>This is a result:</para>
+ <figure>
+ <title>Using facets </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/calendar2.png"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>As it's shown on the picture above {selectedDateControl}, {todayControl} elements
+ are placed in the <emphasis>
+ <property>"header"</property>
+ </emphasis> facet, {previousMonthControl}, {currentMonthControl}, {nextMonthControl} - in the <emphasis>
+ <property>"footer"</property>
+ </emphasis> facet, {weekDayLabelShort} - in the <emphasis>
+ <property>"weekDay"</property>
+ </emphasis> facet, {nextYearControl}, {previousYearControl} are absent. Numbers of weeks are
+ red colored.</para>
+
+ <para>It's possible to program events for calendar from JavaScript code. A simplest example of
+ usage JavaScript API is placed below:</para>
<para>
<emphasis role="bold">Example:</emphasis>
</para>
<programlisting role="XML"><![CDATA[...
<a4j:form id="form">
- <h:panelGroup id="test" columns="2" style="width: 300px">
- <h:selectBooleanCheckbox value="#{bean.check}">
- <a4j:support event="onchange" reRender="test" />
- <f:selectItem itemValue="true" itemLabel="Show" />
- <f:selectItem itemValue="false" itemLabel="Hide" />
- </h:selectBooleanCheckbox>
- <rich:calendar popup="true"
- rendered="#{!bean.check}" value="#{bean.date}" id="c"/>
- <a onclick="$('form:c').component.doExpand()" href="#">Show</a>
- </h:panelGroup>
+ <rich:calendar popup="true" rendered="#{!bean.check}" value="#{bean.date}" id="c"/>
+ <!--The link which is used to call a calendar popup externally-->
+ <a onclick="$('form:c').component.doExpand()" href="#">Show</a>
</a4j:form>
...
]]></programlisting>
-
+
<para>Also the discussion about this problem can be found on the <ulink
url="http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4078301#..."
>RichFaces Users Forum</ulink>.</para>
-
<para>The <emphasis role="bold">
<property><rich:calendar></property>
</emphasis> component provides the possibility to use a special Data Model to define data for
element rendering. Data Model includes two major interfaces: </para>
-
<itemizedlist>
<listitem>CalendarDataModel</listitem>
<listitem>CalendarDataModelItem</listitem>
</itemizedlist>
-
<para><property>CalendarDataModel</property> provides the following function:</para>
<itemizedlist>
<listitem>CalendarDataModelItem[] getData(Date[]);</listitem>
</itemizedlist>
-
<para>This method is called when it's necessary to represent the next block of
CalendarDataItems. It happens during navigation to the next (previous) month or in any other
case when calendar renders. This method is called in <emphasis>
<property>"Ajax"</property>
</emphasis> mode when the calendar renders a new page. </para>
-
<para><property>CalendarDataModelItem</property> provides the following function:</para>
<itemizedlist>
<listitem>Date getDate() - returns date from the item. Default implementation returns date.</listitem>
@@ -293,7 +361,6 @@
object. It could be used in the custom date representation on the calendar (inside the
custom facet).</listitem>
</itemizedlist>
-
</section>
<section>
@@ -315,14 +382,14 @@
<row>
<entry>selectDate(date)</entry>
- <entry>Select the date specified. If the date isn't in current month - performs
+ <entry>Selects the date specified. If the date isn't in current month - performs
request to select</entry>
</row>
<row>
<entry>isDateEnabled(date)</entry>
- <entry>Check if given date is selectable</entry>
+ <entry>Checks if given date is selectable</entry>
</row>
<row>
@@ -352,55 +419,55 @@
<row>
<entry>nextMonth()</entry>
- <entry>Navigate to next month</entry>
+ <entry>Navigates to next month</entry>
</row>
<row>
<entry>nextYear()</entry>
- <entry>Navigate to next year</entry>
+ <entry>Navigates to next year</entry>
</row>
<row>
<entry>prevMonth()</entry>
- <entry>Navigate to previous month </entry>
+ <entry>Navigates to previous month </entry>
</row>
<row>
<entry>prevYear()</entry>
- <entry>Navigate to previous year</entry>
+ <entry>Navigates to previous year</entry>
</row>
<row>
<entry>today()</entry>
- <entry>Select today date</entry>
+ <entry>Selects today date</entry>
</row>
<row>
<entry>getSelectedDate()</entry>
- <entry>Return currently selected date</entry>
+ <entry>Returns currently selected date</entry>
</row>
<row>
<entry>Object getData()</entry>
- <entry>Return additional data for the date</entry>
+ <entry>Returns additional data for the date</entry>
</row>
<row>
<entry>enable()</entry>
- <entry>enables calendar</entry>
+ <entry>Enables calendar</entry>
</row>
<row>
<entry>disable()</entry>
- <entry>disables calendar</entry>
+ <entry>Disables calendar</entry>
</row>
<row>
@@ -418,13 +485,13 @@
<row>
<entry>doCollapse()</entry>
- <entry>Collapse calendar element</entry>
+ <entry>Collapses calendar element</entry>
</row>
<row>
<entry>doExpand()</entry>
- <entry>Expand calendar element</entry>
+ <entry>Expands calendar element</entry>
</row>
</tbody>
</tgroup>
@@ -941,11 +1008,15 @@
</thead>
<tbody>
+ <row>
+ <entry>rich-calendar-popup</entry>
+ <entry>Defines styles for a popup element</entry>
+ </row>
<row>
<entry>rich-calendar-exterior</entry>
- <entry>Defines styles for a popup element</entry>
+ <entry>Defines styles for a popup element exterior</entry>
</row>
<row>
@@ -997,7 +1068,7 @@
</row>
<row>
- <entry>rich-calendar-current</entry>
+ <entry>rich-calendar-toolfooter</entry>
<entry>Defines styles for a today control date</entry>
</row>
@@ -1006,14 +1077,14 @@
</tgroup>
</table>
- <para>In order to redefine the style for all <emphasis role="bold">
+ <para>In order to redefine styles for all <emphasis role="bold">
<property><rich:calendar></property>
</emphasis> components on a page using CSS, it's enough to create classes with the
- same names and define the necessary properties in them.</para>
+ same names and define necessary properties in them.</para>
- <para>To change the style of particular <emphasis role="bold">
+ <para>To change styles of particular <emphasis role="bold">
<property><rich:calendar></property>
- </emphasis> components define your own style classes in the corresponding <emphasis
+ </emphasis> components, define your own style classes in the corresponding <emphasis
role="bold">
<property><rich:calendar></property>
</emphasis>attributes.</para>
Deleted: branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.desc.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.desc.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.desc.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<section>
-<sectioninfo>
-<keywordset>
-<keyword>suggestionBox</keyword>
-</keywordset>
-</sectioninfo>
-<section>
-<title>Description</title>
- <para>The component adds on-keypress suggestions capabilities to any input text component
- (like <emphasis role="bold"><property><h:inputText></property></emphasis>). When a key
- is pressed in the field Ajax request is sent to the server. When the suggestion action returns a
- list of possible values, it pop ups them inside the
- <emphasis role="bold"><property><div></property></emphasis> element bellow the input.</para>
- <figure>
- <title>SuggestionBox component</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/suggestionbox1.gif"/>
- </imageobject>
- </mediaobject>
- </figure>
- </section>
- <section>
- <title>Key Features</title>
- <itemizedlist>
- <listitem>Fully skinnable component</listitem>
- <listitem>Adds <emphasis><property>"onkeypress"</property></emphasis> suggestions capabilities to any input text component</listitem>
- <listitem>Performs suggestion via Ajax requests without any line of JavaScript code written
- by you</listitem>
- <listitem>Possible to render table as a popup suggestion</listitem>
- <listitem>Can be pointed to any Ajax request status indicator of the page</listitem>
- <listitem>Easily customizable size of suggestion popup</listitem>
- <listitem>Setting rules that appear between cells within a table of popup values</listitem>
- <listitem><emphasis
-
-><property>"Event queue"</property></emphasis> and <emphasis
-
-><property>"request delay"</property></emphasis> attributes present to divide
- frequently requests</listitem>
- <listitem>Managing area of components submitted on Ajax request</listitem>
- <listitem>Flexible list of components to update after Ajax request managed by attributes</listitem>
- <listitem>Setting restriction to Ajax request generation</listitem>
- <listitem>Easily setting action to collect suggestion data</listitem>
- <listitem>Keyboard navigation support</listitem>
- </itemizedlist>
- </section>
-</section>
\ No newline at end of file
Deleted: branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionBox.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -1,522 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<section>
- <sectioninfo>
- <keywordset>
- <keyword>on-keypress suggestion</keyword>
- <keyword>rich:suggestionBox</keyword>
- <keyword>HtmlSuggestionBox</keyword>
- </keywordset>
- </sectioninfo>
-
- <table>
- <title>Component identification parameters</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Name</entry>
- <entry>Value</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>component-type</entry>
- <entry>org.richfaces.SuggestionBox</entry>
- </row>
- <row>
- <entry>component-class</entry>
- <entry>org.richfaces.component.html.HtmlSuggestionBox</entry>
- </row>
- <row>
- <entry>component-family</entry>
- <entry>org.richfaces.SuggestionBox</entry>
- </row>
- <row>
- <entry>renderer-type</entry>
- <entry>org.richfaces.SuggestionBoxRenderer</entry>
- </row>
- <row>
- <entry>tag-class</entry>
- <entry>org.richfaces.taglib.SuggestionBoxTag</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <section>
- <title>Creating the Component with a Page Tag</title>
- <para>Here is a simple example as it could be used on a page: </para>
-
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
- <h:inputText value="#{bean.property}" id="suggest"/>
- <rich:suggestionbox for="suggest" suggestionAction="#{bean.autocomplete}"
- var="suggest">
- <h:column>
- <h:outputText value="#{suggest.text}"/>
- </h:column>
- </rich:suggestionbox>
-...
-]]></programlisting>
- <para>Here is the <emphasis>
- <property>bean.autocomplete</property>
- </emphasis> method that returns the collection to pop up:</para>
-
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="JAVA"><![CDATA[public List autocomplete(Object event) {
- String pref = event.toString();
- //collecting some data that begins with "pref" letters.
- ...
- return result;
- }
-]]></programlisting>
- </section>
- <section>
- <title>Creating the Component Dynamically Using Java</title>
-
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="JAVA"><![CDATA[import org.richfaces.component.html.HtmlSuggestionBox;
-...
-HtmlSuggestionBox myList = new HtmlSuggestionBox();
-...
-]]></programlisting>
- </section>
- <section>
- <title>Details of Usage</title>
- <para>As it is shown in the example above, the main component attribute are:</para>
- <itemizedlist>
- <listitem>
- <emphasis>
- <property>"for"</property>
- </emphasis>
- <para>The attribute where there is an input component which activation causes a
- suggestion activation</para>
- </listitem>
- <listitem>
- <emphasis>
- <property>"suggestionAction"</property>
- </emphasis>
- <para> is an accepting parameter of a SuggestionEvent type that returns as a result
- a collection for rendering in a tool tip window.</para>
- </listitem>
- <listitem>
- <emphasis>
- <property>"var"</property>
- </emphasis>
- <para> a collection name that provides access for inputting into a table in a
- popup</para>
- </listitem>
- </itemizedlist>
- <para>There are also two size attributes (<emphasis>
- <property>"width"</property>
- </emphasis> and <emphasis>
- <property>"height"</property>
- </emphasis>) that are obligatory for the suggestion component. The attributes have
- initial Defaults but should be specified manually in order to be changed.</para>
- <para>The <property>suggestionBox</property> component, as it is shown on the screenshot,
- could get any collection for an output and outputs it in a tooltip window the same as a
- custom dataTable (in several columns)</para>
- <programlisting role="XML"><![CDATA[...
- <rich:suggestionbox for="test"
- suggestionAction="#{bean.autocomplete}" var="cit" fetchValue="#{cit.text}">
- <h:column>
- <h:outputText value="#{cit.label}"/>
- </h:column>
- <h:column>
- <h:outputText value="#{cit.text}"/>
- </h:column>
- </rich:suggestionbox>
-...
-]]></programlisting>
- <para>It looks on a page in the following way:</para>
- <figure>
- <title>SuggestionBox with tooltip window</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/suggestionbox2.gif"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>When some string is chosen input receives the corresponding value from the second
- column containing <property>#{cit.text}</property></para>
- <para>There is also one more important attribute named <emphasis>
- <property>"tokens"</property>
- </emphasis> that specifies separators after which a set of some characters sequence is
- defined as a new prefix beginning from this separator and not from the string beginning.</para>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
- <rich:suggestiobox for="test" suggestionAction="#{bean.autocomplete}" var="cit"
- selfRendered="true" tokens=",">
- <h:column>
- <h:outputText value="#{cit.text}"/>
- </h:column>
- </rich:suggestionbox>
-...
-]]></programlisting>
- <para>This example shows that when a city is chosen and a comma and first letter character
- are input, Ajax request is called again, but it submits a value starting from the last
- token:</para>
- <figure>
- <title>SuggestionBox with chosen word</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/suggestionbox3.gif"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>For a multiple definition use either ",.; " syntax as a value for
- tokens or link a parameter to some bean property transmitting separators collection.</para>
- <para>The component also encompasses <emphasis>
- <property>"layout"</property>
- </emphasis> and <emphasis>
- <property>"style"</property>
- </emphasis> attributes corresponding to dataTable ones for a table appearing in popup
- (for additional information, read JSF Reference) and custom attribute managing AJAX
- requests sending (for additional information, see <ulink
- url="http://www.jboss.org/projects/jbossajax4jsf">Ajax4JSF Project</ulink>).</para>
- <para>In addition to these attributes common for Ajax action components and limiting
- requests quantity and frequency, <property>suggestionBox</property> has one more its own
- attribute limiting requests (the <emphasis>
- <property>"minChars"</property>
- </emphasis> attribute). The attribute defines characters quantity inputted into a field
- after which Ajax requests are called to perform suggestion.</para>
-
- </section>
-
- <section>
- <para>
-There is possibility to define what be shown if the autocomplete returns empty list.
-Attribute<emphasis><property> "nothingLabel" </property></emphasis>or facet with the same name could be used for it.
- </para>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
- <rich:suggestiobox nothingLabel="Empty" for="test" suggestionAction="#{bean.autocomplete}" var="cit">
- <h:column>
- <h:outputText value="#{cit.text}"/>
- </h:column>
- </rich:suggestionbox>
-...
-]]></programlisting>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
-<rich:suggestiobox for="test" suggestionAction="#{bean.autocomplete}" var="cit">
- <facet name="nothingLabel">
- <h:outputText value="Empty"/>
- </facet>
- <h:column>
- <h:outputText value="#{cit.text}"/>
- </h:column>
-</rich:suggestionbox>
-...
-]]></programlisting>
-
-
- <para>It looks on a page in the following way:</para>
-
- <figure>
- <title>SuggestionBox with empty list</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/suggestionbox5.gif"/>
- </imageobject>
- </mediaobject>
- </figure>
-</section>
-
- <section>
- <title>Look-and-Feel Customization</title>
-
- <para>For skinnability implementation, the components use a <emphasis>
- <property>style class redefinition method.</property>
- </emphasis> Default style classes are mapped on <emphasis>
- <property>skin parameters.</property>
- </emphasis></para>
-
- <para>There are two ways to redefine the appearance of all <emphasis role="bold">
- <property><rich:suggestionBox></property>
- </emphasis> components at once:</para>
-
- <itemizedlist>
- <listitem>
- <para>Redefine the corresponding skin parameters</para>
- </listitem>
-
- <listitem>
- <para>Add to your style sheets <emphasis>
- <property>style classes</property>
- </emphasis> used by a <emphasis role="bold">
- <property><rich:suggestionBox></property>
- </emphasis> component</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title> Skin Parameters Redefinition</title>
-
- <table>
- <title>General skin parameters redefinition for popup list</title>
-
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Parameters for popup list</entry>
-
- <entry>CSS properties</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>additionalBackgroundColor</entry>
-
- <entry>background-color</entry>
- </row>
-
- <row>
- <entry>panelBorderColor</entry>
-
- <entry>border-color</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table>
- <title>Skin parameters redefinition for shadow element of the list</title>
-
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Parameters for shadow element of the list</entry>
-
- <entry>CSS properties</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>shadowBackgroundColor</entry>
-
- <entry>background-color</entry>
- </row>
-
- <row>
- <entry>shadowBackgroundColor</entry>
-
- <entry>border-color</entry>
- </row>
-
- <row>
- <entry>shadowOpacity</entry>
-
- <entry>opacity</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table>
- <title>Skin parameters redefinition for popup table rows</title>
-
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Parameters for popup table rows</entry>
-
- <entry>CSS properties</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>generalSizeFont</entry>
-
- <entry>font-size</entry>
- </row>
-
- <row>
- <entry>generalTextColor</entry>
-
- <entry>color</entry>
- </row>
-
- <row>
- <entry>generalFamilyFont</entry>
-
- <entry>font-family</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table>
- <title>Skin parameters redefinition for selected row</title>
-
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Parameters for selected row</entry>
-
- <entry>CSS properties</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>headerBackgroundColor</entry>
-
- <entry>background-color</entry>
- </row>
-
- <row>
- <entry>generalSizeFont</entry>
-
- <entry>font-size</entry>
- </row>
-
- <row>
- <entry>generalFamilyFont</entry>
-
- <entry>font-family</entry>
- </row>
- <row>
- <entry>headerTextColor</entry>
-
- <entry>color</entry>
- </row>
-
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>Definition of Custom Style Classes</title>
-
- <figure>
- <title>Classes names</title>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/suggestionbox4.gif"/>
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>On the screenshot, there are classes names defining specified elements.</para>
-
- <table>
- <title>Classes names that define a suggestionBox</title>
-
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Class name</entry>
-
- <entry>Description</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>rich-sb-common-container</entry>
-
- <entry>Defines styles for a wrapper <div> element of a suggestion container</entry>
- </row>
-
- <row>
- <entry>rich-sb-ext-decor-1</entry>
-
- <entry>Defines styles for the first wrapper <div> element of a suggestion box exterior</entry>
- </row>
-
- <row>
- <entry>rich-sb-ext-decor-2</entry>
-
- <entry>Defines styles for the second wrapper <div> element of a suggestion box exterior</entry>
- </row>
-
- <row>
- <entry>rich-sb-ext-decor-3</entry>
-
- <entry>Defines styles for the third wrapper <div> element of a suggestion box exterior</entry>
- </row>
-
- <row>
- <entry>rich-sb-overflow</entry>
-
- <entry>Defines styles for a wrapper <div> element</entry>
- </row>
-
- <row>
- <entry>rich-sb-int-decor-table</entry>
-
- <entry>Defines styles for a suggestion box table</entry>
- </row>
-
- <row>
- <entry>rich-sb-int</entry>
-
- <entry>Defines the styles for a suggestion box table rows (tr)</entry>
- </row>
-
- <row>
- <entry>rich-sb-cell-padding</entry>
-
- <entry>Defines the styles for suggestion box table cells (td)</entry>
- </row>
-
- <row>
- <entry>rich-sb-int-sel</entry>
-
- <entry>Defines styles for a selected row</entry>
- </row>
-
- <row>
- <entry>rich-sb-shadow</entry>
-
- <entry>Defines styles for a suggestion boxshadow</entry>
- </row>
-
- </tbody>
- </tgroup>
- </table>
-
- <para>In order to redefine styles for all <emphasis role="bold">
- <property><rich:suggestionBox></property>
- </emphasis> components on a page using CSS, it's enough to create classes with the
- same names and define necessary properties in them.</para>
-
- <para>To change styles of particular <emphasis role="bold">
- <property><rich:suggestionBox></property>
- </emphasis> components, define your own style classes in the corresponding <emphasis
- role="bold">
- <property><rich:suggestionBox></property>
- </emphasis>attributes.</para>
- </section>
-
-
-
- <section>
- <title>Relevant Resources Links</title>
- <para>
- <ulink
- url="http://livedemo.exadel.com/richfaces-demo/richfaces/suggestionBox.jsf?c=s..."
- >Here</ulink> you can see the example of <emphasis role="bold"
- ><property><rich:suggestionBox></property></emphasis> usage and sources for the given
- example. </para>
- </section>
-
-</section>
Added: branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.desc.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.desc.xml (rev 0)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.desc.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<section>
+<sectioninfo>
+<keywordset>
+<keyword>suggestionBox</keyword>
+</keywordset>
+</sectioninfo>
+<section>
+<title>Description</title>
+ <para>The component adds on-keypress suggestions capabilities to any input text component
+ (like <emphasis role="bold"><property><h:inputText></property></emphasis>). When a key
+ is pressed in the field Ajax request is sent to the server. When the suggestion action returns a
+ list of possible values, it pop ups them inside the
+ <emphasis role="bold"><property><div></property></emphasis> element bellow the input.</para>
+ <figure>
+ <title>SuggestionBox component</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/suggestionbox1.gif"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ </section>
+ <section>
+ <title>Key Features</title>
+ <itemizedlist>
+ <listitem>Fully skinnable component</listitem>
+ <listitem>Adds <emphasis><property>"onkeypress"</property></emphasis> suggestions capabilities to any input text component</listitem>
+ <listitem>Performs suggestion via Ajax requests without any line of JavaScript code written
+ by you</listitem>
+ <listitem>Possible to render table as a popup suggestion</listitem>
+ <listitem>Can be pointed to any Ajax request status indicator of the page</listitem>
+ <listitem>Easily customizable size of suggestion popup</listitem>
+ <listitem>Setting rules that appear between cells within a table of popup values</listitem>
+ <listitem><emphasis
+
+><property>"Event queue"</property></emphasis> and <emphasis
+
+><property>"request delay"</property></emphasis> attributes present to divide
+ frequently requests</listitem>
+ <listitem>Managing area of components submitted on Ajax request</listitem>
+ <listitem>Flexible list of components to update after Ajax request managed by attributes</listitem>
+ <listitem>Setting restriction to Ajax request generation</listitem>
+ <listitem>Easily setting action to collect suggestion data</listitem>
+ <listitem>Keyboard navigation support</listitem>
+ </itemizedlist>
+ </section>
+</section>
\ No newline at end of file
Property changes on: branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.desc.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.xml (rev 0)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -0,0 +1,522 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<section>
+ <sectioninfo>
+ <keywordset>
+ <keyword>on-keypress suggestion</keyword>
+ <keyword>rich:suggestionBox</keyword>
+ <keyword>HtmlSuggestionBox</keyword>
+ </keywordset>
+ </sectioninfo>
+
+ <table>
+ <title>Component identification parameters</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Value</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>component-type</entry>
+ <entry>org.richfaces.SuggestionBox</entry>
+ </row>
+ <row>
+ <entry>component-class</entry>
+ <entry>org.richfaces.component.html.HtmlSuggestionBox</entry>
+ </row>
+ <row>
+ <entry>component-family</entry>
+ <entry>org.richfaces.SuggestionBox</entry>
+ </row>
+ <row>
+ <entry>renderer-type</entry>
+ <entry>org.richfaces.SuggestionBoxRenderer</entry>
+ </row>
+ <row>
+ <entry>tag-class</entry>
+ <entry>org.richfaces.taglib.SuggestionBoxTag</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <section>
+ <title>Creating the Component with a Page Tag</title>
+ <para>Here is a simple example as it could be used on a page: </para>
+
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[...
+ <h:inputText value="#{bean.property}" id="suggest"/>
+ <rich:suggestionbox for="suggest" suggestionAction="#{bean.autocomplete}"
+ var="suggest">
+ <h:column>
+ <h:outputText value="#{suggest.text}"/>
+ </h:column>
+ </rich:suggestionbox>
+...
+]]></programlisting>
+ <para>Here is the <emphasis>
+ <property>bean.autocomplete</property>
+ </emphasis> method that returns the collection to pop up:</para>
+
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="JAVA"><![CDATA[public List autocomplete(Object event) {
+ String pref = event.toString();
+ //collecting some data that begins with "pref" letters.
+ ...
+ return result;
+ }
+]]></programlisting>
+ </section>
+ <section>
+ <title>Creating the Component Dynamically Using Java</title>
+
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="JAVA"><![CDATA[import org.richfaces.component.html.HtmlSuggestionBox;
+...
+HtmlSuggestionBox myList = new HtmlSuggestionBox();
+...
+]]></programlisting>
+ </section>
+ <section>
+ <title>Details of Usage</title>
+ <para>As it is shown in the example above, the main component attribute are:</para>
+ <itemizedlist>
+ <listitem>
+ <emphasis>
+ <property>"for"</property>
+ </emphasis>
+ <para>The attribute where there is an input component which activation causes a
+ suggestion activation</para>
+ </listitem>
+ <listitem>
+ <emphasis>
+ <property>"suggestionAction"</property>
+ </emphasis>
+ <para> is an accepting parameter of a SuggestionEvent type that returns as a result
+ a collection for rendering in a tool tip window.</para>
+ </listitem>
+ <listitem>
+ <emphasis>
+ <property>"var"</property>
+ </emphasis>
+ <para> a collection name that provides access for inputting into a table in a
+ popup</para>
+ </listitem>
+ </itemizedlist>
+ <para>There are also two size attributes (<emphasis>
+ <property>"width"</property>
+ </emphasis> and <emphasis>
+ <property>"height"</property>
+ </emphasis>) that are obligatory for the suggestion component. The attributes have
+ initial Defaults but should be specified manually in order to be changed.</para>
+ <para>The <property>suggestionBox</property> component, as it is shown on the screenshot,
+ could get any collection for an output and outputs it in a tooltip window the same as a
+ custom dataTable (in several columns)</para>
+ <programlisting role="XML"><![CDATA[...
+ <rich:suggestionbox for="test"
+ suggestionAction="#{bean.autocomplete}" var="cit" fetchValue="#{cit.text}">
+ <h:column>
+ <h:outputText value="#{cit.label}"/>
+ </h:column>
+ <h:column>
+ <h:outputText value="#{cit.text}"/>
+ </h:column>
+ </rich:suggestionbox>
+...
+]]></programlisting>
+ <para>It looks on a page in the following way:</para>
+ <figure>
+ <title>SuggestionBox with tooltip window</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/suggestionbox2.gif"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>When some string is chosen input receives the corresponding value from the second
+ column containing <property>#{cit.text}</property></para>
+ <para>There is also one more important attribute named <emphasis>
+ <property>"tokens"</property>
+ </emphasis> that specifies separators after which a set of some characters sequence is
+ defined as a new prefix beginning from this separator and not from the string beginning.</para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[...
+ <rich:suggestiobox for="test" suggestionAction="#{bean.autocomplete}" var="cit"
+ selfRendered="true" tokens=",">
+ <h:column>
+ <h:outputText value="#{cit.text}"/>
+ </h:column>
+ </rich:suggestionbox>
+...
+]]></programlisting>
+ <para>This example shows that when a city is chosen and a comma and first letter character
+ are input, Ajax request is called again, but it submits a value starting from the last
+ token:</para>
+ <figure>
+ <title>SuggestionBox with chosen word</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/suggestionbox3.gif"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>For a multiple definition use either ",.; " syntax as a value for
+ tokens or link a parameter to some bean property transmitting separators collection.</para>
+ <para>The component also encompasses <emphasis>
+ <property>"layout"</property>
+ </emphasis> and <emphasis>
+ <property>"style"</property>
+ </emphasis> attributes corresponding to dataTable ones for a table appearing in popup
+ (for additional information, read JSF Reference) and custom attribute managing AJAX
+ requests sending (for additional information, see <ulink
+ url="http://www.jboss.org/projects/jbossajax4jsf">Ajax4JSF Project</ulink>).</para>
+ <para>In addition to these attributes common for Ajax action components and limiting
+ requests quantity and frequency, <property>suggestionBox</property> has one more its own
+ attribute limiting requests (the <emphasis>
+ <property>"minChars"</property>
+ </emphasis> attribute). The attribute defines characters quantity inputted into a field
+ after which Ajax requests are called to perform suggestion.</para>
+
+ </section>
+
+ <section>
+ <para>
+There is possibility to define what be shown if the autocomplete returns empty list.
+Attribute<emphasis><property> "nothingLabel" </property></emphasis>or facet with the same name could be used for it.
+ </para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[...
+ <rich:suggestiobox nothingLabel="Empty" for="test" suggestionAction="#{bean.autocomplete}" var="cit">
+ <h:column>
+ <h:outputText value="#{cit.text}"/>
+ </h:column>
+ </rich:suggestionbox>
+...
+]]></programlisting>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[...
+<rich:suggestiobox for="test" suggestionAction="#{bean.autocomplete}" var="cit">
+ <facet name="nothingLabel">
+ <h:outputText value="Empty"/>
+ </facet>
+ <h:column>
+ <h:outputText value="#{cit.text}"/>
+ </h:column>
+</rich:suggestionbox>
+...
+]]></programlisting>
+
+
+ <para>It looks on a page in the following way:</para>
+
+ <figure>
+ <title>SuggestionBox with empty list</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/suggestionbox5.gif"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+</section>
+
+ <section>
+ <title>Look-and-Feel Customization</title>
+
+ <para>For skinnability implementation, the components use a <emphasis>
+ <property>style class redefinition method.</property>
+ </emphasis> Default style classes are mapped on <emphasis>
+ <property>skin parameters.</property>
+ </emphasis></para>
+
+ <para>There are two ways to redefine the appearance of all <emphasis role="bold">
+ <property><rich:suggestionBox></property>
+ </emphasis> components at once:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Redefine the corresponding skin parameters</para>
+ </listitem>
+
+ <listitem>
+ <para>Add to your style sheets <emphasis>
+ <property>style classes</property>
+ </emphasis> used by a <emphasis role="bold">
+ <property><rich:suggestionBox></property>
+ </emphasis> component</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title> Skin Parameters Redefinition</title>
+
+ <table>
+ <title>General skin parameters redefinition for popup list</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Parameters for popup list</entry>
+
+ <entry>CSS properties</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>additionalBackgroundColor</entry>
+
+ <entry>background-color</entry>
+ </row>
+
+ <row>
+ <entry>panelBorderColor</entry>
+
+ <entry>border-color</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table>
+ <title>Skin parameters redefinition for shadow element of the list</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Parameters for shadow element of the list</entry>
+
+ <entry>CSS properties</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>shadowBackgroundColor</entry>
+
+ <entry>background-color</entry>
+ </row>
+
+ <row>
+ <entry>shadowBackgroundColor</entry>
+
+ <entry>border-color</entry>
+ </row>
+
+ <row>
+ <entry>shadowOpacity</entry>
+
+ <entry>opacity</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table>
+ <title>Skin parameters redefinition for popup table rows</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Parameters for popup table rows</entry>
+
+ <entry>CSS properties</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>generalSizeFont</entry>
+
+ <entry>font-size</entry>
+ </row>
+
+ <row>
+ <entry>generalTextColor</entry>
+
+ <entry>color</entry>
+ </row>
+
+ <row>
+ <entry>generalFamilyFont</entry>
+
+ <entry>font-family</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table>
+ <title>Skin parameters redefinition for selected row</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Parameters for selected row</entry>
+
+ <entry>CSS properties</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>headerBackgroundColor</entry>
+
+ <entry>background-color</entry>
+ </row>
+
+ <row>
+ <entry>generalSizeFont</entry>
+
+ <entry>font-size</entry>
+ </row>
+
+ <row>
+ <entry>generalFamilyFont</entry>
+
+ <entry>font-family</entry>
+ </row>
+ <row>
+ <entry>headerTextColor</entry>
+
+ <entry>color</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section>
+ <title>Definition of Custom Style Classes</title>
+
+ <figure>
+ <title>Classes names</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/suggestionbox4.gif"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>On the screenshot, there are classes names defining specified elements.</para>
+
+ <table>
+ <title>Classes names that define a suggestionBox</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Class name</entry>
+
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>rich-sb-common-container</entry>
+
+ <entry>Defines styles for a wrapper <div> element of a suggestion container</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-ext-decor-1</entry>
+
+ <entry>Defines styles for the first wrapper <div> element of a suggestion box exterior</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-ext-decor-2</entry>
+
+ <entry>Defines styles for the second wrapper <div> element of a suggestion box exterior</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-ext-decor-3</entry>
+
+ <entry>Defines styles for the third wrapper <div> element of a suggestion box exterior</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-overflow</entry>
+
+ <entry>Defines styles for a wrapper <div> element</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-int-decor-table</entry>
+
+ <entry>Defines styles for a suggestion box table</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-int</entry>
+
+ <entry>Defines the styles for a suggestion box table rows (tr)</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-cell-padding</entry>
+
+ <entry>Defines the styles for suggestion box table cells (td)</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-int-sel</entry>
+
+ <entry>Defines styles for a selected row</entry>
+ </row>
+
+ <row>
+ <entry>rich-sb-shadow</entry>
+
+ <entry>Defines styles for a suggestion boxshadow</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>In order to redefine styles for all <emphasis role="bold">
+ <property><rich:suggestionBox></property>
+ </emphasis> components on a page using CSS, it's enough to create classes with the
+ same names and define necessary properties in them.</para>
+
+ <para>To change styles of particular <emphasis role="bold">
+ <property><rich:suggestionBox></property>
+ </emphasis> components, define your own style classes in the corresponding <emphasis
+ role="bold">
+ <property><rich:suggestionBox></property>
+ </emphasis>attributes.</para>
+ </section>
+
+
+
+ <section>
+ <title>Relevant Resources Links</title>
+ <para>
+ <ulink
+ url="http://livedemo.exadel.com/richfaces-demo/richfaces/suggestionBox.jsf?c=s..."
+ >Here</ulink> you can see the example of <emphasis role="bold"
+ ><property><rich:suggestionBox></property></emphasis> usage and sources for the given
+ example. </para>
+ </section>
+
+</section>
Property changes on: branches/3.1.x/docs/userguide/en/src/main/docbook/included/suggestionbox.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.desc.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.desc.xml (rev 0)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.desc.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<section>
+<sectioninfo>
+<keywordset>
+<keyword>tooltip</keyword>
+</keywordset>
+</sectioninfo>
+<section>
+<title>Description</title>
+ <para>The component used for creation non-modal popup that activated on some event and display some information.
+ </para>
+ <figure>
+ <title>Tooltip component</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/tooltip1.png"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ </section>
+ <section>
+ <title>Key Features</title>
+ <itemizedlist>
+ <listitem>Highly customizable look and feel </listitem>
+ <listitem>Different ways of data loading to tooltip</listitem>
+ <listitem>Disablement support</listitem>
+ </itemizedlist>
+</section>
+</section>
\ No newline at end of file
Property changes on: branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.desc.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.xml (rev 0)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -0,0 +1,368 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<section>
+<sectioninfo>
+<keywordset>
+<keyword>tooltip</keyword>
+<keyword>rich:tooltip</keyword>
+<keyword>HtmlTooltip</keyword>
+</keywordset>
+</sectioninfo>
+ <table>
+ <title>Component identification parameters </title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Value</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>component-type</entry>
+ <entry>org.richfaces.component.ToolTip</entry>
+ </row>
+ <row>
+ <entry>component-class</entry>
+ <entry>org.richfaces.component.html.HtmlToolTip</entry>
+ </row>
+ <row>
+ <entry>component-family</entry>
+ <entry>org.richfaces.component.ToolTip</entry>
+ </row>
+ <row>
+ <entry>renderer-type</entry>
+ <entry>org.richfaces.renderkit.html.ToolTipRenderer</entry>
+ </row>
+ <row>
+ <entry>tag-class</entry>
+ <entry>org.richfaces.taglib.HtmlToolTipTag</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <section>
+ <title>Creating the Component with a Page Tag</title>
+ <para>To create the simplest variant of <property>tooltip</property> on a page, use the following syntax:</para>
+
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[...
+<h:commandButton value="Button">
+ <rich:tooltip value="Tooltip content"/>
+</h:commandButton>
+...
+]]></programlisting>
+ </section>
+
+ <section>
+ <title>Creating the Component Dynamically Using Java</title>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="JAVA"><![CDATA[import org.richfaces.component.html.HtmlToolTip;
+...
+HtmlToolTip myToolTip = new HtmlToolTip();
+...
+]]></programlisting>
+</section>
+
+<section>
+<title>Details of Usage</title>
+<para>
+<property>Tooltip</property> main area is a simple rectangle area with any information inside. The content may be defined via
+"value" attribute as text or via any nested content. When both are defined, the value is displayed as text and nested content
+after the text. <property>Tooltip</property> stretches if the content more than the <property>tooltip</property> sizes.
+</para>
+<para>
+There is possibility to define a facet with the name "defaultContent". This facet provides the default content to
+display while the main content is loaded to a page in an Ajax mode. Thus when <property>tooltip</property> called in an Ajax mode, it
+appears with the content defined in the facet and when loading is completed, the content is changed to a loaded one.
+</para>
+<para>
+ Here is an example:
+</para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[...
+<h:commandLink value="Simple 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>DEFAULT TOOLTIP CONTENT</f:verbatim>
+ </f:facet>
+ </rich:toolTip>
+</h:commandLink>
+...
+]]></programlisting>
+
+<para>
+This is the result:
+</para>
+ <figure>
+ <title>Tooltip component with default content</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/tooltip2.png"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+<para>
+And after <property>tooltip</property> loaded it will be changed to next one:
+</para>
+ <figure>
+ <title>Tooltip component with loaded content</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/tooltip3.png"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+<para>
+By default, <property>tooltip</property> appears smart positioned. But as you can see from the previous example, you
+can define an appearance direction via the corresponding attribute "direction". And also it's possible to define vertical and horizontal
+offsets relatively to a mouse position.
+</para>
+<para>
+<property>Tooltip</property> appears attached to the corner dependent on the <emphasis><property>"direction"</property></emphasis> attribute. By default it is positioned bottom-right.
+<property>Tooltip</property> activation occurs after a defined event (default=mouseover) on the parent component takes into consideration
+the "delay" attribute (default=0) or after calling JS API function doShow(). <property>Tooltip</property> deactivation occurs after mouseout event on the parent component (excepting the situation when the mouse is hovered onto the <property>tooltip</property> itself) or after calling JS API function doHide().
+</para>
+
+<note>
+<title>Note:</title>
+It is recommended to define parent component "id" for correction of <property>tooltip</property> work.
+</note>
+
+ <para>The attribute <emphasis><property>"for"</property></emphasis> is used for defining the <emphasis><property>"id"</property></emphasis> of an element a tooltip should be attached to. Look at the example:
+</para>
+
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[...
+<div id="elementId">
+ <rich:toolTip for="elementId">Using a toolTip<rich:toolTip>
+ <p>The first simple example<p>
+</div>
+...
+<div id="elementId">
+ <p>The second simple example<p>
+</div>
+<rich:toolTip for="elementId">Using a toolTip<rich:toolTip>
+...
+]]></programlisting>
+
+ <para>Here, the attribute <emphasis><property>"for"</property></emphasis> of a <emphasis role="bold">
+ <property><rich:tooltip></property>
+ </emphasis> component is required. Whithout it an example doesn’t work because HTML elements aren't presented in component tree built by facelets.
+ </para>
+
+<para>
+The <emphasis><property>"mode"</property></emphasis> attribute is provided you to control the way of data loading to <property>tooltip</property>. It has following values:
+ <itemizedlist>
+ <listitem>Client</listitem>
+ <listitem>Ajax</listitem>
+ </itemizedlist>
+</para>
+<para>
+In a client mode, <property>tooltip</property> content is rendered once on the server and could be reRendered only via external submit.
+In an Ajax mode, <property>tooltip</property> content is requested from server every activation.
+</para>
+<para>
+Special JS API is provided to control the component behaviour:
+ <itemizedlist>
+ <listitem> - </listitem>
+ <listitem> - </listitem>
+ <listitem> - </listitem>
+ <listitem> - </listitem>
+ </itemizedlist>
+</para>
+<para>
+Disabled <property>tooltip</property> is rendered to a page as usual but JS that responds for its activation is
+disabled until doEnable() is called.
+</para>
+<para>
+Moreover, to add some JavaScript effects, client events defined on it are used:
+</para>
+<para>
+ Standart:
+ <itemizedlist>
+ <listitem>onclick</listitem>
+ <listitem>ondblclick</listitem>
+ <listitem>onmouseout</listitem>
+ <listitem>onmousemove</listitem>
+ <listitem>onmouseover</listitem>
+ </itemizedlist>
+</para>
+<para>
+ Special:
+ <itemizedlist>
+ <listitem>onshow - Called after the tooltip is called (some element hovered) but before its request
+ </listitem>
+ <listitem>oncomplete - Called just after the tooltip is shown
+ </listitem>
+ <listitem>onhide - Called after the tooltip is hidden
+ </listitem>
+ </itemizedlist>
+</para>
+</section>
+
+ <section>
+ <title>JavaScript API</title>
+ <table>
+ <title>JavaScript API</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Function</entry>
+
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+
+ <row>
+ <entry>doShow()</entry>
+
+ <entry>Shows the corresponding tooltip</entry>
+ </row>
+
+ <row>
+ <entry>doHide()</entry>
+
+ <entry>Hides the corresponding tooltip</entry>
+ </row>
+
+ <row>
+ <entry>doEnable()</entry>
+
+ <entry>Enables the corresponding tooltip</entry>
+ </row>
+
+ <row>
+ <entry>doDisable()</entry>
+
+ <entry>Disables the corresponding tooltip</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+
+ </section>
+
+ <section>
+ <title>Look-and-Feel Customization</title>
+
+ <para>For skinnability implementation, the components use a <emphasis>
+ <property>style class redefinition method.</property>
+ </emphasis> Default style classes are mapped on <emphasis>
+ <property>skin parameters.</property>
+ </emphasis></para>
+
+ <para>There are two ways to redefine the appearance of all <emphasis role="bold">
+ <property><rich:tooltip></property>
+ </emphasis> components at once:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Redefine the corresponding skin parameters</para>
+ </listitem>
+
+ <listitem>
+ <para>Add to your style sheets <emphasis>
+ <property>style classes</property>
+ </emphasis> used by a <emphasis role="bold">
+ <property><rich:tooltip></property>
+ </emphasis> component</para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+ <section>
+ <title>Skin Parameters Redefinition</title>
+ <table>
+ <title>Skin parameters redefinition for a component</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Skin parameters</entry>
+ <entry>CSS properties</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>tipBackgroundColor</entry>
+ <entry>background-color</entry>
+ </row>
+ <row>
+ <entry>tipBorderColor</entry>
+ <entry>border-color</entry>
+ </row>
+ <row>
+ <entry>generalSizeFont</entry>
+ <entry>font-size</entry>
+ </row>
+ <row>
+ <entry>generalFamilyFont</entry>
+ <entry>font-family</entry>
+ </row>
+ <row>
+ <entry>generalFontColor</entry>
+ <entry>color</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+</section>
+
+
+ <section>
+ <title>Definition of Custom Style Classes</title>
+ <table>
+ <title>Classes names that define a component appearance</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Class name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>rich-tool-tip</entry>
+ <entry>Defines styles for a wrapper <span> or <div> element of a tooltip</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ It depends on <emphasis role="bold"><property><rich:tooltip></property></emphasis> layout what a wrapper element <emphasis><property><span></property></emphasis> or <emphasis><property><div></property></emphasis>to choose.
+ </para>
+ <para>In order to redefine styles for all <emphasis role="bold">
+ <property><rich:tooltip></property>
+ </emphasis> components on a page using CSS, it's enough to create class with the
+ same name and define necessary properties in it.</para>
+
+ <para>To change styles of particular <emphasis role="bold">
+ <property><rich:tooltip></property>
+ </emphasis> components define your own style class in the corresponding <emphasis
+ role="bold">
+ <property><rich:tooltip></property>
+ </emphasis>attributes</para>
+</section>
+ <section>
+ <title>Relevant Resources Links</title>
+ <para><ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/toolTip.jsf?c=toolTip"
+ >Here</ulink> you can see the example of <emphasis role="bold"
+ ><property><rich:toolTip></property></emphasis> usage and sources for the given example. </para>
+ </section>
+</section>
+
\ No newline at end of file
Property changes on: branches/3.1.x/docs/userguide/en/src/main/docbook/included/toolTip.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.desc.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.desc.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.desc.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<section>
-<sectioninfo>
-<keywordset>
-<keyword>tooltip</keyword>
-</keywordset>
-</sectioninfo>
-<section>
-<title>Description</title>
- <para>The component used for creation non-modal popup that activated on some event and display some information.
- </para>
- <figure>
- <title>Tooltip component</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/tooltip1.png"/>
- </imageobject>
- </mediaobject>
- </figure>
- </section>
- <section>
- <title>Key Features</title>
- <itemizedlist>
- <listitem>Highly customizable look and feel </listitem>
- <listitem>Different ways of data loading to tooltip</listitem>
- <listitem>Disablement support</listitem>
- </itemizedlist>
-</section>
-</section>
\ No newline at end of file
Deleted: branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.xml
===================================================================
--- branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/userguide/en/src/main/docbook/included/tooltip.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -1,368 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<section>
-<sectioninfo>
-<keywordset>
-<keyword>tooltip</keyword>
-<keyword>rich:tooltip</keyword>
-<keyword>HtmlTooltip</keyword>
-</keywordset>
-</sectioninfo>
- <table>
- <title>Component identification parameters </title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Name</entry>
- <entry>Value</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>component-type</entry>
- <entry>org.richfaces.component.ToolTip</entry>
- </row>
- <row>
- <entry>component-class</entry>
- <entry>org.richfaces.component.html.HtmlToolTip</entry>
- </row>
- <row>
- <entry>component-family</entry>
- <entry>org.richfaces.component.ToolTip</entry>
- </row>
- <row>
- <entry>renderer-type</entry>
- <entry>org.richfaces.renderkit.html.ToolTipRenderer</entry>
- </row>
- <row>
- <entry>tag-class</entry>
- <entry>org.richfaces.taglib.HtmlToolTipTag</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <section>
- <title>Creating the Component with a Page Tag</title>
- <para>To create the simplest variant of <property>tooltip</property> on a page, use the following syntax:</para>
-
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
-<h:commandButton value="Button">
- <rich:tooltip value="Tooltip content"/>
-</h:commandButton>
-...
-]]></programlisting>
- </section>
-
- <section>
- <title>Creating the Component Dynamically Using Java</title>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="JAVA"><![CDATA[import org.richfaces.component.html.HtmlToolTip;
-...
-HtmlToolTip myToolTip = new HtmlToolTip();
-...
-]]></programlisting>
-</section>
-
-<section>
-<title>Details of Usage</title>
-<para>
-<property>Tooltip</property> main area is a simple rectangle area with any information inside. The content may be defined via
-"value" attribute as text or via any nested content. When both are defined, the value is displayed as text and nested content
-after the text. <property>Tooltip</property> stretches if the content more than the <property>tooltip</property> sizes.
-</para>
-<para>
-There is possibility to define a facet with the name "defaultContent". This facet provides the default content to
-display while the main content is loaded to a page in an Ajax mode. Thus when <property>tooltip</property> called in an Ajax mode, it
-appears with the content defined in the facet and when loading is completed, the content is changed to a loaded one.
-</para>
-<para>
- Here is an example:
-</para>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
-<h:commandLink value="Simple 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>DEFAULT TOOLTIP CONTENT</f:verbatim>
- </f:facet>
- </rich:toolTip>
-</h:commandLink>
-...
-]]></programlisting>
-
-<para>
-This is the result:
-</para>
- <figure>
- <title>Tooltip component with default content</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/tooltip2.png"/>
- </imageobject>
- </mediaobject>
- </figure>
-<para>
-And after <property>tooltip</property> loaded it will be changed to next one:
-</para>
- <figure>
- <title>Tooltip component with loaded content</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/tooltip3.png"/>
- </imageobject>
- </mediaobject>
- </figure>
-<para>
-By default, <property>tooltip</property> appears smart positioned. But as you can see from the previous example, you
-can define an appearance direction via the corresponding attribute "direction". And also it's possible to define vertical and horizontal
-offsets relatively to a mouse position.
-</para>
-<para>
-<property>Tooltip</property> appears attached to the corner dependent on the <emphasis><property>"direction"</property></emphasis> attribute. By default it is positioned bottom-right.
-<property>Tooltip</property> activation occurs after a defined event (default=mouseover) on the parent component takes into consideration
-the "delay" attribute (default=0) or after calling JS API function doShow(). <property>Tooltip</property> deactivation occurs after mouseout event on the parent component (excepting the situation when the mouse is hovered onto the <property>tooltip</property> itself) or after calling JS API function doHide().
-</para>
-
-<note>
-<title>Note:</title>
-It is recommended to define parent component "id" for correction of <property>tooltip</property> work.
-</note>
-
- <para>The attribute <emphasis><property>"for"</property></emphasis> is used for defining the <emphasis><property>"id"</property></emphasis> of an element a tooltip should be attached to. Look at the example:
-</para>
-
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[...
-<div id="elementId">
- <rich:toolTip for="elementId">Using a toolTip<rich:toolTip>
- <p>The first simple example<p>
-</div>
-...
-<div id="elementId">
- <p>The second simple example<p>
-</div>
-<rich:toolTip for="elementId">Using a toolTip<rich:toolTip>
-...
-]]></programlisting>
-
- <para>Here, the attribute <emphasis><property>"for"</property></emphasis> of a <emphasis role="bold">
- <property><rich:tooltip></property>
- </emphasis> component is required. Whithout it an example doesn’t work because HTML elements aren't presented in component tree built by facelets.
- </para>
-
-<para>
-The <emphasis><property>"mode"</property></emphasis> attribute is provided you to control the way of data loading to <property>tooltip</property>. It has following values:
- <itemizedlist>
- <listitem>Client</listitem>
- <listitem>Ajax</listitem>
- </itemizedlist>
-</para>
-<para>
-In a client mode, <property>tooltip</property> content is rendered once on the server and could be reRendered only via external submit.
-In an Ajax mode, <property>tooltip</property> content is requested from server every activation.
-</para>
-<para>
-Special JS API is provided to control the component behaviour:
- <itemizedlist>
- <listitem> - </listitem>
- <listitem> - </listitem>
- <listitem> - </listitem>
- <listitem> - </listitem>
- </itemizedlist>
-</para>
-<para>
-Disabled <property>tooltip</property> is rendered to a page as usual but JS that responds for its activation is
-disabled until doEnable() is called.
-</para>
-<para>
-Moreover, to add some JavaScript effects, client events defined on it are used:
-</para>
-<para>
- Standart:
- <itemizedlist>
- <listitem>onclick</listitem>
- <listitem>ondblclick</listitem>
- <listitem>onmouseout</listitem>
- <listitem>onmousemove</listitem>
- <listitem>onmouseover</listitem>
- </itemizedlist>
-</para>
-<para>
- Special:
- <itemizedlist>
- <listitem>onshow - Called after the tooltip is called (some element hovered) but before its request
- </listitem>
- <listitem>oncomplete - Called just after the tooltip is shown
- </listitem>
- <listitem>onhide - Called after the tooltip is hidden
- </listitem>
- </itemizedlist>
-</para>
-</section>
-
- <section>
- <title>JavaScript API</title>
- <table>
- <title>JavaScript API</title>
-
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Function</entry>
-
- <entry>Description</entry>
- </row>
- </thead>
-
- <tbody>
-
- <row>
- <entry>doShow()</entry>
-
- <entry>Shows the corresponding tooltip</entry>
- </row>
-
- <row>
- <entry>doHide()</entry>
-
- <entry>Hides the corresponding tooltip</entry>
- </row>
-
- <row>
- <entry>doEnable()</entry>
-
- <entry>Enables the corresponding tooltip</entry>
- </row>
-
- <row>
- <entry>doDisable()</entry>
-
- <entry>Disables the corresponding tooltip</entry>
- </row>
-
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
- <section>
- <title>Look-and-Feel Customization</title>
-
- <para>For skinnability implementation, the components use a <emphasis>
- <property>style class redefinition method.</property>
- </emphasis> Default style classes are mapped on <emphasis>
- <property>skin parameters.</property>
- </emphasis></para>
-
- <para>There are two ways to redefine the appearance of all <emphasis role="bold">
- <property><rich:tooltip></property>
- </emphasis> components at once:</para>
-
- <itemizedlist>
- <listitem>
- <para>Redefine the corresponding skin parameters</para>
- </listitem>
-
- <listitem>
- <para>Add to your style sheets <emphasis>
- <property>style classes</property>
- </emphasis> used by a <emphasis role="bold">
- <property><rich:tooltip></property>
- </emphasis> component</para>
- </listitem>
- </itemizedlist>
-
- </section>
- <section>
- <title>Skin Parameters Redefinition</title>
- <table>
- <title>Skin parameters redefinition for a component</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Skin parameters</entry>
- <entry>CSS properties</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>tipBackgroundColor</entry>
- <entry>background-color</entry>
- </row>
- <row>
- <entry>tipBorderColor</entry>
- <entry>border-color</entry>
- </row>
- <row>
- <entry>generalSizeFont</entry>
- <entry>font-size</entry>
- </row>
- <row>
- <entry>generalFamilyFont</entry>
- <entry>font-family</entry>
- </row>
- <row>
- <entry>generalFontColor</entry>
- <entry>color</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
-</section>
-
-
- <section>
- <title>Definition of Custom Style Classes</title>
- <table>
- <title>Classes names that define a component appearance</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Class name</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>rich-tool-tip</entry>
- <entry>Defines styles for a wrapper <span> or <div> element of a tooltip</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
- It depends on <emphasis role="bold"><property><rich:tooltip></property></emphasis> layout what a wrapper element <emphasis><property><span></property></emphasis> or <emphasis><property><div></property></emphasis>to choose.
- </para>
- <para>In order to redefine styles for all <emphasis role="bold">
- <property><rich:tooltip></property>
- </emphasis> components on a page using CSS, it's enough to create class with the
- same name and define necessary properties in it.</para>
-
- <para>To change styles of particular <emphasis role="bold">
- <property><rich:tooltip></property>
- </emphasis> components define your own style class in the corresponding <emphasis
- role="bold">
- <property><rich:tooltip></property>
- </emphasis>attributes</para>
-</section>
- <section>
- <title>Relevant Resources Links</title>
- <para><ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/toolTip.jsf?c=toolTip"
- >Here</ulink> you can see the example of <emphasis role="bold"
- ><property><rich:toolTip></property></emphasis> usage and sources for the given example. </para>
- </section>
-</section>
-
\ No newline at end of file
Modified: branches/3.1.x/docs/xslt/en/src/main/xslt/f.xsl
===================================================================
--- branches/3.1.x/docs/xslt/en/src/main/xslt/f.xsl 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/docs/xslt/en/src/main/xslt/f.xsl 2007-12-12 00:45:15 UTC (rev 4756)
@@ -13,7 +13,11 @@
<xsl:variable name="excluded-tag-names">
header2,header3,header4,header5,header6
</xsl:variable>
-
+ <xsl:comment>
+ XSLT Version = <xsl:copy-of select="system-property('xsl:version')"/>
+ XSLT Vendor = <xsl:copy-of select="system-property('xsl:vendor')"/>
+ XSLT Vendor URL = <xsl:copy-of select="system-property('xsl:vendor-url')"/>
+ </xsl:comment>
<xsl:for-each select="javaee:tag | tag">
<!--xsl:value-of select="./name/text()" /-->
Modified: branches/3.1.x/ui/assembly/pom.xml
===================================================================
--- branches/3.1.x/ui/assembly/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
+++ branches/3.1.x/ui/assembly/pom.xml 2007-12-12 00:45:15 UTC (rev 4756)
@@ -149,6 +149,34 @@
${project.build.directory}/docs/userguide/en
</outputDirectory>
</artifactItem>
+ <artifactItem>
+ <groupId>
+ org.richfaces.docs.userguide
+ </groupId>
+ <artifactId>en</artifactId>
+ <version>
+ ${project.version}
+ </version>
+ <type>war</type>
+ <classifier>pdf</classifier>
+ <outputDirectory>
+ ${project.build.directory}/docs/userguide/en
+ </outputDirectory>
+ </artifactItem>
+ <artifactItem>
+ <groupId>
+ org.richfaces.docs.faq
+ </groupId>
+ <artifactId>en</artifactId>
+ <version>
+ ${project.version}
+ </version>
+ <type>war</type>
+ <classifier>pdf</classifier>
+ <outputDirectory>
+ ${project.build.directory}/docs/faq/en
+ </outputDirectory>
+ </artifactItem>
</artifactItems>
<outputDirectory>
${project.build.directory}/docs
18 years, 5 months
JBoss Rich Faces SVN: r4755 - in trunk: cdk/maven-javascript-plugin and 30 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: alexsmirnov
Date: 2007-12-11 18:30:42 -0500 (Tue, 11 Dec 2007)
New Revision: 4755
Added:
trunk/cdk/maven-javascript-plugin/
trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt
trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt
trunk/cdk/maven-javascript-plugin/pom.xml
trunk/cdk/maven-javascript-plugin/src/
trunk/cdk/maven-javascript-plugin/src/changes/
trunk/cdk/maven-javascript-plugin/src/changes/changes.xml
trunk/cdk/maven-javascript-plugin/src/main/
trunk/cdk/maven-javascript-plugin/src/main/java/
trunk/cdk/maven-javascript-plugin/src/main/java/com/
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
trunk/cdk/maven-javascript-plugin/src/main/java/org/
trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/
trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/
trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
trunk/cdk/maven-javascript-plugin/src/main/resources/
trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js
trunk/cdk/maven-javascript-plugin/src/test/
trunk/cdk/maven-javascript-plugin/src/test/java/
trunk/cdk/maven-javascript-plugin/src/test/java/net/
trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/
trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/
trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/
trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/
trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
Modified:
trunk/cdk/pom.xml
trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java
trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java
trunk/framework/impl/pom.xml
trunk/framework/test/pom.xml
trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml
trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml
trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml
Log:
Import patched yuicompressor-maven-plugin into project, to aggregate and test JavaScripts.
Generate aggregatet scripts and styles.
Modify Seam Booking portlet to work with a refactored bridge.
Added: trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt
===================================================================
--- trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt (rev 0)
+++ trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,76 @@
+==============================================================================
+YUI Compressor
+==============================================================================
+
+NAME
+
+ YUI Compressor - The Yahoo! JavaScript and CSS Compressor
+
+SYNOPSIS
+
+ java -jar yuicompressor.jar
+ [-h, --help] [--line-break] [--nomunge]
+ [--warn] [--charset character-set]
+ [-o outfile] infile
+
+DESCRIPTION
+
+ The YUI Compressor is a JavaScript compressor which, in addition to removing
+ comments and white-spaces, obfuscates local variables using the smallest
+ possible variable name. This obfuscation is safe, even when using constructs
+ such as 'eval' or 'with' (although the compression is not optimal is those
+ cases) Compared to jsmin, the average savings is around 20%.
+
+ The YUI Compressor is also able to safely compress CSS files. The decision
+ on which compressor is being used is made on the file extension (js or css)
+
+GLOBAL OPTIONS
+
+ -h, --help
+ Prints help on how to use the YUI Compressor
+
+ --type js|css
+ The type of compressor (JavaScript or CSS) is chosen based on the
+ extension of the input file name (.js or .css) If the input file name
+ does not have an extension, or that extension is neither .js nor .css,
+ the type option MUST be specified.
+
+ --charset character-set
+ If a supported character set is specified, the YUI Compressor will use it
+ to read the input file. Otherwise, it will assume that the platform's
+ default character set is being used. The output file is encoded using
+ the same character set.
+
+ -o outfile
+ Place output in file outfile. If not specified, the YUI Compressor will
+ place the output in a file which name is made of the input file name,
+ the "-min" suffix and the "js" extension.
+
+JAVASCRIPT ONLY OPTIONS
+
+ --line-break
+ Adds a line feed character after each semi-colon character in the
+ output file (may help debugging with the MS Script debugger)
+
+ --nomunge
+ Minify only. Do not obfuscate local symbols.
+
+ --warn
+ Prints additional warnings such as duplicate variable declarations,
+ missing variable declaration, unrecommended practices, etc.
+
+NOTES
+
+ The YUI Compressor requires Java version >= 1.4.
+
+AUTHOR
+
+ The YUI Compressor was written and is maintained by:
+ Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ The CSS portion is a port of Isaac Schlueter's cssmin utility.
+
+COPYRIGHT
+
+ Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ Code licensed under the BSD License:
+ http://developer.yahoo.net/yui/license.txt
Property changes on: trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt
===================================================================
--- trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt (rev 0)
+++ trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,100 @@
+==============================================================================
+YUI Compressor
+==============================================================================
+
+NAME
+
+ YUI Compressor - The Yahoo! JavaScript and CSS Compressor
+
+SYNOPSIS
+
+ Usage: java -jar yuicompressor-x.y.z.jar [options] [input file]
+
+ Global Options
+ -h, --help Displays this information
+ --type <js|css> Specifies the type of the input file
+ --charset <charset> Read the input file using <charset>
+ --line-break <column> Insert a line break after the specified column number
+ -o <file> Place the output into <file>. Defaults to stdout.
+
+ JavaScript Options
+ --warn Display possible errors in the code
+ --nomunge Minify only, do not obfuscate
+ --preserve-semi Preserve all semicolons
+ --preserve-strings Do not merge concatenated string literals
+
+DESCRIPTION
+
+ The YUI Compressor is a JavaScript compressor which, in addition to removing
+ comments and white-spaces, obfuscates local variables using the smallest
+ possible variable name. This obfuscation is safe, even when using constructs
+ such as 'eval' or 'with' (although the compression is not optimal is those
+ cases) Compared to jsmin, the average savings is around 20%.
+
+ The YUI Compressor is also able to safely compress CSS files. The decision
+ on which compressor is being used is made on the file extension (js or css)
+
+GLOBAL OPTIONS
+
+ -h, --help
+ Prints help on how to use the YUI Compressor
+
+ --line-break
+ Some source control tools don't like files containing lines longer than,
+ say 8000 characters. The linebreak option is used in that case to split
+ long lines after a specific column. It can also be used to make the code
+ more readable, easier to debug (especially with the MS Script Debugger)
+ Specify 0 to get a line break after each semi-colon in JavaScript, and
+ after each rule in CSS.
+
+ --type js|css
+ The type of compressor (JavaScript or CSS) is chosen based on the
+ extension of the input file name (.js or .css) This option is required
+ if no input file has been specified. Otherwise, this option is only
+ required if the input file extension is neither 'js' nor 'css'.
+
+ --charset character-set
+ If a supported character set is specified, the YUI Compressor will use it
+ to read the input file. Otherwise, it will assume that the platform's
+ default character set is being used. The output file is encoded using
+ the same character set.
+
+ -o outfile
+ Place output in file outfile. If not specified, the YUI Compressor will
+ default to the standard output, which you can redirect to a file.
+
+JAVASCRIPT ONLY OPTIONS
+
+ --nomunge
+ Minify only. Do not obfuscate local symbols.
+
+ --warn
+ Prints additional warnings such as duplicate variable declarations,
+ missing variable declaration, unrecommended practices, etc.
+
+ --preserve-semi
+ Preserve unnecessary semicolons (such as right before a '}') This option
+ is useful when compressed code has to be run through JSLint (which is the
+ case of YUI for example)
+
+ --preserve-strings
+ Use this option to specify that concatenated string literals should
+ never be merged.
+
+NOTES
+
+ + If no input file is specified, it defaults to stdin.
+
+ + The YUI Compressor requires Java version >= 1.4.
+
+AUTHOR
+
+ The YUI Compressor was written and is maintained by:
+ Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ The CSS portion is a port of Isaac Schlueter's cssmin utility.
+
+COPYRIGHT
+
+ Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ Code licensed under the BSD License:
+ http://developer.yahoo.net/yui/license.txt
Property changes on: trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/cdk/maven-javascript-plugin/pom.xml
===================================================================
--- trunk/cdk/maven-javascript-plugin/pom.xml (rev 0)
+++ trunk/cdk/maven-javascript-plugin/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,56 @@
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>cdk</artifactId>
+ <groupId>org.richfaces</groupId>
+ <version>3.2.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.richfaces.cdk</groupId>
+ <artifactId>maven-javascript-plugin</artifactId>
+ <packaging>maven-plugin</packaging>
+ <name>YUI Compressor Maven Mojo</name>
+ <description>
+ To compress (Minify + Ofuscate) Javascript files and CSS files
+ (using YUI Compressor from Julien Lecomte) and/or to check
+ Javascript files with jslint.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>rhino</groupId>
+ <artifactId>js</artifactId>
+ <version>1.6R7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>2.0.7</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>2.0.7</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins></plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <properties>
+ <java.src.version>1.5</java.src.version>
+ <runtime.log>target/velocity.log</runtime.log>
+ </properties>
+
+</project>
Property changes on: trunk/cdk/maven-javascript-plugin/pom.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/changes/changes.xml
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/changes/changes.xml (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/changes/changes.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<document>
+ <properties>
+ <author email="dwayneb(a)users.sourceforge.net">David Bernard</author>
+ </properties>
+ <body>
+ <release version="TODO" description="Future">
+ <action dev="dwayneb" type="add">add support for offline mode (don't failed)</action>
+ <action dev="dwayneb" type="add">generate an xml report for integration with external tool (like QALab)</action>
+ <action dev="dwayneb" type="add">generate an html/xdoc report for integration with the site (like other static analyser : pmd, checkstyle,...)</action>
+ <action dev="dwayneb" type="add">more test</action>
+ <action dev="dwayneb" type="add">add option to stop maven processing if Spoon building failed (pre-compilation by JDTCompiler)</action>
+ <action dev="dwayneb" type="add">add logging information (about download,...)</action>
+ </release>
+ <release version="0.6.1" date="2007-06-27" description="spoon-1.3">
+ <action dev="dwayneb" type="update">move to spoon-1.3</action>
+ </release>
+ <release version="0.6" date="2007-06-14" description="testing">
+ <action dev="dwayneb" type="fix">keep annotation in the generated bytecode</action>
+ <action dev="dwayneb" type="update">enhance/fix support for using plugin for test phase with local spoonlet</action>
+ <action dev="dwayneb" type="add">add the goal 'test-recompile'</action>
+ <action dev="dwayneb" type="update">rename the goal 'test-run' to 'test-generate'</action>
+ </release>
+ <release version="0.5" date="2007-06-06" description="spoon-1.2">
+ <action dev="dwayneb" type="add">add option to stop maven processing if WARNING or ERROR are reported by Spoonlet(s)</action>
+ <action dev="dwayneb" type="fix">use maven logger for every report (include new from spoon-core-1.2)</action>
+ <action dev="dwayneb" type="update">change scm from subversion (svn) to mercurial (hg)</action>
+ <action dev="dwayneb" type="update">move to spoon-core-1.2.</action>
+ <action dev="dwayneb" type="fix">change the groupId from spoon.contrib to net.sf.alchim to follow Maven's convention</action>
+ </release>
+ <release version="0.4" description="launcher improvement">
+ <action dev="dwayneb" type="fix">support change in the api of spoon-1.1-SNAPSHOT.</action>
+ <action dev="dwayneb" type="fix">display classpath as debug message</action>
+ <action dev="dwayneb" type="add">add basic support SNAPSHOT (always downloaded)</action>
+ <action dev="dwayneb" type="add">add basic support for relocation of artifact's groupId (see http://maven.apache.org/guides/mini/guide-relocation.html)</action>
+ </release>
+ <release version="0.3" date="2006-12-03" description="Support spoon.cfg.xml">
+ <action dev="dwayneb" type="add">add support of "spoon.cfg.xml".</action>
+ <action dev="dwayneb" type="add">rename previous 'run' goal by 'generate' goal.</action>
+ <action dev="dwayneb" type="add">add 'recompile' goal.</action>
+ <action dev="dwayneb" type="fix">fix classloader and classpath issue when compile and run spoonlet.</action>
+ </release>
+ <release version="0.2" date="2006-11-23" description="First release">
+ <action dev="dwayneb" type="add">Publish the project on sourceforge (under alchim project)</action>
+ </release>
+ </body>
+</document>
Property changes on: trunk/cdk/maven-javascript-plugin/src/changes/changes.xml
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,157 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ *
+ * This code is a port of Isaac Schlueter's cssmin utility.
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+public class CssCompressor {
+
+ private StringBuffer srcsb = new StringBuffer();
+
+ public CssCompressor(Reader in) throws IOException {
+ // Read the stream...
+ int c;
+ while ((c = in.read()) != -1) {
+ srcsb.append((char) c);
+ }
+ }
+
+ public void compress(Writer out, int linebreakpos)
+ throws IOException {
+
+ Pattern p;
+ Matcher m;
+ String css;
+ StringBuffer sb;
+ int startIndex, endIndex;
+
+ // Remove all comment blocks...
+ sb = new StringBuffer(srcsb.toString());
+ while ((startIndex = sb.indexOf("/*")) >= 0) {
+ endIndex = sb.indexOf("*/", startIndex + 2);
+ if (endIndex >= startIndex + 2)
+ sb.delete(startIndex, endIndex + 2);
+ }
+
+ css = sb.toString();
+
+ // Normalize all whitespace strings to single spaces. Easier to work with that way.
+ css = css.replaceAll("\\s+", " ");
+
+ // Remove the spaces before the things that should not have spaces before them.
+ // But, be careful not to turn "p :link {...}" into "p:link{...}"
+ // Swap out any pseudo-class colons with the token, and then swap back.
+ sb = new StringBuffer();
+ p = Pattern.compile("(^|\\})(([^\\{:])+:)+([^\\{]*\\{)");
+ m = p.matcher(css);
+ while (m.find()) {
+ String s = m.group();
+ s = s.replaceAll(":", "___PSEUDOCLASSCOLON___");
+ m.appendReplacement(sb, s);
+ }
+ m.appendTail(sb);
+ css = sb.toString();
+ css = css.replaceAll("\\s+([!{};:>+\\(\\)\\],])", "$1");
+ css = css.replaceAll("___PSEUDOCLASSCOLON___", ":");
+
+ // Remove the spaces after the things that should not have spaces after them.
+ css = css.replaceAll("([!{}:;>+\\(\\[,])\\s+", "$1");
+
+ // Add the semicolon where it's missing.
+ css = css.replaceAll("([^;\\}])}", "$1;}");
+
+ // Replace 0(px,em,%) with 0.
+ css = css.replaceAll("([\\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)", "$1$2");
+
+ // Replace 0 0 0 0; with 0.
+ css = css.replaceAll(":0 0 0 0;", ":0;");
+ css = css.replaceAll(":0 0 0;", ":0;");
+ css = css.replaceAll(":0 0;", ":0;");
+ // Replace background-position:0; with background-position:0 0;
+ css = css.replaceAll("background-position:0;", "background-position:0 0;");
+
+ // Replace 0.6 to .6, but only when preceded by : or a white-space
+ css = css.replaceAll("(:|\\s)0+\\.(\\d+)", "$1.$2");
+
+ // Shorten colors from rgb(51,102,153) to #336699
+ // This makes it more likely that it'll get further compressed in the next step.
+ p = Pattern.compile("rgb\\s*\\(\\s*([0-9,\\s]+)\\s*\\)");
+ m = p.matcher(css);
+ sb = new StringBuffer();
+ while (m.find()) {
+ String[] rgbcolors = m.group(1).split(",");
+ StringBuffer hexcolor = new StringBuffer("#");
+ for (int i = 0; i < rgbcolors.length; i++) {
+ int val = Integer.parseInt(rgbcolors[i]);
+ if (val < 16) {
+ hexcolor.append("0");
+ }
+ hexcolor.append(Integer.toHexString(val));
+ }
+ m.appendReplacement(sb, hexcolor.toString());
+ }
+ m.appendTail(sb);
+ css = sb.toString();
+
+ // Shorten colors from #AABBCC to #ABC. Note that we want to make sure
+ // the color is not preceded by either ", " or =. Indeed, the property
+ // filter: chroma(color="#FFFFFF");
+ // would become
+ // filter: chroma(color="#FFF");
+ // which makes the filter break in IE.
+ p = Pattern.compile("([^\"'=\\s])(\\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])");
+ m = p.matcher(css);
+ sb = new StringBuffer();
+ while (m.find()) {
+ // Test for AABBCC pattern
+ if (m.group(3).equalsIgnoreCase(m.group(4)) &&
+ m.group(5).equalsIgnoreCase(m.group(6)) &&
+ m.group(7).equalsIgnoreCase(m.group(8))) {
+ m.appendReplacement(sb, m.group(1) + m.group(2) + "#" + m.group(3) + m.group(5) + m.group(7));
+ } else {
+ m.appendReplacement(sb, m.group());
+ }
+ }
+ m.appendTail(sb);
+ css = sb.toString();
+
+ // Remove empty rules.
+ css = css.replaceAll("[^\\}]+\\{;\\}", "");
+
+ if (linebreakpos >= 0) {
+ // Some source control tools don't like it when files containing lines longer
+ // than, say 8000 characters, are checked in. The linebreak option is used in
+ // that case to split long lines after a specific column.
+ int i = 0;
+ int linestartpos = 0;
+ sb = new StringBuffer(css);
+ while (i < sb.length()) {
+ char c = sb.charAt(i++);
+ if (c == '}' && i - linestartpos > linebreakpos) {
+ sb.insert(i, '\n');
+ linestartpos = i;
+ }
+ }
+
+ css = sb.toString();
+ }
+
+ // Trim the final string (for any leading or trailing white spaces)
+ css = css.trim();
+
+ // Write the output...
+ out.write(css);
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,1151 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import org.mozilla.javascript.*;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.*;
+
+public class JavaScriptCompressor {
+
+ static final ArrayList ones;
+ static final ArrayList twos;
+ static final ArrayList threes;
+
+ static final Set builtin = new HashSet();
+ static final Map literals = new Hashtable();
+
+ static {
+
+ // This list contains all the 3 characters or less built-in global
+ // symbols available in a browser. Please add to this list if you
+ // see anything missing.
+ builtin.add("NaN");
+ builtin.add("top");
+
+ ones = new ArrayList();
+ for (char c = 'A'; c <= 'Z'; c++)
+ ones.add(Character.toString(c));
+ for (char c = 'a'; c <= 'z'; c++)
+ ones.add(Character.toString(c));
+
+ twos = new ArrayList();
+ for (int i = 0; i < ones.size(); i++) {
+ String one = (String) ones.get(i);
+ for (char c = 'A'; c <= 'Z'; c++)
+ twos.add(one + Character.toString(c));
+ for (char c = 'a'; c <= 'z'; c++)
+ twos.add(one + Character.toString(c));
+ for (char c = '0'; c <= '9'; c++)
+ twos.add(one + Character.toString(c));
+ }
+
+ // Remove two-letter JavaScript reserved words and built-in globals...
+ twos.remove("as");
+ twos.remove("is");
+ twos.remove("do");
+ twos.remove("if");
+ twos.remove("in");
+ twos.removeAll(builtin);
+
+ threes = new ArrayList();
+ for (int i = 0; i < twos.size(); i++) {
+ String two = (String) twos.get(i);
+ for (char c = 'A'; c <= 'Z'; c++)
+ threes.add(two + Character.toString(c));
+ for (char c = 'a'; c <= 'z'; c++)
+ threes.add(two + Character.toString(c));
+ for (char c = '0'; c <= '9'; c++)
+ threes.add(two + Character.toString(c));
+ }
+
+ // Remove three-letter JavaScript reserved words and built-in globals...
+ threes.remove("for");
+ threes.remove("int");
+ threes.remove("new");
+ threes.remove("try");
+ threes.remove("use");
+ threes.remove("var");
+ threes.removeAll(builtin);
+
+ // That's up to ((26+26)*(1+(26+26+10)))*(1+(26+26+10))-8
+ // (206,380 symbols per scope)
+
+ // The following list comes from org/mozilla/javascript/Decompiler.java...
+ literals.put(new Integer(Token.GET), "get ");
+ literals.put(new Integer(Token.SET), "set ");
+ literals.put(new Integer(Token.TRUE), "true");
+ literals.put(new Integer(Token.FALSE), "false");
+ literals.put(new Integer(Token.NULL), "null");
+ literals.put(new Integer(Token.THIS), "this");
+ literals.put(new Integer(Token.FUNCTION), "function ");
+ literals.put(new Integer(Token.COMMA), ",");
+ literals.put(new Integer(Token.LC), "{");
+ literals.put(new Integer(Token.RC), "}");
+ literals.put(new Integer(Token.LP), "(");
+ literals.put(new Integer(Token.RP), ")");
+ literals.put(new Integer(Token.LB), "[");
+ literals.put(new Integer(Token.RB), "]");
+ literals.put(new Integer(Token.DOT), ".");
+ literals.put(new Integer(Token.NEW), "new ");
+ literals.put(new Integer(Token.DELPROP), "delete ");
+ literals.put(new Integer(Token.IF), "if");
+ literals.put(new Integer(Token.ELSE), "else");
+ literals.put(new Integer(Token.FOR), "for");
+ literals.put(new Integer(Token.IN), " in ");
+ literals.put(new Integer(Token.WITH), "with");
+ literals.put(new Integer(Token.WHILE), "while");
+ literals.put(new Integer(Token.DO), "do");
+ literals.put(new Integer(Token.TRY), "try");
+ literals.put(new Integer(Token.CATCH), "catch");
+ literals.put(new Integer(Token.FINALLY), "finally");
+ literals.put(new Integer(Token.THROW), "throw ");
+ literals.put(new Integer(Token.SWITCH), "switch");
+ literals.put(new Integer(Token.BREAK), "break ");
+ literals.put(new Integer(Token.CONTINUE), "continue ");
+ literals.put(new Integer(Token.CASE), "case ");
+ literals.put(new Integer(Token.DEFAULT), "default");
+ literals.put(new Integer(Token.RETURN), "return ");
+ literals.put(new Integer(Token.VAR), "var ");
+ literals.put(new Integer(Token.SEMI), ";");
+ literals.put(new Integer(Token.ASSIGN), "=");
+ literals.put(new Integer(Token.ASSIGN_ADD), "+=");
+ literals.put(new Integer(Token.ASSIGN_SUB), "-=");
+ literals.put(new Integer(Token.ASSIGN_MUL), "*=");
+ literals.put(new Integer(Token.ASSIGN_DIV), "/=");
+ literals.put(new Integer(Token.ASSIGN_MOD), "%=");
+ literals.put(new Integer(Token.ASSIGN_BITOR), "|=");
+ literals.put(new Integer(Token.ASSIGN_BITXOR), "^=");
+ literals.put(new Integer(Token.ASSIGN_BITAND), "&=");
+ literals.put(new Integer(Token.ASSIGN_LSH), "<<=");
+ literals.put(new Integer(Token.ASSIGN_RSH), ">>=");
+ literals.put(new Integer(Token.ASSIGN_URSH), ">>>=");
+ literals.put(new Integer(Token.HOOK), "?");
+ literals.put(new Integer(Token.OBJECTLIT), ":");
+ literals.put(new Integer(Token.COLON), ":");
+ literals.put(new Integer(Token.OR), "||");
+ literals.put(new Integer(Token.AND), "&&");
+ literals.put(new Integer(Token.BITOR), "|");
+ literals.put(new Integer(Token.BITXOR), "^");
+ literals.put(new Integer(Token.BITAND), "&");
+ literals.put(new Integer(Token.SHEQ), "===");
+ literals.put(new Integer(Token.SHNE), "!==");
+ literals.put(new Integer(Token.EQ), "==");
+ literals.put(new Integer(Token.NE), "!=");
+ literals.put(new Integer(Token.LE), "<=");
+ literals.put(new Integer(Token.LT), "<");
+ literals.put(new Integer(Token.GE), ">=");
+ literals.put(new Integer(Token.GT), ">");
+ literals.put(new Integer(Token.INSTANCEOF), " instanceof ");
+ literals.put(new Integer(Token.LSH), "<<");
+ literals.put(new Integer(Token.RSH), ">>");
+ literals.put(new Integer(Token.URSH), ">>>");
+ literals.put(new Integer(Token.TYPEOF), "typeof ");
+ literals.put(new Integer(Token.VOID), "void ");
+ literals.put(new Integer(Token.CONST), "const ");
+ literals.put(new Integer(Token.NOT), "!");
+ literals.put(new Integer(Token.BITNOT), "~");
+ literals.put(new Integer(Token.POS), "+");
+ literals.put(new Integer(Token.NEG), "-");
+ literals.put(new Integer(Token.INC), "++");
+ literals.put(new Integer(Token.DEC), "--");
+ literals.put(new Integer(Token.ADD), "+");
+ literals.put(new Integer(Token.SUB), "-");
+ literals.put(new Integer(Token.MUL), "*");
+ literals.put(new Integer(Token.DIV), "/");
+ literals.put(new Integer(Token.MOD), "%");
+ literals.put(new Integer(Token.COLONCOLON), "::");
+ literals.put(new Integer(Token.DOTDOT), "..");
+ literals.put(new Integer(Token.DOTQUERY), ".(");
+ literals.put(new Integer(Token.XMLATTR), "@");
+ }
+
+ private static int countChar(String haystack, char needle) {
+ int idx = 0;
+ int count = 0;
+ int length = haystack.length();
+ while (idx < length) {
+ char c = haystack.charAt(idx++);
+ if (c == needle) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private static int printSourceString(String source, int offset, StringBuffer sb) {
+ int length = source.charAt(offset);
+ ++offset;
+ if ((0x8000 & length) != 0) {
+ length = ((0x7FFF & length) << 16) | source.charAt(offset);
+ ++offset;
+ }
+ if (sb != null) {
+ String str = source.substring(offset, offset + length);
+ sb.append(str);
+ }
+ return offset + length;
+ }
+
+ private static int printSourceNumber(String source,
+ int offset, StringBuffer sb) {
+ double number = 0.0;
+ char type = source.charAt(offset);
+ ++offset;
+ if (type == 'S') {
+ if (sb != null) {
+ number = source.charAt(offset);
+ }
+ ++offset;
+ } else if (type == 'J' || type == 'D') {
+ if (sb != null) {
+ long lbits;
+ lbits = (long) source.charAt(offset) << 48;
+ lbits |= (long) source.charAt(offset + 1) << 32;
+ lbits |= (long) source.charAt(offset + 2) << 16;
+ lbits |= (long) source.charAt(offset + 3);
+ if (type == 'J') {
+ number = lbits;
+ } else {
+ number = Double.longBitsToDouble(lbits);
+ }
+ }
+ offset += 4;
+ } else {
+ // Bad source
+ throw new RuntimeException();
+ }
+ if (sb != null) {
+ sb.append(ScriptRuntime.numberToString(number, 10));
+ }
+ return offset;
+ }
+
+ private static ArrayList parse(Reader in, ErrorReporter reporter)
+ throws IOException, EvaluatorException {
+
+ CompilerEnvirons env = new CompilerEnvirons();
+ Parser parser = new Parser(env, reporter);
+ parser.parse(in, null, 1);
+ String source = parser.getEncodedSource();
+
+ int offset = 0;
+ int length = source.length();
+ ArrayList tokens = new ArrayList();
+ StringBuffer sb = new StringBuffer();
+
+ while (offset < length) {
+ int tt = source.charAt(offset++);
+ switch (tt) {
+
+ case Token.IECC:
+ case Token.NAME:
+ case Token.REGEXP:
+ case Token.STRING:
+ sb.setLength(0);
+ offset = printSourceString(source, offset, sb);
+ tokens.add(new JavaScriptToken(tt, sb.toString()));
+ break;
+
+ case Token.NUMBER:
+ sb.setLength(0);
+ offset = printSourceNumber(source, offset, sb);
+ tokens.add(new JavaScriptToken(tt, sb.toString()));
+ break;
+
+ default:
+ String literal = (String) literals.get(new Integer(tt));
+ if (literal != null) {
+ tokens.add(new JavaScriptToken(tt, literal));
+ }
+ break;
+ }
+ }
+
+ return tokens;
+ }
+
+ private static ArrayList processStringLiterals(ArrayList tokens, boolean merge) {
+
+ String tv;
+ int i, length;
+ ArrayList result = new ArrayList();
+ JavaScriptToken token, prevToken, nextToken;
+
+ // Concatenate string literals that are being appended wherever
+ // it is safe to do so. Note that we take care of the case:
+ // "a" + "b".toUpperCase()
+
+ for (i = 0, length = tokens.size(); i < length; i++) {
+ token = (JavaScriptToken) tokens.get(i);
+ switch (token.getType()) {
+
+ case Token.ADD:
+ if (merge) {
+ if (i > 0 && i < length) {
+ prevToken = (JavaScriptToken) result.get(result.size() - 1);
+ nextToken = (JavaScriptToken) tokens.get(i + 1);
+ if (prevToken.getType() == Token.STRING && nextToken.getType() == Token.STRING &&
+ (i == length - 1 || ((JavaScriptToken) tokens.get(i + 2)).getType() != Token.DOT)) {
+ result.set(result.size() - 1, new JavaScriptToken(Token.STRING,
+ prevToken.getValue() + nextToken.getValue()));
+ i++; // not a good practice, but oh well...
+ break;
+ }
+ }
+ }
+
+ /* FALLSTHROUGH */
+
+ default:
+ result.add(token);
+ break;
+ }
+ }
+
+ // Second pass...
+
+ for (i = 0, length = result.size(); i < length; i++) {
+ token = (JavaScriptToken) result.get(i);
+ if (token.getType() == Token.STRING) {
+ tv = token.getValue();
+
+ // Finally, add the quoting characters and escape the string. We use
+ // the quoting character that minimizes the amount of escaping to save
+ // a few additional bytes.
+
+ char quotechar;
+ int singleQuoteCount = countChar(tv, '\'');
+ int doubleQuoteCount = countChar(tv, '"');
+ if (doubleQuoteCount <= singleQuoteCount) {
+ quotechar = '"';
+ } else {
+ quotechar = '\'';
+ }
+
+ tv = quotechar + escapeString(tv, quotechar) + quotechar;
+
+ // String concatenation transforms the old script scheme:
+ // '<scr'+'ipt ...><'+'/script>'
+ // into the following:
+ // '<script ...></script>'
+ // which breaks if this code is embedded inside an HTML document.
+ // Since this is not the right way to do this, let's fix the code by
+ // transforming all "</script" into "<\/script"
+
+ if (tv.indexOf("</script") >= 0) {
+ tv = tv.replaceAll("<\\/script", "<\\\\/script");
+ }
+
+ result.set(i, new JavaScriptToken(Token.STRING, tv));
+ }
+ }
+
+ return result;
+ }
+
+ // Add necessary escaping that was removed in Rhino's tokenizer.
+ private static String escapeString(String s, char quotechar) {
+
+ assert quotechar == '"' || quotechar == '\'';
+
+ if (s == null) {
+ return null;
+ }
+
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0, L = s.length(); i < L; i++) {
+ int c = s.charAt(i);
+ if (c == quotechar) {
+ sb.append("\\");
+ }
+ sb.append((char) c);
+ }
+
+ return sb.toString();
+ }
+
+ private ErrorReporter logger;
+
+ private boolean munge;
+ private boolean warn;
+
+ private static final int BUILDING_SYMBOL_TREE = 1;
+ private static final int CHECKING_SYMBOL_TREE = 2;
+
+ private int mode;
+ private int offset;
+ private int braceNesting;
+ private ArrayList srctokens, tokens;
+ private Stack scopes = new Stack();
+ private ScriptOrFnScope globalScope = new ScriptOrFnScope(-1, null);
+ private Hashtable indexedScopes = new Hashtable();
+
+ public JavaScriptCompressor(Reader in, ErrorReporter reporter)
+ throws IOException, EvaluatorException {
+
+ this.logger = reporter;
+ this.srctokens = parse(in, reporter);
+ }
+
+ public void compress(Writer out, int linebreak, boolean munge, boolean warn,
+ boolean preserveAllSemiColons, boolean preserveStringLiterals)
+ throws IOException {
+
+ this.munge = munge;
+ this.warn = warn;
+
+ this.tokens = processStringLiterals(this.srctokens, !preserveStringLiterals);
+
+ buildSymbolTree();
+ mungeSymboltree();
+ StringBuffer sb = printSymbolTree(linebreak, preserveAllSemiColons);
+
+ out.write(sb.toString());
+ }
+
+ private ScriptOrFnScope getCurrentScope() {
+ return (ScriptOrFnScope) scopes.peek();
+ }
+
+ private void enterScope(ScriptOrFnScope scope) {
+ scopes.push(scope);
+ }
+
+ private void leaveCurrentScope() {
+ scopes.pop();
+ }
+
+ private JavaScriptToken consumeToken() {
+ return (JavaScriptToken) tokens.get(offset++);
+ }
+
+ private JavaScriptToken getToken(int delta) {
+ return (JavaScriptToken) tokens.get(offset + delta);
+ }
+
+ /*
+ * Returns the identifier for the specified symbol defined in
+ * the specified scope or in any scope above it. Returns null
+ * if this symbol does not have a corresponding identifier.
+ */
+ private JavaScriptIdentifier getIdentifier(String symbol, ScriptOrFnScope scope) {
+ JavaScriptIdentifier identifier;
+ while (scope != null) {
+ identifier = scope.getIdentifier(symbol);
+ if (identifier != null) {
+ return identifier;
+ }
+ scope = scope.getParentScope();
+ }
+ return null;
+ }
+
+ /*
+ * If either 'eval' or 'with' is used in a local scope, we must make
+ * sure that all containing local scopes don't get munged. Otherwise,
+ * the obfuscation would potentially introduce bugs.
+ */
+ private void protectScopeFromObfuscation(ScriptOrFnScope scope) {
+ assert scope != null;
+
+ if (scope == globalScope) {
+ // The global scope does not get obfuscated,
+ // so we don't need to worry about it...
+ return;
+ }
+
+ // Find the highest local scope containing the specified scope.
+ while (scope.getParentScope() != globalScope) {
+ scope = scope.getParentScope();
+ }
+
+ assert scope.getParentScope() == globalScope;
+ scope.preventMunging();
+ }
+
+ private String getDebugString(int max) {
+ assert max > 0;
+ StringBuffer result = new StringBuffer();
+ int start = Math.max(offset - max, 0);
+ int end = Math.min(offset + max, tokens.size());
+ for (int i = start; i < end; i++) {
+ JavaScriptToken token = (JavaScriptToken) tokens.get(i);
+ if (i == offset)
+ result.append(" ---> ");
+ result.append(token.getValue());
+ if (i == offset)
+ result.append(" <--- ");
+ }
+ return result.toString();
+ }
+
+ private void warn(String message, boolean showDebugString) {
+ if (warn) {
+ if (showDebugString) {
+ message = message + "\n" + getDebugString(10);
+ }
+ logger.warning(message, null, -1, null, -1);
+ }
+ }
+
+ private void parseFunctionDeclaration() {
+
+ String symbol;
+ JavaScriptToken token;
+ ScriptOrFnScope currentScope, fnScope;
+ JavaScriptIdentifier identifier;
+
+ currentScope = getCurrentScope();
+
+ token = consumeToken();
+ if (token.getType() == Token.NAME) {
+ if (mode == BUILDING_SYMBOL_TREE) {
+ // Get the name of the function and declare it in the current scope.
+ symbol = token.getValue();
+ if (currentScope.getIdentifier(symbol) != null) {
+ warn("[WARNING] The function " + symbol + " has already been declared in the same scope...", true);
+ }
+ currentScope.declareIdentifier(symbol);
+ }
+ token = consumeToken();
+ }
+
+ assert token.getType() == Token.LP;
+ if (mode == BUILDING_SYMBOL_TREE) {
+ fnScope = new ScriptOrFnScope(braceNesting, currentScope);
+ indexedScopes.put(new Integer(offset), fnScope);
+ } else {
+ fnScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset));
+ }
+
+ // Parse function arguments.
+ int argpos = 0;
+ while ((token = consumeToken()).getType() != Token.RP) {
+ assert token.getType() == Token.NAME ||
+ token.getType() == Token.COMMA;
+ if (token.getType() == Token.NAME && mode == BUILDING_SYMBOL_TREE) {
+ symbol = token.getValue();
+ identifier = fnScope.declareIdentifier(symbol);
+ if (symbol.equals("$super") && argpos == 0) {
+ // Exception for Prototype 1.6...
+ identifier.preventMunging();
+ }
+ argpos++;
+ }
+ }
+
+ token = consumeToken();
+ assert token.getType() == Token.LC;
+ braceNesting++;
+
+ token = getToken(0);
+ if (token.getType() == Token.STRING &&
+ getToken(1).getType() == Token.SEMI) {
+ // This is a hint. Hints are empty statements that look like
+ // "localvar1:nomunge, localvar2:nomunge"; They allow developers
+ // to prevent specific symbols from getting obfuscated (some heretic
+ // implementations, such as Prototype 1.6, require specific variable
+ // names, such as $super for example, in order to work appropriately.
+ // Note: right now, only "nomunge" is supported in the right hand side
+ // of a hint. However, in the future, the right hand side may contain
+ // other values.
+ consumeToken();
+ String hints = token.getValue();
+ // Remove the leading and trailing quotes...
+ hints = hints.substring(1, hints.length() - 1).trim();
+ StringTokenizer st1 = new StringTokenizer(hints, ",");
+ while (st1.hasMoreTokens()) {
+ String hint = st1.nextToken();
+ int idx = hint.indexOf(':');
+ if (idx <= 0 || idx >= hint.length() - 1) {
+ if (mode == BUILDING_SYMBOL_TREE) {
+ // No need to report the error twice, hence the test...
+ warn("[WARNING] Invalid hint syntax: " + hint, true);
+ }
+ break;
+ }
+ String variableName = hint.substring(0, idx).trim();
+ String variableType = hint.substring(idx + 1).trim();
+ if (mode == BUILDING_SYMBOL_TREE) {
+ fnScope.addHint(variableName, variableType);
+ } else if (mode == CHECKING_SYMBOL_TREE) {
+ identifier = fnScope.getIdentifier(variableName);
+ if (identifier != null) {
+ if (variableType.equals("nomunge")) {
+ identifier.preventMunging();
+ } else {
+ warn("[WARNING] Unsupported hint value: " + hint, true);
+ }
+ } else {
+ warn("[WARNING] Hint refers to an unknown identifier: " + hint, true);
+ }
+ }
+ }
+ }
+
+ parseScope(fnScope);
+ }
+
+ private void parseCatch() {
+
+ String symbol;
+ JavaScriptToken token;
+ ScriptOrFnScope currentScope;
+ JavaScriptIdentifier identifier;
+
+ token = getToken(-1);
+ assert token.getType() == Token.CATCH;
+ token = consumeToken();
+ assert token.getType() == Token.LP;
+ token = consumeToken();
+ assert token.getType() == Token.NAME;
+
+ symbol = token.getValue();
+ currentScope = getCurrentScope();
+
+ if (mode == BUILDING_SYMBOL_TREE) {
+ // We must declare the exception identifier in the containing function
+ // scope to avoid errors related to the obfuscation process. No need to
+ // display a warning if the symbol was already declared here...
+ currentScope.declareIdentifier(symbol);
+ } else {
+ identifier = getIdentifier(symbol, currentScope);
+ identifier.incrementRefcount();
+ }
+
+ token = consumeToken();
+ assert token.getType() == Token.RP;
+ }
+
+ private void parseExpression() {
+
+ // Parse the expression until we encounter a comma or a semi-colon
+ // in the same brace nesting, bracket nesting and paren nesting.
+ // Parse functions if any...
+
+ String symbol;
+ JavaScriptToken token;
+ ScriptOrFnScope currentScope;
+ JavaScriptIdentifier identifier;
+
+ int expressionBraceNesting = braceNesting;
+ int bracketNesting = 0;
+ int parensNesting = 0;
+
+ int length = tokens.size();
+
+ while (offset < length) {
+
+ token = consumeToken();
+ currentScope = getCurrentScope();
+
+ switch (token.getType()) {
+
+ case Token.SEMI:
+ case Token.COMMA:
+ if (braceNesting == expressionBraceNesting &&
+ bracketNesting == 0 &&
+ parensNesting == 0) {
+ return;
+ }
+ break;
+
+ case Token.FUNCTION:
+ parseFunctionDeclaration();
+ break;
+
+ case Token.LC:
+ braceNesting++;
+ break;
+
+ case Token.RC:
+ braceNesting--;
+ assert braceNesting >= expressionBraceNesting;
+ break;
+
+ case Token.LB:
+ bracketNesting++;
+ break;
+
+ case Token.RB:
+ bracketNesting--;
+ break;
+
+ case Token.LP:
+ parensNesting++;
+ break;
+
+ case Token.RP:
+ parensNesting--;
+ break;
+
+ case Token.IECC:
+ if (mode == BUILDING_SYMBOL_TREE) {
+ protectScopeFromObfuscation(currentScope);
+ warn("[WARNING] Using JScript conditional comments is not recommended..." + (munge ? "\n[INFO] Using JSCript conditional comments reduces the level of compression!" : ""), true);
+ }
+ break;
+
+ case Token.NAME:
+ symbol = token.getValue();
+
+ if (mode == BUILDING_SYMBOL_TREE) {
+
+ if (symbol.equals("eval")) {
+
+ protectScopeFromObfuscation(currentScope);
+ warn("[WARNING] Using 'eval' is not recommended..." + (munge ? "\n[INFO] Using 'eval' reduces the level of compression!" : ""), true);
+
+ }
+
+ } else if (mode == CHECKING_SYMBOL_TREE) {
+
+ if ((offset < 2 ||
+ (getToken(-2).getType() != Token.DOT &&
+ getToken(-2).getType() != Token.GET &&
+ getToken(-2).getType() != Token.SET)) &&
+ getToken(0).getType() != Token.OBJECTLIT) {
+
+ identifier = getIdentifier(symbol, currentScope);
+
+ if (identifier == null) {
+
+ if (symbol.length() <= 3 && !builtin.contains(symbol)) {
+ // Here, we found an undeclared and un-namespaced symbol that is
+ // 3 characters or less in length. Declare it in the global scope.
+ // We don't need to declare longer symbols since they won't cause
+ // any conflict with other munged symbols.
+ globalScope.declareIdentifier(symbol);
+ warn("[WARNING] Found an undeclared symbol: " + symbol, true);
+ }
+
+ } else {
+
+ identifier.incrementRefcount();
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ private void parseScope(ScriptOrFnScope scope) {
+
+ String symbol;
+ JavaScriptToken token;
+ JavaScriptIdentifier identifier;
+
+ int length = tokens.size();
+
+ enterScope(scope);
+
+ while (offset < length) {
+
+ token = consumeToken();
+
+ switch (token.getType()) {
+
+ case Token.VAR:
+ case Token.CONST:
+
+ // The var keyword is followed by at least one symbol name.
+ // If several symbols follow, they are comma separated.
+ for (; ;) {
+ token = consumeToken();
+
+ assert token.getType() == Token.NAME;
+
+ if (mode == BUILDING_SYMBOL_TREE) {
+ symbol = token.getValue();
+ if (scope.getIdentifier(symbol) == null) {
+ scope.declareIdentifier(symbol);
+ } else {
+ warn("[WARNING] The variable " + symbol + " has already been declared in the same scope...", true);
+ }
+ }
+
+ token = getToken(0);
+
+ assert token.getType() == Token.SEMI ||
+ token.getType() == Token.ASSIGN ||
+ token.getType() == Token.COMMA ||
+ token.getType() == Token.IN;
+
+ if (token.getType() == Token.IN) {
+ break;
+ } else {
+ parseExpression();
+ token = getToken(-1);
+ if (token.getType() == Token.SEMI) {
+ break;
+ }
+ }
+ }
+ break;
+
+ case Token.FUNCTION:
+ parseFunctionDeclaration();
+ break;
+
+ case Token.LC:
+ braceNesting++;
+ break;
+
+ case Token.RC:
+ braceNesting--;
+ assert braceNesting >= scope.getBraceNesting();
+ if (braceNesting == scope.getBraceNesting()) {
+ leaveCurrentScope();
+ return;
+ }
+ break;
+
+ case Token.WITH:
+ if (mode == BUILDING_SYMBOL_TREE) {
+ // Inside a 'with' block, it is impossible to figure out
+ // statically whether a symbol is a local variable or an
+ // object member. As a consequence, the only thing we can
+ // do is turn the obfuscation off for the highest scope
+ // containing the 'with' block.
+ protectScopeFromObfuscation(scope);
+ warn("[WARNING] Using 'with' is not recommended" + (munge ? "(and it reduces the level of compression)" : ""), true);
+ }
+ break;
+
+ case Token.CATCH:
+ parseCatch();
+ break;
+
+ case Token.IECC:
+ if (mode == BUILDING_SYMBOL_TREE) {
+ protectScopeFromObfuscation(scope);
+ warn("[WARNING] Using JScript conditional comments is not recommended..." + (munge ? "\n[INFO] Using JSCript conditional comments reduces the level of compression!" : ""), true);
+ }
+ break;
+
+ case Token.NAME:
+ symbol = token.getValue();
+
+ if (mode == BUILDING_SYMBOL_TREE) {
+
+ if (symbol.equals("eval")) {
+
+ protectScopeFromObfuscation(scope);
+ warn("[WARNING] Using 'eval' is not recommended..." + (munge ? "\n[INFO] Using 'eval' reduces the level of compression!" : ""), true);
+
+ }
+
+ } else if (mode == CHECKING_SYMBOL_TREE) {
+
+ if ((offset < 2 || getToken(-2).getType() != Token.DOT) &&
+ getToken(0).getType() != Token.OBJECTLIT) {
+
+ identifier = getIdentifier(symbol, scope);
+
+ if (identifier == null) {
+
+ if (symbol.length() <= 3 && !builtin.contains(symbol)) {
+ // Here, we found an undeclared and un-namespaced symbol that is
+ // 3 characters or less in length. Declare it in the global scope.
+ // We don't need to declare longer symbols since they won't cause
+ // any conflict with other munged symbols.
+ globalScope.declareIdentifier(symbol);
+ warn("[WARNING] Found an undeclared symbol: " + symbol, true);
+ }
+
+ } else {
+
+ identifier.incrementRefcount();
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ private void buildSymbolTree() {
+ offset = 0;
+ braceNesting = 0;
+ scopes.clear();
+ indexedScopes.clear();
+ indexedScopes.put(new Integer(0), globalScope);
+ mode = BUILDING_SYMBOL_TREE;
+ parseScope(globalScope);
+ }
+
+ private void mungeSymboltree() {
+
+ if (!munge) {
+ return;
+ }
+
+ // One problem with obfuscation resides in the use of undeclared
+ // and un-namespaced global symbols that are 3 characters or less
+ // in length. Here is an example:
+ //
+ // var declaredGlobalVar;
+ //
+ // function declaredGlobalFn() {
+ // var localvar;
+ // localvar = abc; // abc is an undeclared global symbol
+ // }
+ //
+ // In the example above, there is a slim chance that localvar may be
+ // munged to 'abc', conflicting with the undeclared global symbol
+ // abc, creating a potential bug. The following code detects such
+ // global symbols. This must be done AFTER the entire file has been
+ // parsed, and BEFORE munging the symbol tree. Note that declaring
+ // extra symbols in the global scope won't hurt.
+ //
+ // Note: Since we go through all the tokens to do this, we also use
+ // the opportunity to count how many times each identifier is used.
+
+ offset = 0;
+ braceNesting = 0;
+ scopes.clear();
+ mode = CHECKING_SYMBOL_TREE;
+ parseScope(globalScope);
+ globalScope.munge();
+ }
+
+ private StringBuffer printSymbolTree(int linebreakpos, boolean preserveAllSemiColons)
+ throws IOException {
+
+ offset = 0;
+ braceNesting = 0;
+ scopes.clear();
+
+ String symbol;
+ JavaScriptToken token;
+ ScriptOrFnScope currentScope;
+ JavaScriptIdentifier identifier;
+
+ int length = tokens.size();
+ StringBuffer result = new StringBuffer();
+
+ int linestartpos = 0;
+
+ enterScope(globalScope);
+
+ while (offset < length) {
+
+ token = consumeToken();
+ symbol = token.getValue();
+ currentScope = getCurrentScope();
+
+ switch (token.getType()) {
+
+ case Token.NAME:
+
+ if (offset >= 2 && getToken(-2).getType() == Token.DOT ||
+ getToken(0).getType() == Token.OBJECTLIT) {
+
+ result.append(symbol);
+
+ } else {
+
+ identifier = getIdentifier(symbol, currentScope);
+ if (identifier != null) {
+ if (identifier.getMungedValue() != null) {
+ result.append(identifier.getMungedValue());
+ } else {
+ result.append(symbol);
+ }
+ if (currentScope != globalScope && identifier.getRefcount() == 0) {
+ warn("[WARNING] The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more efficient way.", true);
+ }
+ } else {
+ result.append(symbol);
+ }
+ }
+ break;
+
+ case Token.REGEXP:
+ case Token.NUMBER:
+ case Token.STRING:
+ result.append(symbol);
+ break;
+
+ case Token.ADD:
+ case Token.SUB:
+ result.append((String) literals.get(new Integer(token.getType())));
+ if (offset < length) {
+ token = getToken(0);
+ if (token.getType() == Token.INC ||
+ token.getType() == Token.DEC ||
+ token.getType() == Token.ADD ||
+ token.getType() == Token.DEC) {
+ // Handle the case x +/- ++/-- y
+ // We must keep a white space here. Otherwise, x +++ y would be
+ // interpreted as x ++ + y by the compiler, which is a bug (due
+ // to the implicit assignment being done on the wrong variable)
+ result.append(" ");
+ } else if (token.getType() == Token.POS && getToken(-1).getType() == Token.ADD ||
+ token.getType() == Token.NEG && getToken(-1).getType() == Token.SUB) {
+ // Handle the case x + + y and x - - y
+ result.append(" ");
+ }
+ }
+ break;
+
+ case Token.FUNCTION:
+ result.append("function");
+ token = consumeToken();
+ if (token.getType() == Token.NAME) {
+ result.append(" ");
+ symbol = token.getValue();
+ identifier = getIdentifier(symbol, currentScope);
+ assert identifier != null;
+ if (identifier.getMungedValue() != null) {
+ result.append(identifier.getMungedValue());
+ } else {
+ result.append(symbol);
+ }
+ if (currentScope != globalScope && identifier.getRefcount() == 0) {
+ warn("[WARNING] The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more efficient way.", true);
+ }
+ token = consumeToken();
+ }
+ assert token.getType() == Token.LP;
+ result.append("(");
+ currentScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset));
+ enterScope(currentScope);
+ while ((token = consumeToken()).getType() != Token.RP) {
+ assert token.getType() == Token.NAME || token.getType() == Token.COMMA;
+ if (token.getType() == Token.NAME) {
+ symbol = token.getValue();
+ identifier = getIdentifier(symbol, currentScope);
+ assert identifier != null;
+ if (identifier.getMungedValue() != null) {
+ result.append(identifier.getMungedValue());
+ } else {
+ result.append(symbol);
+ }
+ } else if (token.getType() == Token.COMMA) {
+ result.append(",");
+ }
+ }
+ result.append(")");
+ token = consumeToken();
+ assert token.getType() == Token.LC;
+ result.append("{");
+ braceNesting++;
+ token = getToken(0);
+ if (token.getType() == Token.STRING) {
+ // This is a hint. Skip it!
+ consumeToken();
+ token = getToken(0);
+ assert token.getType() == Token.SEMI;
+ consumeToken();
+ }
+ break;
+
+ case Token.RETURN:
+ result.append("return");
+ // No space needed after 'return' when followed
+ // by '(', '[', '{', a string or a regexp.
+ if (offset < length) {
+ token = getToken(0);
+ if (token.getType() != Token.LP &&
+ token.getType() != Token.LB &&
+ token.getType() != Token.LC &&
+ token.getType() != Token.STRING &&
+ token.getType() != Token.REGEXP) {
+ result.append(" ");
+ }
+ }
+ break;
+
+ case Token.CASE:
+ result.append("case");
+ // White-space needed after 'case' when not followed by a string.
+ if (offset < length && getToken(0).getType() != Token.STRING) {
+ result.append(" ");
+ }
+ break;
+
+ case Token.THROW:
+ // White-space needed after 'throw' when not followed by a string.
+ result.append("throw");
+ if (offset < length && getToken(0).getType() != Token.STRING) {
+ result.append(" ");
+ }
+ break;
+
+ case Token.BREAK:
+ result.append("break");
+ if (offset < length && getToken(0).getType() != Token.SEMI) {
+ // If 'break' is not followed by a semi-colon, it must be
+ // followed by a label, hence the need for a white space.
+ result.append(" ");
+ }
+ break;
+
+ case Token.CONTINUE:
+ result.append("continue");
+ if (offset < length && getToken(0).getType() != Token.SEMI) {
+ // If 'continue' is not followed by a semi-colon, it must be
+ // followed by a label, hence the need for a white space.
+ result.append(" ");
+ }
+ break;
+
+ case Token.LC:
+ result.append("{");
+ braceNesting++;
+ break;
+
+ case Token.RC:
+ result.append("}");
+ braceNesting--;
+ assert braceNesting >= currentScope.getBraceNesting();
+ if (braceNesting == currentScope.getBraceNesting()) {
+ leaveCurrentScope();
+ }
+ break;
+
+ case Token.SEMI:
+ // No need to output a semi-colon if the next character is a right-curly...
+ if (preserveAllSemiColons || offset < length && getToken(0).getType() != Token.RC)
+ result.append(";");
+ if (linebreakpos >= 0 && result.length() - linestartpos > linebreakpos) {
+ // Some source control tools don't like it when files containing lines longer
+ // than, say 8000 characters, are checked in. The linebreak option is used in
+ // that case to split long lines after a specific column.
+ result.append("\n");
+ linestartpos = result.length();
+ }
+ break;
+
+ case Token.IECC:
+ result.append("/*");
+ result.append(symbol);
+ result.append("*/");
+ break;
+
+ default:
+ String literal = (String) literals.get(new Integer(token.getType()));
+ if (literal != null) {
+ result.append(literal);
+ } else {
+ warn("[WARNING] This symbol cannot be printed: " + symbol, true);
+ }
+ break;
+ }
+ }
+
+ return result;
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,56 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import org.mozilla.javascript.ErrorReporter;
+import org.mozilla.javascript.EvaluatorException;
+
+import java.io.PrintStream;
+
+class JavaScriptErrorReporter implements ErrorReporter {
+
+ private boolean reportWarnings;
+ private PrintStream err;
+
+ JavaScriptErrorReporter(PrintStream err, boolean reportWarnings) {
+ this.err = err;
+ this.reportWarnings = reportWarnings;
+ }
+
+ public void warning(String message, String sourceName,
+ int line, String lineSource, int lineOffset) {
+ if (reportWarnings) {
+ reportMessage(message, sourceName, line, lineSource, lineOffset);
+ }
+ }
+
+ public EvaluatorException runtimeError(String message, String sourceName,
+ int line, String lineSource, int lineOffset) {
+ error(message, sourceName, line, lineSource, lineOffset);
+ return new EvaluatorException(message);
+ }
+
+ public void error(String message, String sourceName,
+ int line, String lineSource, int lineOffset) {
+ reportMessage(message, sourceName, line, lineSource, lineOffset);
+ }
+
+ private void reportMessage(String message, String sourceName,
+ int line, String lineSource, int lineOffset) {
+ if (line < 0) {
+ if (message.length() == 0) {
+ err.println("An unknown error occurred...");
+ } else {
+ err.println(message);
+ }
+ } else {
+ err.println(line + ':' + lineOffset + ':' + message);
+ }
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,55 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import org.mozilla.javascript.Token;
+
+/**
+ * JavaScriptIdentifier represents a variable/function identifier.
+ */
+class JavaScriptIdentifier extends JavaScriptToken {
+
+ private int refcount = 0;
+ private String mungedValue;
+ private ScriptOrFnScope declaredScope;
+ private boolean markedForMunging = true;
+
+ JavaScriptIdentifier(String value, ScriptOrFnScope declaredScope) {
+ super(Token.NAME, value);
+ this.declaredScope = declaredScope;
+ }
+
+ ScriptOrFnScope getDeclaredScope() {
+ return declaredScope;
+ }
+
+ void setMungedValue(String value) {
+ mungedValue = value;
+ }
+
+ String getMungedValue() {
+ return mungedValue;
+ }
+
+ void preventMunging() {
+ markedForMunging = false;
+ }
+
+ boolean isMarkedForMunging() {
+ return markedForMunging;
+ }
+
+ void incrementRefcount() {
+ refcount++;
+ }
+
+ int getRefcount() {
+ return refcount;
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,28 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+public class JavaScriptToken {
+
+ private int type;
+ private String value;
+
+ JavaScriptToken(int type, String value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ int getType() {
+ return type;
+ }
+
+ String getValue() {
+ return value;
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,156 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte(a)yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+class ScriptOrFnScope {
+
+ private int braceNesting;
+ private ScriptOrFnScope parentScope;
+ private ArrayList subScopes;
+ private Hashtable identifiers = new Hashtable();
+ private Hashtable hints = new Hashtable();
+ private boolean markedForMunging = true;
+
+ ScriptOrFnScope(int braceNesting, ScriptOrFnScope parentScope) {
+ this.braceNesting = braceNesting;
+ this.parentScope = parentScope;
+ this.subScopes = new ArrayList();
+ if (parentScope != null) {
+ parentScope.subScopes.add(this);
+ }
+ }
+
+ int getBraceNesting() {
+ return braceNesting;
+ }
+
+ ScriptOrFnScope getParentScope() {
+ return parentScope;
+ }
+
+ JavaScriptIdentifier declareIdentifier(String symbol) {
+ JavaScriptIdentifier identifier = (JavaScriptIdentifier) identifiers.get(symbol);
+ if (identifier == null) {
+ identifier = new JavaScriptIdentifier(symbol, this);
+ identifiers.put(symbol, identifier);
+ }
+ return identifier;
+ }
+
+ JavaScriptIdentifier getIdentifier(String symbol) {
+ return (JavaScriptIdentifier) identifiers.get(symbol);
+ }
+
+ void addHint(String variableName, String variableType) {
+ hints.put(variableName, variableType);
+ }
+
+ void preventMunging() {
+ if (parentScope != null) {
+ // The symbols in the global scope don't get munged,
+ // but the sub-scopes it contains do get munged.
+ markedForMunging = false;
+ }
+ }
+
+ private ArrayList getUsedSymbols() {
+ ArrayList result = new ArrayList();
+ Enumeration elements = identifiers.elements();
+ while (elements.hasMoreElements()) {
+ JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement();
+ String mungedValue = identifier.getMungedValue();
+ if (mungedValue == null) {
+ mungedValue = identifier.getValue();
+ }
+ result.add(mungedValue);
+ }
+ return result;
+ }
+
+ private ArrayList getAllUsedSymbols() {
+ ArrayList result = new ArrayList();
+ ScriptOrFnScope scope = this;
+ while (scope != null) {
+ result.addAll(scope.getUsedSymbols());
+ scope = scope.parentScope;
+ }
+ return result;
+ }
+
+ void munge() {
+
+ if (!markedForMunging) {
+ // Stop right here if this scope was flagged as unsafe for munging.
+ return;
+ }
+
+ int pickFromSet = 1;
+
+ // Do not munge symbols in the global scope!
+ if (parentScope != null) {
+
+ ArrayList freeSymbols = new ArrayList();
+
+ freeSymbols.addAll(JavaScriptCompressor.ones);
+ freeSymbols.removeAll(getAllUsedSymbols());
+ if (freeSymbols.size() == 0) {
+ pickFromSet = 2;
+ freeSymbols.addAll(JavaScriptCompressor.twos);
+ freeSymbols.removeAll(getAllUsedSymbols());
+ }
+ if (freeSymbols.size() == 0) {
+ pickFromSet = 3;
+ freeSymbols.addAll(JavaScriptCompressor.threes);
+ freeSymbols.removeAll(getAllUsedSymbols());
+ }
+ if (freeSymbols.size() == 0) {
+ System.err.println("The YUI Compressor ran out of symbols. Aborting...");
+ System.exit(1);
+ }
+
+ Enumeration elements = identifiers.elements();
+ while (elements.hasMoreElements()) {
+ if (freeSymbols.size() == 0) {
+ pickFromSet++;
+ if (pickFromSet == 2) {
+ freeSymbols.addAll(JavaScriptCompressor.twos);
+ } else if (pickFromSet == 3) {
+ freeSymbols.addAll(JavaScriptCompressor.threes);
+ } else {
+ System.err.println("The YUI Compressor ran out of symbols. Aborting...");
+ System.exit(1);
+ }
+ // It is essential to remove the symbols already used in
+ // the containing scopes, or some of the variables declared
+ // in the containing scopes will be redeclared, which can
+ // lead to errors.
+ freeSymbols.removeAll(getAllUsedSymbols());
+ }
+
+ String mungedValue;
+ JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement();
+ if (identifier.isMarkedForMunging()) {
+ mungedValue = (String) freeSymbols.remove(0);
+ } else {
+ mungedValue = identifier.getValue();
+ }
+ identifier.setMungedValue(mungedValue);
+ }
+ }
+
+ for (int i = 0; i < subScopes.size(); i++) {
+ ScriptOrFnScope scope = (ScriptOrFnScope) subScopes.get(i);
+ scope.munge();
+ }
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,92 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.plexus.util.DirectoryScanner;
+import org.codehaus.plexus.util.IOUtil;
+
+public class Aggregation {
+ public File output;
+ public File sourceDirectory;
+ public String[] includes;
+ public String[] excludes;
+ public boolean removeIncluded = false;
+ public boolean insertNewLine = false;
+
+ public void run(File outputDirectory) throws Exception {
+ if(null == sourceDirectory){
+ sourceDirectory = outputDirectory;
+ }
+ List<File> files = getIncludedFiles();
+ if (files.size() != 0) {
+ FileOutputStream out = new FileOutputStream(output);
+ try {
+ for (File file : files) {
+ FileInputStream in = new FileInputStream(file);
+ try {
+ IOUtil.copy(in, out);
+ if (insertNewLine) {
+ out.write('\n');
+ }
+ if (removeIncluded) {
+ file.delete();
+ }
+ } finally {
+ IOUtil.close(in);
+ in = null;
+ }
+ }
+ } finally {
+ IOUtil.close(out);
+ out = null;
+ }
+ }
+ }
+
+ protected List<File> getIncludedFiles() throws Exception {
+ ArrayList<File> back = new ArrayList<File>();
+ if (includes != null) {
+ for (String include : includes) {
+ addInto(include, back);
+ }
+ }
+ return back;
+ }
+
+ private void addInto(String include, List<File> includedFiles) throws Exception {
+ if (include.indexOf('*') > -1) {
+ DirectoryScanner scanner = newScanner();
+ scanner.setIncludes(new String[] { include });
+ scanner.scan();
+ String[] rpaths = scanner.getIncludedFiles();
+ for (String rpath : rpaths) {
+ File file = new File(scanner.getBasedir(), rpath);
+ if (!includedFiles.contains(file)) {
+ includedFiles.add(file);
+ }
+ }
+ } else {
+ File file = new File(include);
+ if (!file.isAbsolute()) {
+ file = new File(output.getParentFile(), include);
+ }
+ if (!includedFiles.contains(file)) {
+ includedFiles.add(file);
+ }
+ }
+ }
+
+ private DirectoryScanner newScanner() throws Exception {
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setBasedir(sourceDirectory);
+ if ((excludes != null) && (excludes.length != 0)) {
+ scanner.setExcludes(excludes);
+ }
+ scanner.addDefaultExcludes();
+ return scanner;
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,354 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import org.codehaus.plexus.util.IOUtil;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ErrorReporter;
+import org.mozilla.javascript.EvaluatorException;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.WrappedException;
+
+/**
+ * The BasicRhinoShell program.
+ *
+ * Can execute scripts interactively or in batch mode at the command line. An
+ * example of controlling the JavaScript engine.
+ *
+ * @author Norris Boyd
+ * @based http://lxr.mozilla.org/mozilla/source/js/rhino/examples/BasicRhinoShell.java
+ * (2007-08-30)
+ */
+@SuppressWarnings("serial")
+public class BasicRhinoShell extends ScriptableObject {
+
+ @Override
+ public String getClassName() {
+ return "global";
+ }
+
+ /**
+ * Main entry point.
+ *
+ * Process arguments as would a normal Java program. Also create a new
+ * Context and associate it with the current thread. Then set up the
+ * execution environment and begin to execute scripts.
+ */
+ public static void exec(String args[], ErrorReporter reporter) {
+ // Associate a new Context with this thread
+ Context cx = Context.enter();
+ cx.setErrorReporter(reporter);
+ try {
+ // Initialize the standard objects (Object, Function, etc.)
+ // This must be done before scripts can be executed.
+ BasicRhinoShell BasicRhinoShell = new BasicRhinoShell();
+ cx.initStandardObjects(BasicRhinoShell);
+
+ // Define some global functions particular to the BasicRhinoShell.
+ // Note
+ // that these functions are not part of ECMA.
+ String[] names = { "print", "quit", "version", "load", "help", "readFile" };
+ BasicRhinoShell.defineFunctionProperties(names, BasicRhinoShell.class, ScriptableObject.DONTENUM);
+
+ args = processOptions(cx, args);
+
+ // Set up "arguments" in the global scope to contain the command
+ // line arguments after the name of the script to execute
+ Object[] array;
+ if (args.length == 0) {
+ array = new Object[0];
+ } else {
+ int length = args.length - 1;
+ array = new Object[length];
+ System.arraycopy(args, 1, array, 0, length);
+ }
+ Scriptable argsObj = cx.newArray(BasicRhinoShell, array);
+ BasicRhinoShell.defineProperty("arguments", argsObj, ScriptableObject.DONTENUM);
+
+ BasicRhinoShell.processSource(cx, args.length == 0 ? null : args[0]);
+ } finally {
+ Context.exit();
+ }
+ }
+
+ /**
+ * Parse arguments.
+ */
+ public static String[] processOptions(Context cx, String args[]) {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (!arg.startsWith("-")) {
+ String[] result = new String[args.length - i];
+ for (int j = i; j < args.length; j++) {
+ result[j - i] = args[j];
+ }
+ return result;
+ }
+ if (arg.equals("-version")) {
+ if (++i == args.length) {
+ usage(arg);
+ }
+ double d = Context.toNumber(args[i]);
+ if (d != d) {
+ usage(arg);
+ }
+ cx.setLanguageVersion((int) d);
+ continue;
+ }
+ usage(arg);
+ }
+ return new String[0];
+ }
+
+ /**
+ * Print a usage message.
+ */
+ private static void usage(String s) {
+ p("Didn't understand \"" + s + "\".");
+ p("Valid arguments are:");
+ p("-version 100|110|120|130|140|150|160|170");
+ System.exit(1);
+ }
+
+ /**
+ * Print a help message.
+ *
+ * This method is defined as a JavaScript function.
+ */
+ public void help() {
+ p("");
+ p("Command Description");
+ p("======= ===========");
+ p("help() Display usage and help messages. ");
+ p("defineClass(className) Define an extension using the Java class");
+ p(" named with the string argument. ");
+ p(" Uses ScriptableObject.defineClass(). ");
+ p("load(['foo.js', ...]) Load JavaScript source files named by ");
+ p(" string arguments. ");
+ p("loadClass(className) Load a class named by a string argument.");
+ p(" The class must be a script compiled to a");
+ p(" class file. ");
+ p("print([expr ...]) Evaluate and print expressions. ");
+ p("quit() Quit the BasicRhinoShell. ");
+ p("version([number]) Get or set the JavaScript version number.");
+ p("");
+ }
+
+ /**
+ * Print the string values of its arguments.
+ *
+ * This method is defined as a JavaScript function. Note that its arguments
+ * are of the "varargs" form, which allows it to handle an arbitrary number
+ * of arguments supplied to the JavaScript function.
+ *
+ */
+ public static void print(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
+ for (int i = 0; i < args.length; i++) {
+ if (i > 0) {
+ System.out.print(" ");
+ }
+
+ // Convert the arbitrary JavaScript value into a string form.
+ String s = Context.toString(args[i]);
+
+ System.out.print(s);
+ }
+ System.out.println();
+ }
+
+ /**
+ * Quit the BasicRhinoShell.
+ *
+ * This only affects the interactive mode.
+ *
+ * This method is defined as a JavaScript function.
+ */
+ public void quit() {
+ quitting = true;
+ }
+
+ /**
+ * This method is defined as a JavaScript function.
+ */
+ public String readFile(String path) {
+ try {
+ return IOUtil.toString(new FileInputStream(path));
+ } catch (RuntimeException exc) {
+ throw exc;
+ } catch (Exception exc) {
+ throw new RuntimeException("wrap: " + exc.getMessage(), exc);
+ }
+ }
+
+ /**
+ * Get and set the language version.
+ *
+ * This method is defined as a JavaScript function.
+ */
+ public static double version(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
+ double result = cx.getLanguageVersion();
+ if (args.length > 0) {
+ double d = Context.toNumber(args[0]);
+ cx.setLanguageVersion((int) d);
+ }
+ return result;
+ }
+
+ /**
+ * Load and execute a set of JavaScript source files.
+ *
+ * This method is defined as a JavaScript function.
+ *
+ */
+ public static void load(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
+ BasicRhinoShell BasicRhinoShell = (BasicRhinoShell) getTopLevelScope(thisObj);
+ for (Object element : args) {
+ BasicRhinoShell.processSource(cx, Context.toString(element));
+ }
+ }
+
+ /**
+ * Evaluate JavaScript source.
+ *
+ * @param cx the current context
+ * @param filename the name of the file to compile, or null for interactive
+ * mode.
+ */
+ private void processSource(Context cx, String filename) {
+ if (filename == null) {
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ String sourceName = "<stdin>";
+ int lineno = 1;
+ boolean hitEOF = false;
+ do {
+ int startline = lineno;
+ System.err.print("js> ");
+ System.err.flush();
+ try {
+ String source = "";
+ // Collect lines of source to compile.
+ while (true) {
+ String newline;
+ newline = in.readLine();
+ if (newline == null) {
+ hitEOF = true;
+ break;
+ }
+ source = source + newline + "\n";
+ lineno++;
+ // Continue collecting as long as more lines
+ // are needed to complete the current
+ // statement. stringIsCompilableUnit is also
+ // true if the source statement will result in
+ // any error other than one that might be
+ // resolved by appending more source.
+ if (cx.stringIsCompilableUnit(source)) {
+ break;
+ }
+ }
+ Object result = cx.evaluateString(this, source, sourceName, startline, null);
+ if (result != Context.getUndefinedValue()) {
+ System.err.println(Context.toString(result));
+ }
+ } catch (WrappedException we) {
+ // Some form of exception was caught by JavaScript and
+ // propagated up.
+ System.err.println(we.getWrappedException().toString());
+ we.printStackTrace();
+ } catch (EvaluatorException ee) {
+ // Some form of JavaScript error.
+ System.err.println("js: " + ee.getMessage());
+ } catch (JavaScriptException jse) {
+ // Some form of JavaScript error.
+ System.err.println("js: " + jse.getMessage());
+ } catch (IOException ioe) {
+ System.err.println(ioe.toString());
+ }
+ if (quitting) {
+ // The user executed the quit() function.
+ break;
+ }
+ } while (!hitEOF);
+ System.err.println();
+ } else {
+ FileReader in = null;
+ try {
+ in = new FileReader(filename);
+ } catch (FileNotFoundException ex) {
+ Context.reportError("Couldn't open file \"" + filename + "\".");
+ return;
+ }
+
+ try {
+ // Here we evalute the entire contents of the file as
+ // a script. Text is printed only if the print() function
+ // is called.
+ cx.evaluateReader(this, in, filename, 1, null);
+ } catch (WrappedException we) {
+ System.err.println(we.getWrappedException().toString());
+ we.printStackTrace();
+ } catch (EvaluatorException ee) {
+ System.err.println("js: " + ee.getMessage());
+ } catch (JavaScriptException jse) {
+ System.err.println("js: " + jse.getMessage());
+ } catch (IOException ioe) {
+ System.err.println(ioe.toString());
+ } finally {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ System.err.println(ioe.toString());
+ }
+ }
+ }
+ }
+
+ private static void p(String s) {
+ System.out.println(s);
+ }
+
+ private boolean quitting;
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,81 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import org.apache.maven.plugin.logging.Log;
+import org.mozilla.javascript.ErrorReporter;
+import org.mozilla.javascript.EvaluatorException;
+
+public class ErrorReporter4Mojo implements ErrorReporter {
+
+ private String defaultFilename_;
+ private boolean acceptWarn_;
+ private Log log_;
+ private int warningCnt_;
+ private int errorCnt_;
+
+ public ErrorReporter4Mojo(Log log, boolean jswarn) {
+ log_ = log;
+ acceptWarn_ = jswarn;
+ }
+
+ public void setDefaultFileName(String v) {
+ if (v.length() == 0) {
+ v = null;
+ }
+ defaultFilename_ = v;
+ }
+
+ public int getErrorCnt() {
+ return errorCnt_;
+ }
+
+ public int getWarningCnt() {
+ return warningCnt_;
+ }
+
+ public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
+ String fullMessage = newMessage(message, sourceName, line, lineSource, lineOffset);
+ log_.error(fullMessage);
+ errorCnt_++;
+ }
+
+ public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset) {
+ error(message, sourceName, line, lineSource, lineOffset);
+ throw new EvaluatorException(message, sourceName, line, lineSource, lineOffset);
+ }
+
+ public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
+ if (acceptWarn_) {
+ String fullMessage = newMessage(message, sourceName, line, lineSource, lineOffset);
+ log_.warn(fullMessage);
+ warningCnt_++;
+ }
+ }
+
+ private String newMessage(String message, String sourceName, int line, String lineSource, int lineOffset) {
+ StringBuilder back = new StringBuilder();
+ if ((sourceName == null) || (sourceName.length() == 0)) {
+ sourceName = defaultFilename_;
+ }
+ if (sourceName != null) {
+ back.append(sourceName)
+ .append(":line ")
+ .append(line)
+ .append(":column ")
+ .append(lineOffset)
+ .append(':')
+ ;
+ }
+ if ((message != null) && (message.length() != 0)) {
+ back.append(message);
+ } else {
+ back.append("unknown error");
+ }
+ if ((lineSource != null) && (lineSource.length() != 0)) {
+ back.append("\n\t")
+ .append(lineSource)
+ ;
+ }
+ return back.toString();
+ }
+
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,38 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+
+import org.codehaus.plexus.util.IOUtil;
+import org.mozilla.javascript.ErrorReporter;
+
+//TODO: use MojoErrorReporter
+class JSLintChecker {
+ private String jslintPath_;
+
+ public JSLintChecker() throws Exception {
+ FileOutputStream out = null;
+ InputStream in = null;
+ try {
+ File jslint = File.createTempFile("jslint", ".js");
+ in = getClass().getResourceAsStream("/jslint.js");
+ out = new FileOutputStream(jslint);
+ IOUtil.copy(in, out);
+ jslintPath_ = jslint.getAbsolutePath();
+ } finally {
+ IOUtil.close(in);
+ IOUtil.close(out);
+ }
+ }
+
+ public void check(File jsFile, ErrorReporter reporter) {
+ String[] args = new String[2];
+ args[0] = jslintPath_;
+ args[1] = jsFile.getAbsolutePath();
+ BasicRhinoShell.exec(args, reporter);
+ //if (Main.exec(args) != 0) {
+ // reporter.warning("warnings during checking of :" + jsFile.getAbsolutePath(), null, -1, null, -1);
+ //}
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,36 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+
+/**
+ * Check JS files with jslint.
+ *
+ * @goal jslint
+ * @phase process-resources
+ *
+ * @author David Bernard
+ * @created 2007-08-29
+ */
+// @SuppressWarnings("unchecked")
+public class JSLintMojo extends MojoSupport {
+ private JSLintChecker jslint_;
+
+ @Override
+ protected String[] getDefaultIncludes() throws Exception {
+ return new String[] { "**/**.js" };
+ }
+
+ @Override
+ public void beforeProcess() throws Exception {
+ jslint_ = new JSLintChecker();
+ }
+
+ @Override
+ public void afterProcess() throws Exception {
+ }
+
+ @Override
+ protected void processFile(SourceFile src) throws Exception {
+ getLog().info("check file :" + src.toFile());
+ jslint_.check(src.toFile(), jsErrorReporter_);
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,184 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.DirectoryScanner;
+
+/**
+ * Common class for mojos.
+ *
+ * @author David Bernard
+ * @created 2007-08-29
+ */
+// @SuppressWarnings("unchecked")
+public abstract class MojoSupport extends AbstractMojo {
+ private static final String[] EMPTY_STRING_ARRAY = {};
+
+ /**
+ * Javascript source directory. (result will be put to outputDirectory).
+ * This allow project with "src/main/js" structure.
+ *
+ * @parameter default-value="${project.build.sourceDirectory}/../js"
+ */
+ private File sourceDirectory;
+
+ /**
+ * Single directory for extra files to include in the WAR.
+ *
+ * @parameter default-value="${basedir}/src/main/webapp"
+ */
+ private File warSourceDirectory;
+
+ /**
+ * The directory where the webapp is built.
+ *
+ * @parameter default-value="${project.build.directory}/${project.build.finalName}"
+ */
+ protected File webappDirectory;
+
+ /**
+ * The output directory into which to copy the resources.
+ *
+ * @parameter default-value="${project.build.outputDirectory}"
+ */
+ protected File outputDirectory;
+
+ /**
+ * The list of resources we want to transfer.
+ *
+ * @parameter default-value="${project.resources}"
+ */
+ private List<Resource> resources;
+
+ /**
+ * list of additionnal excludes
+ *
+ * @parameter
+ */
+ private List<String> excludes;
+
+ /**
+ * list of additionnal includes
+ *
+ * @parameter
+ */
+ private List<String> includes;
+
+ /**
+ * @parameter expression="${project}"
+ * @readonly
+ * @required
+ */
+ protected MavenProject project;
+
+ /**
+ * [js only] Display possible errors in the code
+ *
+ * @parameter expression="${maven.yuicompressor.jswarm}"
+ * default-value="true"
+ */
+ protected boolean jswarn;
+
+ /**
+ * define if plugin must stop/fail on warnings.
+ *
+ * @parameter expression="${maven.yuicompressor.failOnWarning}"
+ * default-value="false"
+ */
+ protected boolean failOnWarning;
+ protected ErrorReporter4Mojo jsErrorReporter_;
+
+ @SuppressWarnings("unchecked")
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ try {
+ if (failOnWarning) {
+ jswarn = true;
+ }
+ jsErrorReporter_ = new ErrorReporter4Mojo(getLog(), jswarn);
+ beforeProcess();
+ processDir(sourceDirectory, outputDirectory, null, null,
+ true);
+ for (Resource resource : resources) {
+ File destRoot = outputDirectory;
+ if (resource.getTargetPath() != null) {
+ destRoot = new File(outputDirectory, resource
+ .getTargetPath());
+ }
+ processDir(new File(resource.getDirectory()), destRoot,
+ resource.getIncludes(), resource.getExcludes(), true);
+ }
+ processDir(warSourceDirectory, webappDirectory, null, null,
+ false);
+ afterProcess();
+ getLog().info(
+ String.format("nb warnings: %d, nb errors: %d",
+ jsErrorReporter_.getWarningCnt(), jsErrorReporter_
+ .getErrorCnt()));
+ if (failOnWarning && (jsErrorReporter_.getWarningCnt() > 0)) {
+ throw new MojoFailureException("warnings on "
+ + this.getClass().getSimpleName()
+ + "=> failure ! (see log)");
+ }
+ } catch (RuntimeException exc) {
+ throw exc;
+ } catch (MojoFailureException exc) {
+ throw exc;
+ } catch (MojoExecutionException exc) {
+ throw exc;
+ } catch (Exception exc) {
+ throw new MojoExecutionException("wrap: " + exc.getMessage(), exc);
+ }
+ }
+
+ protected abstract String[] getDefaultIncludes() throws Exception;
+
+ protected abstract void beforeProcess() throws Exception;
+
+ protected abstract void afterProcess() throws Exception;
+
+ protected void processDir(File srcRoot, File destRoot,
+ List<String> srcIncludes, List<String> srcExcludes,
+ boolean destAsSource) throws Exception {
+ if ((srcRoot == null) || (!srcRoot.exists())) {
+ return;
+ }
+ if (destRoot == null) {
+ throw new MojoFailureException("destination directory for "
+ + srcRoot + " is null");
+ }
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setBasedir(srcRoot);
+ if ((srcIncludes != null) && !srcIncludes.isEmpty()) {
+ scanner.setIncludes(srcIncludes.toArray(EMPTY_STRING_ARRAY));
+ }
+ if ((includes != null) && !includes.isEmpty()) {
+ scanner.setIncludes(includes.toArray(EMPTY_STRING_ARRAY));
+ } else {
+ scanner.setIncludes(getDefaultIncludes());
+ }
+ if ((srcExcludes != null) && !srcExcludes.isEmpty()) {
+ scanner.setExcludes(srcExcludes.toArray(EMPTY_STRING_ARRAY));
+ }
+ if ((excludes != null) && !excludes.isEmpty()) {
+ scanner.setExcludes(excludes.toArray(EMPTY_STRING_ARRAY));
+ }
+ scanner.addDefaultExcludes();
+ scanner.scan();
+ for (String name : scanner.getIncludedFiles()) {
+ SourceFile src = new SourceFile(srcRoot, destRoot, name,
+ destAsSource);
+ jsErrorReporter_.setDefaultFileName("..."
+ + src.toFile().getAbsolutePath().substring(
+ project.getBasedir().getAbsolutePath().length()));
+ processFile(src);
+ }
+ }
+
+ protected abstract void processFile(SourceFile src) throws Exception;
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,45 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+
+public class SourceFile {
+
+ private File srcRoot_;
+ private File destRoot_;
+ private boolean destAsSource_;
+ private String rpath_;
+ private String extension_;
+
+ public SourceFile(File srcRoot, File destRoot, String name, boolean destAsSource) throws Exception {
+ srcRoot_ = srcRoot;
+ destRoot_ = destRoot;
+ destAsSource_ = destAsSource;
+ rpath_ = name;
+ int sep = rpath_.lastIndexOf('.');
+ if (sep>0) {
+ extension_ = rpath_.substring(sep);
+ rpath_ = rpath_.substring(0, sep);
+ } else {
+ extension_ = "";
+ }
+ }
+
+ public File toFile() {
+ String frpath = rpath_ + extension_;
+ if (destAsSource_) {
+ File defaultDest = new File(destRoot_, frpath);
+ if (defaultDest.exists() && defaultDest.canRead()) {
+ return defaultDest;
+ }
+ }
+ return new File(srcRoot_, frpath);
+ }
+
+ public File toDestFile(String suffix) {
+ return new File(destRoot_, rpath_ + suffix + extension_);
+ }
+
+ public String getExtension() {
+ return extension_;
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,229 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.zip.GZIPOutputStream;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+
+import com.yahoo.platform.yui.compressor.CssCompressor;
+import com.yahoo.platform.yui.compressor.JavaScriptCompressor;
+
+/**
+ * Apply compression on JS and CSS (using YUI Compressor).
+ *
+ * @goal compress
+ * @phase process-resources
+ *
+ * @author David Bernard
+ * @created 2007-08-28
+ */
+// @SuppressWarnings("unchecked")
+public class YuiCompressorMojo extends MojoSupport {
+
+ /**
+ * Read the input file using "encoding".
+ *
+ * @parameter expression="${file.encoding}" default-value="UTF-8"
+ */
+ private String encoding;
+
+ /**
+ * The output filename suffix.
+ *
+ * @parameter expression="${maven.yuicompressor.suffix}" default-value="-min"
+ */
+ private String suffix;
+
+ /**
+ * If no "suffix" must be add to output filename (maven's configuration manage empty suffix like default).
+ *
+ * @parameter expression="${maven.yuicompressor.nosuffix}" default-value="false"
+ */
+ private boolean nosuffix;
+
+ /**
+ * Insert line breaks in output after the specified column number.
+ *
+ * @parameter expression="${maven.yuicompressor.linebreakpos}" default-value="0"
+ */
+ private int linebreakpos;
+
+ /**
+ * [js only] Minify only, do not obfuscate.
+ *
+ * @parameter expression="${maven.yuicompressor.nomunge}" default-value="false"
+ */
+ private boolean nomunge;
+
+ /**
+ * [js only] Preserve unnecessary semicolons.
+ *
+ * @parameter expression="${maven.yuicompressor.preserveAllSemiColons}" default-value="false"
+ */
+ private boolean preserveAllSemiColons;
+
+ /**
+ * [js only] Preserve string (no optimization).
+ *
+ * @parameter expression="${maven.yuicompressor.preserveStringLiterals}" default-value="false"
+ */
+ private boolean preserveStringLiterals;
+
+ /**
+ * force the compression of every files,
+ * else if compressed file already exists and is younger than source file, nothing is done.
+ *
+ * @parameter expression="${maven.yuicompressor.force}" default-value="false"
+ */
+ private boolean force;
+
+ /**
+ * a list of aggregation/concatenation to do after processing,
+ * for example to create big js files that contain several small js files.
+ * Aggregation could be done on any type of file (js, css, ...).
+ *
+ * @parameter
+ */
+ private Aggregation[] aggregations;
+
+ /**
+ * request to create a gzipped version of the yuicompressed/aggregation files.
+ *
+ * @parameter expression="${maven.yuicompressor.gzip}" default-value="false"
+ */
+ private boolean gzip;
+
+ /**
+ * show statistics (compression ratio).
+ *
+ * @parameter expression="${maven.yuicompressor.statistics}" default-value="true"
+ */
+ private boolean statistics;
+
+ private long inSizeTotal_;
+ private long outSizeTotal_;
+
+ @Override
+ protected String[] getDefaultIncludes() throws Exception {
+ return new String[]{"**/*.css", "**/*.js"};
+ }
+
+ @Override
+ public void beforeProcess() throws Exception {
+ if (nosuffix) {
+ suffix = "";
+ }
+ }
+
+ @Override
+ protected void afterProcess() throws Exception {
+ if (statistics && (inSizeTotal_ > 0)) {
+ getLog().info(String.format("total input (%db) -> output (%db)[%d%%]", inSizeTotal_, outSizeTotal_, ((outSizeTotal_ * 100)/inSizeTotal_)));
+ }
+ if (aggregations != null) {
+ for(Aggregation aggregation : aggregations) {
+ getLog().info("generate aggregation : " + aggregation.output);
+ aggregation.run(outputDirectory);
+ File gzipped = gzipIfRequested(aggregation.output);
+ if (statistics) {
+ if (gzipped != null) {
+ getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]", aggregation.output.getName(), aggregation.output.length(), gzipped.getName(), gzipped.length(), ratioOfSize(aggregation.output, gzipped)));
+ } else if (aggregation.output.exists()){
+ getLog().info(String.format("%s (%db)", aggregation.output.getName(), aggregation.output.length()));
+ } else {
+ getLog().warn(String.format("%s not created", aggregation.output.getName()));
+ }
+ }
+ }
+ }
+ }
+
+
+ @Override
+ protected void processFile(SourceFile src) throws Exception {
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("compress file :" + src.toFile()+ " to " + src.toDestFile(suffix));
+ }
+ File inFile = src.toFile();
+ File outFile = src.toDestFile(suffix);
+
+ getLog().debug("only compress if input file is youger than existing output file");
+ if (!force && outFile.exists() && (outFile.lastModified() > inFile.lastModified())) {
+ if (getLog().isInfoEnabled()) {
+ getLog().info("nothing to do, " + outFile + " is younger than original, use 'force' option or clean your target");
+ }
+ return;
+ }
+
+ InputStreamReader in = null;
+ OutputStreamWriter out = null;
+ try {
+ in = new InputStreamReader(new FileInputStream(inFile), encoding);
+ if (!outFile.getParentFile().exists() && !outFile.getParentFile().mkdirs()) {
+ throw new MojoExecutionException( "Cannot create resource output directory: " + outFile.getParentFile() );
+ }
+ getLog().debug("use a temporary outputfile (in case in == out)");
+ File outFileTmp = new File(outFile.getAbsolutePath() + ".tmp");
+ FileUtils.forceDelete(outFileTmp);
+
+ getLog().debug("start compression");
+ out = new OutputStreamWriter(new FileOutputStream(outFileTmp), encoding);
+ if (".js".equalsIgnoreCase(src.getExtension())) {
+ JavaScriptCompressor compressor = new JavaScriptCompressor(in, jsErrorReporter_);
+ compressor.compress(out, linebreakpos, !nomunge, jswarn, preserveAllSemiColons, preserveStringLiterals);
+ } else if (".css".equalsIgnoreCase(src.getExtension())) {
+ CssCompressor compressor = new CssCompressor(in);
+ compressor.compress(out, linebreakpos);
+ }
+ getLog().debug("end compression");
+ FileUtils.forceDelete(outFile);
+ FileUtils.rename(outFileTmp, outFile);
+ } finally {
+ IOUtil.close(in);
+ IOUtil.close(out);
+ }
+ File gzipped = gzipIfRequested(outFile);
+ if (statistics) {
+ inSizeTotal_ += inFile.length();
+ outSizeTotal_ += outFile.length();
+ getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]", inFile.getName(), inFile.length(), outFile.getName(), outFile.length(), ratioOfSize(inFile, outFile)));
+ if (gzipped != null) {
+ getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]", inFile.getName(), inFile.length(), gzipped.getName(), gzipped.length(), ratioOfSize(inFile, gzipped)));
+ }
+ }
+ }
+
+ protected File gzipIfRequested(File file) throws Exception {
+ if (!gzip || (file == null) || (!file.exists())) {
+ return null;
+ }
+ if (".gz".equalsIgnoreCase(FileUtils.getExtension(file.getName()))) {
+ return null;
+ }
+ File gzipped = new File(file.getAbsolutePath()+".gz");
+ getLog().debug(String.format("create gzip version : %s", gzipped.getName()));
+ GZIPOutputStream out = null;
+ FileInputStream in = null;
+ try {
+ out = new GZIPOutputStream(new FileOutputStream(gzipped));
+ in = new FileInputStream(file);
+ IOUtil.copy(in, out);
+ } finally {
+ IOUtil.close(in);
+ IOUtil.close(out);
+ }
+ return gzipped;
+ }
+
+ protected long ratioOfSize(File file100, File fileX) throws Exception {
+ long v100 = Math.max(file100.length(), 1);
+ long vX = Math.max(fileX.length(), 1);
+ return (vX * 100)/v100;
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,916 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike Ang
+ * Igor Bukanov
+ * Bob Jervis
+ * Mike McCabe
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+/**
+ * The following class save decompilation information about the source.
+ * Source information is returned from the parser as a String
+ * associated with function nodes and with the toplevel script. When
+ * saved in the constant pool of a class, this string will be UTF-8
+ * encoded, and token values will occupy a single byte.
+
+ * Source is saved (mostly) as token numbers. The tokens saved pretty
+ * much correspond to the token stream of a 'canonical' representation
+ * of the input program, as directed by the parser. (There were a few
+ * cases where tokens could have been left out where decompiler could
+ * easily reconstruct them, but I left them in for clarity). (I also
+ * looked adding source collection to TokenStream instead, where I
+ * could have limited the changes to a few lines in getToken... but
+ * this wouldn't have saved any space in the resulting source
+ * representation, and would have meant that I'd have to duplicate
+ * parser logic in the decompiler to disambiguate situations where
+ * newlines are important.) The function decompile expands the
+ * tokens back into their string representations, using simple
+ * lookahead to correct spacing and indentation.
+ *
+ * Assignments are saved as two-token pairs (Token.ASSIGN, op). Number tokens
+ * are stored inline, as a NUMBER token, a character representing the type, and
+ * either 1 or 4 characters representing the bit-encoding of the number. String
+ * types NAME, STRING and OBJECT are currently stored as a token type,
+ * followed by a character giving the length of the string (assumed to
+ * be less than 2^16), followed by the characters of the string
+ * inlined into the source string. Changing this to some reference to
+ * to the string in the compiled class' constant pool would probably
+ * save a lot of space... but would require some method of deriving
+ * the final constant pool entry from information available at parse
+ * time.
+ */
+public class Decompiler
+{
+ /**
+ * Flag to indicate that the decompilation should omit the
+ * function header and trailing brace.
+ */
+ public static final int ONLY_BODY_FLAG = 1 << 0;
+
+ /**
+ * Flag to indicate that the decompilation generates toSource result.
+ */
+ public static final int TO_SOURCE_FLAG = 1 << 1;
+
+ /**
+ * Decompilation property to specify initial ident value.
+ */
+ public static final int INITIAL_INDENT_PROP = 1;
+
+ /**
+ * Decompilation property to specify default identation offset.
+ */
+ public static final int INDENT_GAP_PROP = 2;
+
+ /**
+ * Decompilation property to specify identation offset for case labels.
+ */
+ public static final int CASE_GAP_PROP = 3;
+
+ // Marker to denote the last RC of function so it can be distinguished from
+ // the last RC of object literals in case of function expressions
+ private static final int FUNCTION_END = Token.LAST_TOKEN + 1;
+
+ String getEncodedSource()
+ {
+ return sourceToString(0);
+ }
+
+ int getCurrentOffset()
+ {
+ return sourceTop;
+ }
+
+ int markFunctionStart(int functionType)
+ {
+ int savedOffset = getCurrentOffset();
+ addToken(Token.FUNCTION);
+ append((char)functionType);
+ return savedOffset;
+ }
+
+ int markFunctionEnd(int functionStart)
+ {
+ int offset = getCurrentOffset();
+ append((char)FUNCTION_END);
+ return offset;
+ }
+
+ void addToken(int token)
+ {
+ if (!(0 <= token && token <= Token.LAST_TOKEN))
+ throw new IllegalArgumentException();
+
+ append((char)token);
+ }
+
+ void addEOL(int token)
+ {
+ if (!(0 <= token && token <= Token.LAST_TOKEN))
+ throw new IllegalArgumentException();
+
+ append((char)token);
+ append((char)Token.EOL);
+ }
+
+ void addName(String str)
+ {
+ addToken(Token.NAME);
+ appendString(str);
+ }
+
+ void addString(String str)
+ {
+ addToken(Token.STRING);
+ appendString(str);
+ }
+
+ void addRegexp(String regexp, String flags)
+ {
+ addToken(Token.REGEXP);
+ appendString('/' + regexp + '/' + flags);
+ }
+
+ void addJScriptConditionalComment(String str)
+ {
+ addToken(Token.IECC);
+ appendString(str);
+ }
+
+ void addNumber(double n)
+ {
+ addToken(Token.NUMBER);
+
+ /* encode the number in the source stream.
+ * Save as NUMBER type (char | char char char char)
+ * where type is
+ * 'D' - double, 'S' - short, 'J' - long.
+
+ * We need to retain float vs. integer type info to keep the
+ * behavior of liveconnect type-guessing the same after
+ * decompilation. (Liveconnect tries to present 1.0 to Java
+ * as a float/double)
+ * OPT: This is no longer true. We could compress the format.
+
+ * This may not be the most space-efficient encoding;
+ * the chars created below may take up to 3 bytes in
+ * constant pool UTF-8 encoding, so a Double could take
+ * up to 12 bytes.
+ */
+
+ long lbits = (long)n;
+ if (lbits != n) {
+ // if it's floating point, save as a Double bit pattern.
+ // (12/15/97 our scanner only returns Double for f.p.)
+ lbits = Double.doubleToLongBits(n);
+ append('D');
+ append((char)(lbits >> 48));
+ append((char)(lbits >> 32));
+ append((char)(lbits >> 16));
+ append((char)lbits);
+ }
+ else {
+ // we can ignore negative values, bc they're already prefixed
+ // by NEG
+ if (lbits < 0) Kit.codeBug();
+
+ // will it fit in a char?
+ // this gives a short encoding for integer values up to 2^16.
+ if (lbits <= Character.MAX_VALUE) {
+ append('S');
+ append((char)lbits);
+ }
+ else { // Integral, but won't fit in a char. Store as a long.
+ append('J');
+ append((char)(lbits >> 48));
+ append((char)(lbits >> 32));
+ append((char)(lbits >> 16));
+ append((char)lbits);
+ }
+ }
+ }
+
+ private void appendString(String str)
+ {
+ int L = str.length();
+ int lengthEncodingSize = 1;
+ if (L >= 0x8000) {
+ lengthEncodingSize = 2;
+ }
+ int nextTop = sourceTop + lengthEncodingSize + L;
+ if (nextTop > sourceBuffer.length) {
+ increaseSourceCapacity(nextTop);
+ }
+ if (L >= 0x8000) {
+ // Use 2 chars to encode strings exceeding 32K, were the highest
+ // bit in the first char indicates presence of the next byte
+ sourceBuffer[sourceTop] = (char)(0x8000 | (L >>> 16));
+ ++sourceTop;
+ }
+ sourceBuffer[sourceTop] = (char)L;
+ ++sourceTop;
+ str.getChars(0, L, sourceBuffer, sourceTop);
+ sourceTop = nextTop;
+ }
+
+ private void append(char c)
+ {
+ if (sourceTop == sourceBuffer.length) {
+ increaseSourceCapacity(sourceTop + 1);
+ }
+ sourceBuffer[sourceTop] = c;
+ ++sourceTop;
+ }
+
+ private void increaseSourceCapacity(int minimalCapacity)
+ {
+ // Call this only when capacity increase is must
+ if (minimalCapacity <= sourceBuffer.length) Kit.codeBug();
+ int newCapacity = sourceBuffer.length * 2;
+ if (newCapacity < minimalCapacity) {
+ newCapacity = minimalCapacity;
+ }
+ char[] tmp = new char[newCapacity];
+ System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop);
+ sourceBuffer = tmp;
+ }
+
+ private String sourceToString(int offset)
+ {
+ if (offset < 0 || sourceTop < offset) Kit.codeBug();
+ return new String(sourceBuffer, offset, sourceTop - offset);
+ }
+
+ /**
+ * Decompile the source information associated with this js
+ * function/script back into a string. For the most part, this
+ * just means translating tokens back to their string
+ * representations; there's a little bit of lookahead logic to
+ * decide the proper spacing/indentation. Most of the work in
+ * mapping the original source to the prettyprinted decompiled
+ * version is done by the parser.
+ *
+ * @param source encoded source tree presentation
+ *
+ * @param flags flags to select output format
+ *
+ * @param properties indentation properties
+ *
+ */
+ public static String decompile(String source, int flags,
+ UintMap properties)
+ {
+ int length = source.length();
+ if (length == 0) { return ""; }
+
+ int indent = properties.getInt(INITIAL_INDENT_PROP, 0);
+ if (indent < 0) throw new IllegalArgumentException();
+ int indentGap = properties.getInt(INDENT_GAP_PROP, 4);
+ if (indentGap < 0) throw new IllegalArgumentException();
+ int caseGap = properties.getInt(CASE_GAP_PROP, 2);
+ if (caseGap < 0) throw new IllegalArgumentException();
+
+ StringBuffer result = new StringBuffer();
+ boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
+ boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG));
+
+ // Spew tokens in source, for debugging.
+ // as TYPE number char
+ if (printSource) {
+ System.err.println("length:" + length);
+ for (int i = 0; i < length; ++i) {
+ // Note that tokenToName will fail unless Context.printTrees
+ // is true.
+ String tokenname = null;
+ if (Token.printNames) {
+ tokenname = Token.name(source.charAt(i));
+ }
+ if (tokenname == null) {
+ tokenname = "---";
+ }
+ String pad = tokenname.length() > 7
+ ? "\t"
+ : "\t\t";
+ System.err.println
+ (tokenname
+ + pad + (int)source.charAt(i)
+ + "\t'" + ScriptRuntime.escapeString
+ (source.substring(i, i+1))
+ + "'");
+ }
+ System.err.println();
+ }
+
+ int braceNesting = 0;
+ boolean afterFirstEOL = false;
+ int i = 0;
+ int topFunctionType;
+ if (source.charAt(i) == Token.SCRIPT) {
+ ++i;
+ topFunctionType = -1;
+ } else {
+ topFunctionType = source.charAt(i + 1);
+ }
+
+ if (!toSource) {
+ // add an initial newline to exactly match js.
+ result.append('\n');
+ for (int j = 0; j < indent; j++)
+ result.append(' ');
+ } else {
+ if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
+ result.append('(');
+ }
+ }
+
+ while (i < length) {
+ switch(source.charAt(i)) {
+ case Token.GET:
+ case Token.SET:
+ result.append(source.charAt(i) == Token.GET ? "get " : "set ");
+ ++i;
+ i = printSourceString(source, i + 1, false, result);
+ // Now increment one more to get past the FUNCTION token
+ ++i;
+ break;
+
+ case Token.NAME:
+ case Token.REGEXP: // re-wrapped in '/'s in parser...
+ i = printSourceString(source, i + 1, false, result);
+ continue;
+
+ case Token.STRING:
+ i = printSourceString(source, i + 1, true, result);
+ continue;
+
+ case Token.NUMBER:
+ i = printSourceNumber(source, i + 1, result);
+ continue;
+
+ case Token.TRUE:
+ result.append("true");
+ break;
+
+ case Token.FALSE:
+ result.append("false");
+ break;
+
+ case Token.NULL:
+ result.append("null");
+ break;
+
+ case Token.THIS:
+ result.append("this");
+ break;
+
+ case Token.FUNCTION:
+ ++i; // skip function type
+ result.append("function ");
+ break;
+
+ case FUNCTION_END:
+ // Do nothing
+ break;
+
+ case Token.COMMA:
+ result.append(", ");
+ break;
+
+ case Token.LC:
+ ++braceNesting;
+ if (Token.EOL == getNext(source, length, i))
+ indent += indentGap;
+ result.append('{');
+ break;
+
+ case Token.RC: {
+ --braceNesting;
+ /* don't print the closing RC if it closes the
+ * toplevel function and we're called from
+ * decompileFunctionBody.
+ */
+ if (justFunctionBody && braceNesting == 0)
+ break;
+
+ result.append('}');
+ switch (getNext(source, length, i)) {
+ case Token.EOL:
+ case FUNCTION_END:
+ indent -= indentGap;
+ break;
+ case Token.WHILE:
+ case Token.ELSE:
+ indent -= indentGap;
+ result.append(' ');
+ break;
+ }
+ break;
+ }
+ case Token.LP:
+ result.append('(');
+ break;
+
+ case Token.RP:
+ result.append(')');
+ if (Token.LC == getNext(source, length, i))
+ result.append(' ');
+ break;
+
+ case Token.LB:
+ result.append('[');
+ break;
+
+ case Token.RB:
+ result.append(']');
+ break;
+
+ case Token.EOL: {
+ if (toSource) break;
+ boolean newLine = true;
+ if (!afterFirstEOL) {
+ afterFirstEOL = true;
+ if (justFunctionBody) {
+ /* throw away just added 'function name(...) {'
+ * and restore the original indent
+ */
+ result.setLength(0);
+ indent -= indentGap;
+ newLine = false;
+ }
+ }
+ if (newLine) {
+ result.append('\n');
+ }
+
+ /* add indent if any tokens remain,
+ * less setback if next token is
+ * a label, case or default.
+ */
+ if (i + 1 < length) {
+ int less = 0;
+ int nextToken = source.charAt(i + 1);
+ if (nextToken == Token.CASE
+ || nextToken == Token.DEFAULT)
+ {
+ less = indentGap - caseGap;
+ } else if (nextToken == Token.RC) {
+ less = indentGap;
+ }
+
+ /* elaborate check against label... skip past a
+ * following inlined NAME and look for a COLON.
+ */
+ else if (nextToken == Token.NAME) {
+ int afterName = getSourceStringEnd(source, i + 2);
+ if (source.charAt(afterName) == Token.COLON)
+ less = indentGap;
+ }
+
+ for (; less < indent; less++)
+ result.append(' ');
+ }
+ break;
+ }
+ case Token.DOT:
+ result.append('.');
+ break;
+
+ case Token.NEW:
+ result.append("new ");
+ break;
+
+ case Token.DELPROP:
+ result.append("delete ");
+ break;
+
+ case Token.IF:
+ result.append("if ");
+ break;
+
+ case Token.ELSE:
+ result.append("else ");
+ break;
+
+ case Token.FOR:
+ result.append("for ");
+ break;
+
+ case Token.IN:
+ result.append(" in ");
+ break;
+
+ case Token.WITH:
+ result.append("with ");
+ break;
+
+ case Token.WHILE:
+ result.append("while ");
+ break;
+
+ case Token.DO:
+ result.append("do ");
+ break;
+
+ case Token.TRY:
+ result.append("try ");
+ break;
+
+ case Token.CATCH:
+ result.append("catch ");
+ break;
+
+ case Token.FINALLY:
+ result.append("finally ");
+ break;
+
+ case Token.THROW:
+ result.append("throw ");
+ break;
+
+ case Token.SWITCH:
+ result.append("switch ");
+ break;
+
+ case Token.BREAK:
+ result.append("break");
+ if (Token.NAME == getNext(source, length, i))
+ result.append(' ');
+ break;
+
+ case Token.CONTINUE:
+ result.append("continue");
+ if (Token.NAME == getNext(source, length, i))
+ result.append(' ');
+ break;
+
+ case Token.CASE:
+ result.append("case ");
+ break;
+
+ case Token.DEFAULT:
+ result.append("default");
+ break;
+
+ case Token.RETURN:
+ result.append("return");
+ if (Token.SEMI != getNext(source, length, i))
+ result.append(' ');
+ break;
+
+ case Token.VAR:
+ result.append("var ");
+ break;
+
+ case Token.SEMI:
+ result.append(';');
+ if (Token.EOL != getNext(source, length, i)) {
+ // separators in FOR
+ result.append(' ');
+ }
+ break;
+
+ case Token.ASSIGN:
+ result.append(" = ");
+ break;
+
+ case Token.ASSIGN_ADD:
+ result.append(" += ");
+ break;
+
+ case Token.ASSIGN_SUB:
+ result.append(" -= ");
+ break;
+
+ case Token.ASSIGN_MUL:
+ result.append(" *= ");
+ break;
+
+ case Token.ASSIGN_DIV:
+ result.append(" /= ");
+ break;
+
+ case Token.ASSIGN_MOD:
+ result.append(" %= ");
+ break;
+
+ case Token.ASSIGN_BITOR:
+ result.append(" |= ");
+ break;
+
+ case Token.ASSIGN_BITXOR:
+ result.append(" ^= ");
+ break;
+
+ case Token.ASSIGN_BITAND:
+ result.append(" &= ");
+ break;
+
+ case Token.ASSIGN_LSH:
+ result.append(" <<= ");
+ break;
+
+ case Token.ASSIGN_RSH:
+ result.append(" >>= ");
+ break;
+
+ case Token.ASSIGN_URSH:
+ result.append(" >>>= ");
+ break;
+
+ case Token.HOOK:
+ result.append(" ? ");
+ break;
+
+ case Token.OBJECTLIT:
+ // pun OBJECTLIT to mean colon in objlit property
+ // initialization.
+ // This needs to be distinct from COLON in the general case
+ // to distinguish from the colon in a ternary... which needs
+ // different spacing.
+ result.append(':');
+ break;
+
+ case Token.COLON:
+ if (Token.EOL == getNext(source, length, i))
+ // it's the end of a label
+ result.append(':');
+ else
+ // it's the middle part of a ternary
+ result.append(" : ");
+ break;
+
+ case Token.OR:
+ result.append(" || ");
+ break;
+
+ case Token.AND:
+ result.append(" && ");
+ break;
+
+ case Token.BITOR:
+ result.append(" | ");
+ break;
+
+ case Token.BITXOR:
+ result.append(" ^ ");
+ break;
+
+ case Token.BITAND:
+ result.append(" & ");
+ break;
+
+ case Token.SHEQ:
+ result.append(" === ");
+ break;
+
+ case Token.SHNE:
+ result.append(" !== ");
+ break;
+
+ case Token.EQ:
+ result.append(" == ");
+ break;
+
+ case Token.NE:
+ result.append(" != ");
+ break;
+
+ case Token.LE:
+ result.append(" <= ");
+ break;
+
+ case Token.LT:
+ result.append(" < ");
+ break;
+
+ case Token.GE:
+ result.append(" >= ");
+ break;
+
+ case Token.GT:
+ result.append(" > ");
+ break;
+
+ case Token.INSTANCEOF:
+ result.append(" instanceof ");
+ break;
+
+ case Token.LSH:
+ result.append(" << ");
+ break;
+
+ case Token.RSH:
+ result.append(" >> ");
+ break;
+
+ case Token.URSH:
+ result.append(" >>> ");
+ break;
+
+ case Token.TYPEOF:
+ result.append("typeof ");
+ break;
+
+ case Token.VOID:
+ result.append("void ");
+ break;
+
+ case Token.CONST:
+ result.append("const ");
+ break;
+
+ case Token.NOT:
+ result.append('!');
+ break;
+
+ case Token.BITNOT:
+ result.append('~');
+ break;
+
+ case Token.POS:
+ result.append('+');
+ break;
+
+ case Token.NEG:
+ result.append('-');
+ break;
+
+ case Token.INC:
+ result.append("++");
+ break;
+
+ case Token.DEC:
+ result.append("--");
+ break;
+
+ case Token.ADD:
+ result.append(" + ");
+ break;
+
+ case Token.SUB:
+ result.append(" - ");
+ break;
+
+ case Token.MUL:
+ result.append(" * ");
+ break;
+
+ case Token.DIV:
+ result.append(" / ");
+ break;
+
+ case Token.MOD:
+ result.append(" % ");
+ break;
+
+ case Token.COLONCOLON:
+ result.append("::");
+ break;
+
+ case Token.DOTDOT:
+ result.append("..");
+ break;
+
+ case Token.DOTQUERY:
+ result.append(".(");
+ break;
+
+ case Token.XMLATTR:
+ result.append('@');
+ break;
+
+ default:
+ // If we don't know how to decompile it, raise an exception.
+ throw new RuntimeException("Token: " +
+ Token.name(source.charAt(i)));
+ }
+ ++i;
+ }
+
+ if (!toSource) {
+ // add that trailing newline if it's an outermost function.
+ if (!justFunctionBody)
+ result.append('\n');
+ } else {
+ if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
+ result.append(')');
+ }
+ }
+
+ return result.toString();
+ }
+
+ private static int getNext(String source, int length, int i)
+ {
+ return (i + 1 < length) ? source.charAt(i + 1) : Token.EOF;
+ }
+
+ private static int getSourceStringEnd(String source, int offset)
+ {
+ return printSourceString(source, offset, false, null);
+ }
+
+ private static int printSourceString(String source, int offset,
+ boolean asQuotedString,
+ StringBuffer sb)
+ {
+ int length = source.charAt(offset);
+ ++offset;
+ if ((0x8000 & length) != 0) {
+ length = ((0x7FFF & length) << 16) | source.charAt(offset);
+ ++offset;
+ }
+ if (sb != null) {
+ String str = source.substring(offset, offset + length);
+ if (!asQuotedString) {
+ sb.append(str);
+ } else {
+ sb.append('"');
+ sb.append(ScriptRuntime.escapeString(str));
+ sb.append('"');
+ }
+ }
+ return offset + length;
+ }
+
+ private static int printSourceNumber(String source, int offset,
+ StringBuffer sb)
+ {
+ double number = 0.0;
+ char type = source.charAt(offset);
+ ++offset;
+ if (type == 'S') {
+ if (sb != null) {
+ int ival = source.charAt(offset);
+ number = ival;
+ }
+ ++offset;
+ } else if (type == 'J' || type == 'D') {
+ if (sb != null) {
+ long lbits;
+ lbits = (long)source.charAt(offset) << 48;
+ lbits |= (long)source.charAt(offset + 1) << 32;
+ lbits |= (long)source.charAt(offset + 2) << 16;
+ lbits |= source.charAt(offset + 3);
+ if (type == 'J') {
+ number = lbits;
+ } else {
+ number = Double.longBitsToDouble(lbits);
+ }
+ }
+ offset += 4;
+ } else {
+ // Bad source
+ throw new RuntimeException();
+ }
+ if (sb != null) {
+ sb.append(ScriptRuntime.numberToString(number, 10));
+ }
+ return offset;
+ }
+
+ private char[] sourceBuffer = new char[128];
+
+// Per script/function source buffer top: parent source does not include a
+// nested functions source and uses function index as a reference instead.
+ private int sourceTop;
+
+// whether to do a debug print of the source information, when decompiling.
+ private static final boolean printSource = false;
+
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,2170 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike Ang
+ * Igor Bukanov
+ * Yuh-Ruey Chen
+ * Ethan Hugg
+ * Bob Jervis
+ * Terry Lucas
+ * Mike McCabe
+ * Milen Nankov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+import java.io.Reader;
+import java.io.IOException;
+import java.util.Hashtable;
+
+/**
+ * This class implements the JavaScript parser.
+ *
+ * It is based on the C source files jsparse.c and jsparse.h
+ * in the jsref package.
+ *
+ * @see TokenStream
+ *
+ * @author Mike McCabe
+ * @author Brendan Eich
+ */
+
+public class Parser
+{
+ // TokenInformation flags : currentFlaggedToken stores them together
+ // with token type
+ final static int
+ CLEAR_TI_MASK = 0xFFFF, // mask to clear token information bits
+ TI_AFTER_EOL = 1 << 16, // first token of the source line
+ TI_CHECK_LABEL = 1 << 17; // indicates to check for label
+
+ CompilerEnvirons compilerEnv;
+ private ErrorReporter errorReporter;
+ private String sourceURI;
+ boolean calledByCompileFunction;
+
+ private TokenStream ts;
+ private int currentFlaggedToken;
+ private int syntaxErrorCount;
+
+ private IRFactory nf;
+
+ private int nestingOfFunction;
+
+ private Decompiler decompiler;
+ private String encodedSource;
+
+// The following are per function variables and should be saved/restored
+// during function parsing.
+// XXX Move to separated class?
+ ScriptOrFnNode currentScriptOrFn;
+ private int nestingOfWith;
+ private Hashtable labelSet; // map of label names into nodes
+ private ObjArray loopSet;
+ private ObjArray loopAndSwitchSet;
+ private boolean hasReturnValue;
+ private int functionEndFlags;
+// end of per function variables
+
+ // Exception to unwind
+ private static class ParserException extends RuntimeException
+ {
+ static final long serialVersionUID = 5882582646773765630L;
+ }
+
+ public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter)
+ {
+ this.compilerEnv = compilerEnv;
+ this.errorReporter = errorReporter;
+ }
+
+ protected Decompiler createDecompiler(CompilerEnvirons compilerEnv)
+ {
+ return new Decompiler();
+ }
+
+ void addStrictWarning(String messageId, String messageArg)
+ {
+ if (compilerEnv.isStrictMode())
+ addWarning(messageId, messageArg);
+ }
+
+ void addWarning(String messageId, String messageArg)
+ {
+ String message = ScriptRuntime.getMessage1(messageId, messageArg);
+ if (compilerEnv.reportWarningAsError()) {
+ ++syntaxErrorCount;
+ errorReporter.error(message, sourceURI, ts.getLineno(),
+ ts.getLine(), ts.getOffset());
+ } else
+ errorReporter.warning(message, sourceURI, ts.getLineno(),
+ ts.getLine(), ts.getOffset());
+ }
+
+ void addError(String messageId)
+ {
+ ++syntaxErrorCount;
+ String message = ScriptRuntime.getMessage0(messageId);
+ errorReporter.error(message, sourceURI, ts.getLineno(),
+ ts.getLine(), ts.getOffset());
+ }
+
+ void addError(String messageId, String messageArg)
+ {
+ ++syntaxErrorCount;
+ String message = ScriptRuntime.getMessage1(messageId, messageArg);
+ errorReporter.error(message, sourceURI, ts.getLineno(),
+ ts.getLine(), ts.getOffset());
+ }
+
+ RuntimeException reportError(String messageId)
+ {
+ addError(messageId);
+
+ // Throw a ParserException exception to unwind the recursive descent
+ // parse.
+ throw new ParserException();
+ }
+
+ private int peekToken()
+ throws IOException
+ {
+ int tt = currentFlaggedToken;
+ if (tt == Token.EOF) {
+
+ while ((tt = ts.getToken()) == Token.IECC) {
+ /* Support for JScript conditional comments */
+ decompiler.addJScriptConditionalComment(ts.getString());
+ }
+
+ if (tt == Token.EOL) {
+ do {
+ tt = ts.getToken();
+
+ if (tt == Token.IECC) {
+ /* Support for JScript conditional comments */
+ decompiler.addJScriptConditionalComment(ts.getString());
+ }
+
+ } while (tt == Token.EOL || tt == Token.IECC);
+ tt |= TI_AFTER_EOL;
+ }
+ currentFlaggedToken = tt;
+ }
+ return tt & CLEAR_TI_MASK;
+ }
+
+ private int peekFlaggedToken()
+ throws IOException
+ {
+ peekToken();
+ return currentFlaggedToken;
+ }
+
+ private void consumeToken()
+ {
+ currentFlaggedToken = Token.EOF;
+ }
+
+ private int nextToken()
+ throws IOException
+ {
+ int tt = peekToken();
+ consumeToken();
+ return tt;
+ }
+
+ private int nextFlaggedToken()
+ throws IOException
+ {
+ peekToken();
+ int ttFlagged = currentFlaggedToken;
+ consumeToken();
+ return ttFlagged;
+ }
+
+ private boolean matchToken(int toMatch)
+ throws IOException
+ {
+ int tt = peekToken();
+ if (tt != toMatch) {
+ return false;
+ }
+ consumeToken();
+ return true;
+ }
+
+ private int peekTokenOrEOL()
+ throws IOException
+ {
+ int tt = peekToken();
+ // Check for last peeked token flags
+ if ((currentFlaggedToken & TI_AFTER_EOL) != 0) {
+ tt = Token.EOL;
+ }
+ return tt;
+ }
+
+ private void setCheckForLabel()
+ {
+ if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME)
+ throw Kit.codeBug();
+ currentFlaggedToken |= TI_CHECK_LABEL;
+ }
+
+ private void mustMatchToken(int toMatch, String messageId)
+ throws IOException, ParserException
+ {
+ if (!matchToken(toMatch)) {
+ reportError(messageId);
+ }
+ }
+
+ private void mustHaveXML()
+ {
+ if (!compilerEnv.isXmlAvailable()) {
+ reportError("msg.XML.not.available");
+ }
+ }
+
+ public String getEncodedSource()
+ {
+ return encodedSource;
+ }
+
+ public boolean eof()
+ {
+ return ts.eof();
+ }
+
+ boolean insideFunction()
+ {
+ return nestingOfFunction != 0;
+ }
+
+ private Node enterLoop(Node loopLabel)
+ {
+ Node loop = nf.createLoopNode(loopLabel, ts.getLineno());
+ if (loopSet == null) {
+ loopSet = new ObjArray();
+ if (loopAndSwitchSet == null) {
+ loopAndSwitchSet = new ObjArray();
+ }
+ }
+ loopSet.push(loop);
+ loopAndSwitchSet.push(loop);
+ return loop;
+ }
+
+ private void exitLoop()
+ {
+ loopSet.pop();
+ loopAndSwitchSet.pop();
+ }
+
+ private Node enterSwitch(Node switchSelector, int lineno)
+ {
+ Node switchNode = nf.createSwitch(switchSelector, lineno);
+ if (loopAndSwitchSet == null) {
+ loopAndSwitchSet = new ObjArray();
+ }
+ loopAndSwitchSet.push(switchNode);
+ return switchNode;
+ }
+
+ private void exitSwitch()
+ {
+ loopAndSwitchSet.pop();
+ }
+
+ /*
+ * Build a parse tree from the given sourceString.
+ *
+ * @return an Object representing the parsed
+ * program. If the parse fails, null will be returned. (The
+ * parse failure will result in a call to the ErrorReporter from
+ * CompilerEnvirons.)
+ */
+ public ScriptOrFnNode parse(String sourceString,
+ String sourceURI, int lineno)
+ {
+ this.sourceURI = sourceURI;
+ this.ts = new TokenStream(this, null, sourceString, lineno);
+ try {
+ return parse();
+ } catch (IOException ex) {
+ // Should never happen
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * Build a parse tree from the given sourceString.
+ *
+ * @return an Object representing the parsed
+ * program. If the parse fails, null will be returned. (The
+ * parse failure will result in a call to the ErrorReporter from
+ * CompilerEnvirons.)
+ */
+ public ScriptOrFnNode parse(Reader sourceReader,
+ String sourceURI, int lineno)
+ throws IOException
+ {
+ this.sourceURI = sourceURI;
+ this.ts = new TokenStream(this, sourceReader, null, lineno);
+ return parse();
+ }
+
+ private ScriptOrFnNode parse()
+ throws IOException
+ {
+ this.decompiler = createDecompiler(compilerEnv);
+ this.nf = new IRFactory(this);
+ currentScriptOrFn = nf.createScript();
+ int sourceStartOffset = decompiler.getCurrentOffset();
+ this.encodedSource = null;
+ decompiler.addToken(Token.SCRIPT);
+
+ this.currentFlaggedToken = Token.EOF;
+ this.syntaxErrorCount = 0;
+
+ int baseLineno = ts.getLineno(); // line number where source starts
+
+ /* so we have something to add nodes to until
+ * we've collected all the source */
+ Node pn = nf.createLeaf(Token.BLOCK);
+
+ try {
+ for (;;) {
+ int tt = peekToken();
+
+ if (tt <= Token.EOF) {
+ break;
+ }
+
+ Node n;
+ if (tt == Token.FUNCTION) {
+ consumeToken();
+ try {
+ n = function(calledByCompileFunction
+ ? FunctionNode.FUNCTION_EXPRESSION
+ : FunctionNode.FUNCTION_STATEMENT);
+ } catch (ParserException e) {
+ break;
+ }
+ } else {
+ n = statement();
+ }
+ nf.addChildToBack(pn, n);
+ }
+ } catch (StackOverflowError ex) {
+ String msg = ScriptRuntime.getMessage0(
+ "msg.too.deep.parser.recursion");
+ throw Context.reportRuntimeError(msg, sourceURI,
+ ts.getLineno(), null, 0);
+ }
+
+ if (this.syntaxErrorCount != 0) {
+ String msg = String.valueOf(this.syntaxErrorCount);
+ msg = ScriptRuntime.getMessage1("msg.got.syntax.errors", msg);
+ throw errorReporter.runtimeError(msg, sourceURI, baseLineno,
+ null, 0);
+ }
+
+ currentScriptOrFn.setSourceName(sourceURI);
+ currentScriptOrFn.setBaseLineno(baseLineno);
+ currentScriptOrFn.setEndLineno(ts.getLineno());
+
+ int sourceEndOffset = decompiler.getCurrentOffset();
+ currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,
+ sourceEndOffset);
+
+ nf.initScript(currentScriptOrFn, pn);
+
+ if (compilerEnv.isGeneratingSource()) {
+ encodedSource = decompiler.getEncodedSource();
+ }
+ this.decompiler = null; // It helps GC
+
+ return currentScriptOrFn;
+ }
+
+ /*
+ * The C version of this function takes an argument list,
+ * which doesn't seem to be needed for tree generation...
+ * it'd only be useful for checking argument hiding, which
+ * I'm not doing anyway...
+ */
+ private Node parseFunctionBody()
+ throws IOException
+ {
+ ++nestingOfFunction;
+ Node pn = nf.createBlock(ts.getLineno());
+ try {
+ bodyLoop: for (;;) {
+ Node n;
+ int tt = peekToken();
+ switch (tt) {
+ case Token.ERROR:
+ case Token.EOF:
+ case Token.RC:
+ break bodyLoop;
+
+ case Token.FUNCTION:
+ consumeToken();
+ n = function(FunctionNode.FUNCTION_STATEMENT);
+ break;
+ default:
+ n = statement();
+ break;
+ }
+ nf.addChildToBack(pn, n);
+ }
+ } catch (ParserException e) {
+ // Ignore it
+ } finally {
+ --nestingOfFunction;
+ }
+
+ return pn;
+ }
+
+ private Node function(int functionType)
+ throws IOException, ParserException
+ {
+ int syntheticType = functionType;
+ int baseLineno = ts.getLineno(); // line number where source starts
+
+ int functionSourceStart = decompiler.markFunctionStart(functionType);
+ String name;
+ Node memberExprNode = null;
+ if (matchToken(Token.NAME)) {
+ name = ts.getString();
+ decompiler.addName(name);
+ if (!matchToken(Token.LP)) {
+ if (compilerEnv.isAllowMemberExprAsFunctionName()) {
+ // Extension to ECMA: if 'function <name>' does not follow
+ // by '(', assume <name> starts memberExpr
+ Node memberExprHead = nf.createName(name);
+ name = "";
+ memberExprNode = memberExprTail(false, memberExprHead);
+ }
+ mustMatchToken(Token.LP, "msg.no.paren.parms");
+ }
+ } else if (matchToken(Token.LP)) {
+ // Anonymous function
+ name = "";
+ } else {
+ name = "";
+ if (compilerEnv.isAllowMemberExprAsFunctionName()) {
+ // Note that memberExpr can not start with '(' like
+ // in function (1+2).toString(), because 'function (' already
+ // processed as anonymous function
+ memberExprNode = memberExpr(false);
+ }
+ mustMatchToken(Token.LP, "msg.no.paren.parms");
+ }
+
+ if (memberExprNode != null) {
+ syntheticType = FunctionNode.FUNCTION_EXPRESSION;
+ }
+
+ boolean nested = insideFunction();
+
+ FunctionNode fnNode = nf.createFunction(name);
+ if (nested || nestingOfWith > 0) {
+ // 1. Nested functions are not affected by the dynamic scope flag
+ // as dynamic scope is already a parent of their scope.
+ // 2. Functions defined under the with statement also immune to
+ // this setup, in which case dynamic scope is ignored in favor
+ // of with object.
+ fnNode.itsIgnoreDynamicScope = true;
+ }
+
+ int functionIndex = currentScriptOrFn.addFunction(fnNode);
+
+ int functionSourceEnd;
+
+ ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
+ currentScriptOrFn = fnNode;
+ int savedNestingOfWith = nestingOfWith;
+ nestingOfWith = 0;
+ Hashtable savedLabelSet = labelSet;
+ labelSet = null;
+ ObjArray savedLoopSet = loopSet;
+ loopSet = null;
+ ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
+ loopAndSwitchSet = null;
+ boolean savedHasReturnValue = hasReturnValue;
+ int savedFunctionEndFlags = functionEndFlags;
+
+ Node body;
+ try {
+ decompiler.addToken(Token.LP);
+ if (!matchToken(Token.RP)) {
+ boolean first = true;
+ do {
+ if (!first)
+ decompiler.addToken(Token.COMMA);
+ first = false;
+ mustMatchToken(Token.NAME, "msg.no.parm");
+ String s = ts.getString();
+ if (fnNode.hasParamOrVar(s)) {
+ addWarning("msg.dup.parms", s);
+ }
+ fnNode.addParam(s);
+ decompiler.addName(s);
+ } while (matchToken(Token.COMMA));
+
+ mustMatchToken(Token.RP, "msg.no.paren.after.parms");
+ }
+ decompiler.addToken(Token.RP);
+
+ mustMatchToken(Token.LC, "msg.no.brace.body");
+ decompiler.addEOL(Token.LC);
+ body = parseFunctionBody();
+ mustMatchToken(Token.RC, "msg.no.brace.after.body");
+
+ if (compilerEnv.isStrictMode() && !body.hasConsistentReturnUsage())
+ {
+ String msg = name.length() > 0 ? "msg.no.return.value"
+ : "msg.anon.no.return.value";
+ addStrictWarning(msg, name);
+ }
+
+ decompiler.addToken(Token.RC);
+ functionSourceEnd = decompiler.markFunctionEnd(functionSourceStart);
+ if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
+ // Add EOL only if function is not part of expression
+ // since it gets SEMI + EOL from Statement in that case
+ decompiler.addToken(Token.EOL);
+ }
+ }
+ finally {
+ hasReturnValue = savedHasReturnValue;
+ functionEndFlags = savedFunctionEndFlags;
+ loopAndSwitchSet = savedLoopAndSwitchSet;
+ loopSet = savedLoopSet;
+ labelSet = savedLabelSet;
+ nestingOfWith = savedNestingOfWith;
+ currentScriptOrFn = savedScriptOrFn;
+ }
+
+ fnNode.setEncodedSourceBounds(functionSourceStart, functionSourceEnd);
+ fnNode.setSourceName(sourceURI);
+ fnNode.setBaseLineno(baseLineno);
+ fnNode.setEndLineno(ts.getLineno());
+
+ if (name != null) {
+ int index = currentScriptOrFn.getParamOrVarIndex(name);
+ if (index >= 0 && index < currentScriptOrFn.getParamCount())
+ addStrictWarning("msg.var.hides.arg", name);
+ }
+
+ Node pn = nf.initFunction(fnNode, functionIndex, body, syntheticType);
+ if (memberExprNode != null) {
+ pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn);
+ if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
+ // XXX check JScript behavior: should it be createExprStatement?
+ pn = nf.createExprStatementNoReturn(pn, baseLineno);
+ }
+ }
+ return pn;
+ }
+
+ private Node statements()
+ throws IOException
+ {
+ Node pn = nf.createBlock(ts.getLineno());
+
+ int tt;
+ while((tt = peekToken()) > Token.EOF && tt != Token.RC) {
+ nf.addChildToBack(pn, statement());
+ }
+
+ return pn;
+ }
+
+ private Node condition()
+ throws IOException, ParserException
+ {
+ mustMatchToken(Token.LP, "msg.no.paren.cond");
+ decompiler.addToken(Token.LP);
+ Node pn = expr(false);
+ mustMatchToken(Token.RP, "msg.no.paren.after.cond");
+ decompiler.addToken(Token.RP);
+
+ // Report strict warning on code like "if (a = 7) ...". Suppress the
+ // warning if the condition is parenthesized, like "if ((a = 7)) ...".
+ if (pn.getProp(Node.PARENTHESIZED_PROP) == null &&
+ (pn.getType() == Token.SETNAME || pn.getType() == Token.SETPROP ||
+ pn.getType() == Token.SETELEM))
+ {
+ addStrictWarning("msg.equal.as.assign", "");
+ }
+ return pn;
+ }
+
+ // match a NAME; return null if no match.
+ private Node matchJumpLabelName()
+ throws IOException, ParserException
+ {
+ Node label = null;
+
+ int tt = peekTokenOrEOL();
+ if (tt == Token.NAME) {
+ consumeToken();
+ String name = ts.getString();
+ decompiler.addName(name);
+ if (labelSet != null) {
+ label = (Node)labelSet.get(name);
+ }
+ if (label == null) {
+ reportError("msg.undef.label");
+ }
+ }
+
+ return label;
+ }
+
+ private Node statement()
+ throws IOException
+ {
+ try {
+ Node pn = statementHelper(null);
+ if (pn != null) {
+ if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
+ addStrictWarning("msg.no.side.effects", "");
+ return pn;
+ }
+ } catch (ParserException e) { }
+
+ // skip to end of statement
+ int lineno = ts.getLineno();
+ guessingStatementEnd: for (;;) {
+ int tt = peekTokenOrEOL();
+ consumeToken();
+ switch (tt) {
+ case Token.ERROR:
+ case Token.EOF:
+ case Token.EOL:
+ case Token.SEMI:
+ break guessingStatementEnd;
+ }
+ }
+ return nf.createExprStatement(nf.createName("error"), lineno);
+ }
+
+ /**
+ * Whether the "catch (e: e instanceof Exception) { ... }" syntax
+ * is implemented.
+ */
+
+ private Node statementHelper(Node statementLabel)
+ throws IOException, ParserException
+ {
+ Node pn = null;
+
+ int tt;
+
+ tt = peekToken();
+
+ switch(tt) {
+ case Token.IF: {
+ consumeToken();
+
+ decompiler.addToken(Token.IF);
+ int lineno = ts.getLineno();
+ Node cond = condition();
+ decompiler.addEOL(Token.LC);
+ Node ifTrue = statement();
+ Node ifFalse = null;
+ if (matchToken(Token.ELSE)) {
+ decompiler.addToken(Token.RC);
+ decompiler.addToken(Token.ELSE);
+ decompiler.addEOL(Token.LC);
+ ifFalse = statement();
+ }
+ decompiler.addEOL(Token.RC);
+ pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
+ return pn;
+ }
+
+ case Token.SWITCH: {
+ consumeToken();
+
+ decompiler.addToken(Token.SWITCH);
+ int lineno = ts.getLineno();
+ mustMatchToken(Token.LP, "msg.no.paren.switch");
+ decompiler.addToken(Token.LP);
+ pn = enterSwitch(expr(false), lineno);
+ try {
+ mustMatchToken(Token.RP, "msg.no.paren.after.switch");
+ decompiler.addToken(Token.RP);
+ mustMatchToken(Token.LC, "msg.no.brace.switch");
+ decompiler.addEOL(Token.LC);
+
+ boolean hasDefault = false;
+ switchLoop: for (;;) {
+ tt = nextToken();
+ Node caseExpression;
+ switch (tt) {
+ case Token.RC:
+ break switchLoop;
+
+ case Token.CASE:
+ decompiler.addToken(Token.CASE);
+ caseExpression = expr(false);
+ mustMatchToken(Token.COLON, "msg.no.colon.case");
+ decompiler.addEOL(Token.COLON);
+ break;
+
+ case Token.DEFAULT:
+ if (hasDefault) {
+ reportError("msg.double.switch.default");
+ }
+ decompiler.addToken(Token.DEFAULT);
+ hasDefault = true;
+ caseExpression = null;
+ mustMatchToken(Token.COLON, "msg.no.colon.case");
+ decompiler.addEOL(Token.COLON);
+ break;
+
+ default:
+ reportError("msg.bad.switch");
+ break switchLoop;
+ }
+
+ Node block = nf.createLeaf(Token.BLOCK);
+ while ((tt = peekToken()) != Token.RC
+ && tt != Token.CASE
+ && tt != Token.DEFAULT
+ && tt != Token.EOF)
+ {
+ nf.addChildToBack(block, statement());
+ }
+
+ // caseExpression == null => add default lable
+ nf.addSwitchCase(pn, caseExpression, block);
+ }
+ decompiler.addEOL(Token.RC);
+ nf.closeSwitch(pn);
+ } finally {
+ exitSwitch();
+ }
+ return pn;
+ }
+
+ case Token.WHILE: {
+ consumeToken();
+ decompiler.addToken(Token.WHILE);
+
+ Node loop = enterLoop(statementLabel);
+ try {
+ Node cond = condition();
+ decompiler.addEOL(Token.LC);
+ Node body = statement();
+ decompiler.addEOL(Token.RC);
+ pn = nf.createWhile(loop, cond, body);
+ } finally {
+ exitLoop();
+ }
+ return pn;
+ }
+
+ case Token.DO: {
+ consumeToken();
+ decompiler.addToken(Token.DO);
+ decompiler.addEOL(Token.LC);
+
+ Node loop = enterLoop(statementLabel);
+ try {
+ Node body = statement();
+ decompiler.addToken(Token.RC);
+ mustMatchToken(Token.WHILE, "msg.no.while.do");
+ decompiler.addToken(Token.WHILE);
+ Node cond = condition();
+ pn = nf.createDoWhile(loop, body, cond);
+ } finally {
+ exitLoop();
+ }
+ // Always auto-insert semicon to follow SpiderMonkey:
+ // It is required by EMAScript but is ignored by the rest of
+ // world, see bug 238945
+ matchToken(Token.SEMI);
+ decompiler.addEOL(Token.SEMI);
+ return pn;
+ }
+
+ case Token.FOR: {
+ consumeToken();
+ boolean isForEach = false;
+ decompiler.addToken(Token.FOR);
+
+ Node loop = enterLoop(statementLabel);
+ try {
+
+ Node init; // Node init is also foo in 'foo in Object'
+ Node cond; // Node cond is also object in 'foo in Object'
+ Node incr = null; // to kill warning
+ Node body;
+
+ // See if this is a for each () instead of just a for ()
+ if (matchToken(Token.NAME)) {
+ decompiler.addName(ts.getString());
+ if (ts.getString().equals("each")) {
+ isForEach = true;
+ } else {
+ reportError("msg.no.paren.for");
+ }
+ }
+
+ mustMatchToken(Token.LP, "msg.no.paren.for");
+ decompiler.addToken(Token.LP);
+ tt = peekToken();
+ if (tt == Token.SEMI) {
+ init = nf.createLeaf(Token.EMPTY);
+ } else {
+ if (tt == Token.VAR) {
+ // set init to a var list or initial
+ consumeToken(); // consume the 'var' token
+ init = variables(Token.FOR);
+ }
+ else {
+ init = expr(true);
+ }
+ }
+
+ if (matchToken(Token.IN)) {
+ decompiler.addToken(Token.IN);
+ // 'cond' is the object over which we're iterating
+ cond = expr(false);
+ } else { // ordinary for loop
+ mustMatchToken(Token.SEMI, "msg.no.semi.for");
+ decompiler.addToken(Token.SEMI);
+ if (peekToken() == Token.SEMI) {
+ // no loop condition
+ cond = nf.createLeaf(Token.EMPTY);
+ } else {
+ cond = expr(false);
+ }
+
+ mustMatchToken(Token.SEMI, "msg.no.semi.for.cond");
+ decompiler.addToken(Token.SEMI);
+ if (peekToken() == Token.RP) {
+ incr = nf.createLeaf(Token.EMPTY);
+ } else {
+ incr = expr(false);
+ }
+ }
+
+ mustMatchToken(Token.RP, "msg.no.paren.for.ctrl");
+ decompiler.addToken(Token.RP);
+ decompiler.addEOL(Token.LC);
+ body = statement();
+ decompiler.addEOL(Token.RC);
+
+ if (incr == null) {
+ // cond could be null if 'in obj' got eaten
+ // by the init node.
+ pn = nf.createForIn(loop, init, cond, body, isForEach);
+ } else {
+ pn = nf.createFor(loop, init, cond, incr, body);
+ }
+ } finally {
+ exitLoop();
+ }
+ return pn;
+ }
+
+ case Token.TRY: {
+ consumeToken();
+ int lineno = ts.getLineno();
+
+ Node tryblock;
+ Node catchblocks = null;
+ Node finallyblock = null;
+
+ decompiler.addToken(Token.TRY);
+ decompiler.addEOL(Token.LC);
+ tryblock = statement();
+ decompiler.addEOL(Token.RC);
+
+ catchblocks = nf.createLeaf(Token.BLOCK);
+
+ boolean sawDefaultCatch = false;
+ int peek = peekToken();
+ if (peek == Token.CATCH) {
+ while (matchToken(Token.CATCH)) {
+ if (sawDefaultCatch) {
+ reportError("msg.catch.unreachable");
+ }
+ decompiler.addToken(Token.CATCH);
+ mustMatchToken(Token.LP, "msg.no.paren.catch");
+ decompiler.addToken(Token.LP);
+
+ mustMatchToken(Token.NAME, "msg.bad.catchcond");
+ String varName = ts.getString();
+ decompiler.addName(varName);
+
+ Node catchCond = null;
+ if (matchToken(Token.IF)) {
+ decompiler.addToken(Token.IF);
+ catchCond = expr(false);
+ } else {
+ sawDefaultCatch = true;
+ }
+
+ mustMatchToken(Token.RP, "msg.bad.catchcond");
+ decompiler.addToken(Token.RP);
+ mustMatchToken(Token.LC, "msg.no.brace.catchblock");
+ decompiler.addEOL(Token.LC);
+
+ nf.addChildToBack(catchblocks,
+ nf.createCatch(varName, catchCond,
+ statements(),
+ ts.getLineno()));
+
+ mustMatchToken(Token.RC, "msg.no.brace.after.body");
+ decompiler.addEOL(Token.RC);
+ }
+ } else if (peek != Token.FINALLY) {
+ mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally");
+ }
+
+ if (matchToken(Token.FINALLY)) {
+ decompiler.addToken(Token.FINALLY);
+ decompiler.addEOL(Token.LC);
+ finallyblock = statement();
+ decompiler.addEOL(Token.RC);
+ }
+
+ pn = nf.createTryCatchFinally(tryblock, catchblocks,
+ finallyblock, lineno);
+
+ return pn;
+ }
+
+ case Token.THROW: {
+ consumeToken();
+ if (peekTokenOrEOL() == Token.EOL) {
+ // ECMAScript does not allow new lines before throw expression,
+ // see bug 256617
+ reportError("msg.bad.throw.eol");
+ }
+
+ int lineno = ts.getLineno();
+ decompiler.addToken(Token.THROW);
+ pn = nf.createThrow(expr(false), lineno);
+ break;
+ }
+
+ case Token.BREAK: {
+ consumeToken();
+ int lineno = ts.getLineno();
+
+ decompiler.addToken(Token.BREAK);
+
+ // matchJumpLabelName only matches if there is one
+ Node breakStatement = matchJumpLabelName();
+ if (breakStatement == null) {
+ if (loopAndSwitchSet == null || loopAndSwitchSet.size() == 0) {
+ reportError("msg.bad.break");
+ return null;
+ }
+ breakStatement = (Node)loopAndSwitchSet.peek();
+ }
+ pn = nf.createBreak(breakStatement, lineno);
+ break;
+ }
+
+ case Token.CONTINUE: {
+ consumeToken();
+ int lineno = ts.getLineno();
+
+ decompiler.addToken(Token.CONTINUE);
+
+ Node loop;
+ // matchJumpLabelName only matches if there is one
+ Node label = matchJumpLabelName();
+ if (label == null) {
+ if (loopSet == null || loopSet.size() == 0) {
+ reportError("msg.continue.outside");
+ return null;
+ }
+ loop = (Node)loopSet.peek();
+ } else {
+ loop = nf.getLabelLoop(label);
+ if (loop == null) {
+ reportError("msg.continue.nonloop");
+ return null;
+ }
+ }
+ pn = nf.createContinue(loop, lineno);
+ break;
+ }
+
+ case Token.WITH: {
+ consumeToken();
+
+ decompiler.addToken(Token.WITH);
+ int lineno = ts.getLineno();
+ mustMatchToken(Token.LP, "msg.no.paren.with");
+ decompiler.addToken(Token.LP);
+ Node obj = expr(false);
+ mustMatchToken(Token.RP, "msg.no.paren.after.with");
+ decompiler.addToken(Token.RP);
+ decompiler.addEOL(Token.LC);
+
+ ++nestingOfWith;
+ Node body;
+ try {
+ body = statement();
+ } finally {
+ --nestingOfWith;
+ }
+
+ decompiler.addEOL(Token.RC);
+
+ pn = nf.createWith(obj, body, lineno);
+ return pn;
+ }
+
+ case Token.CONST:
+ case Token.VAR: {
+ consumeToken();
+ pn = variables(tt);
+ break;
+ }
+
+ case Token.RETURN: {
+ if (!insideFunction()) {
+ reportError("msg.bad.return");
+ }
+ consumeToken();
+ decompiler.addToken(Token.RETURN);
+ int lineno = ts.getLineno();
+
+ Node retExpr;
+ /* This is ugly, but we don't want to require a semicolon. */
+ tt = peekTokenOrEOL();
+ switch (tt) {
+ case Token.SEMI:
+ case Token.RC:
+ case Token.EOF:
+ case Token.EOL:
+ case Token.ERROR:
+ retExpr = null;
+ break;
+ default:
+ retExpr = expr(false);
+ hasReturnValue = true;
+ }
+ pn = nf.createReturn(retExpr, lineno);
+
+ // see if we need a strict mode warning
+ if (retExpr == null) {
+ if (functionEndFlags == Node.END_RETURNS_VALUE)
+ addStrictWarning("msg.return.inconsistent", "");
+
+ functionEndFlags |= Node.END_RETURNS;
+ } else {
+ if (functionEndFlags == Node.END_RETURNS)
+ addStrictWarning("msg.return.inconsistent", "");
+
+ functionEndFlags |= Node.END_RETURNS_VALUE;
+ }
+
+ break;
+ }
+
+ case Token.LC:
+ consumeToken();
+ if (statementLabel != null) {
+ decompiler.addToken(Token.LC);
+ }
+ pn = statements();
+ mustMatchToken(Token.RC, "msg.no.brace.block");
+ if (statementLabel != null) {
+ decompiler.addEOL(Token.RC);
+ }
+ return pn;
+
+ case Token.ERROR:
+ // Fall thru, to have a node for error recovery to work on
+ case Token.SEMI:
+ consumeToken();
+ pn = nf.createLeaf(Token.EMPTY);
+ return pn;
+
+ case Token.FUNCTION: {
+ consumeToken();
+ pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);
+ return pn;
+ }
+
+ case Token.DEFAULT :
+ consumeToken();
+ mustHaveXML();
+
+ decompiler.addToken(Token.DEFAULT);
+ int nsLine = ts.getLineno();
+
+ if (!(matchToken(Token.NAME)
+ && ts.getString().equals("xml")))
+ {
+ reportError("msg.bad.namespace");
+ }
+ decompiler.addName(" xml");
+
+ if (!(matchToken(Token.NAME)
+ && ts.getString().equals("namespace")))
+ {
+ reportError("msg.bad.namespace");
+ }
+ decompiler.addName(" namespace");
+
+ if (!matchToken(Token.ASSIGN)) {
+ reportError("msg.bad.namespace");
+ }
+ decompiler.addToken(Token.ASSIGN);
+
+ Node expr = expr(false);
+ pn = nf.createDefaultNamespace(expr, nsLine);
+ break;
+
+ case Token.NAME: {
+ int lineno = ts.getLineno();
+ String name = ts.getString();
+ setCheckForLabel();
+ pn = expr(false);
+ if (pn.getType() != Token.LABEL) {
+ pn = nf.createExprStatement(pn, lineno);
+ } else {
+ // Parsed the label: push back token should be
+ // colon that primaryExpr left untouched.
+ if (peekToken() != Token.COLON) Kit.codeBug();
+ consumeToken();
+ // depend on decompiling lookahead to guess that that
+ // last name was a label.
+ decompiler.addName(name);
+ decompiler.addEOL(Token.COLON);
+
+ if (labelSet == null) {
+ labelSet = new Hashtable();
+ } else if (labelSet.containsKey(name)) {
+ reportError("msg.dup.label");
+ }
+
+ boolean firstLabel;
+ if (statementLabel == null) {
+ firstLabel = true;
+ statementLabel = pn;
+ } else {
+ // Discard multiple label nodes and use only
+ // the first: it allows to simplify IRFactory
+ firstLabel = false;
+ }
+ labelSet.put(name, statementLabel);
+ try {
+ pn = statementHelper(statementLabel);
+ } finally {
+ labelSet.remove(name);
+ }
+ if (firstLabel) {
+ pn = nf.createLabeledStatement(statementLabel, pn);
+ }
+ return pn;
+ }
+ break;
+ }
+
+ default: {
+ int lineno = ts.getLineno();
+ pn = expr(false);
+ pn = nf.createExprStatement(pn, lineno);
+ break;
+ }
+ }
+
+ int ttFlagged = peekFlaggedToken();
+ switch (ttFlagged & CLEAR_TI_MASK) {
+ case Token.SEMI:
+ // Consume ';' as a part of expression
+ consumeToken();
+ break;
+ case Token.ERROR:
+ case Token.EOF:
+ case Token.RC:
+ // Autoinsert ;
+ break;
+ default:
+ if ((ttFlagged & TI_AFTER_EOL) == 0) {
+ // Report error if no EOL or autoinsert ; otherwise
+ reportError("msg.no.semi.stmt");
+ }
+ break;
+ }
+ decompiler.addEOL(Token.SEMI);
+
+ return pn;
+ }
+
+ /**
+ * Parse a 'var' or 'const' statement, or a 'var' init list in a for
+ * statement.
+ * @param context A token value: either VAR, CONST or FOR depending on
+ * context.
+ * @return The parsed statement
+ * @throws IOException
+ * @throws ParserException
+ */
+ private Node variables(int context)
+ throws IOException, ParserException
+ {
+ Node pn;
+ boolean first = true;
+
+ if (context == Token.CONST){
+ pn = nf.createVariables(Token.CONST, ts.getLineno());
+ decompiler.addToken(Token.CONST);
+ } else {
+ pn = nf.createVariables(Token.VAR, ts.getLineno());
+ decompiler.addToken(Token.VAR);
+ }
+
+ for (;;) {
+ Node name;
+ Node init;
+ mustMatchToken(Token.NAME, "msg.bad.var");
+ String s = ts.getString();
+
+ if (!first)
+ decompiler.addToken(Token.COMMA);
+ first = false;
+
+ decompiler.addName(s);
+
+ if (context == Token.CONST) {
+ if (!currentScriptOrFn.addConst(s)) {
+ // We know it's already defined, since addConst passes if
+ // it's not defined at all. The addVar call just confirms
+ // what it is.
+ if (currentScriptOrFn.addVar(s) != ScriptOrFnNode.DUPLICATE_CONST)
+ addError("msg.var.redecl", s);
+ else
+ addError("msg.const.redecl", s);
+ }
+ } else {
+ int dupState = currentScriptOrFn.addVar(s);
+ if (dupState == ScriptOrFnNode.DUPLICATE_CONST)
+ addError("msg.const.redecl", s);
+ else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER)
+ addStrictWarning("msg.var.hides.arg", s);
+ else if (dupState == ScriptOrFnNode.DUPLICATE_VAR)
+ addStrictWarning("msg.var.redecl", s);
+ }
+ name = nf.createName(s);
+
+ // omitted check for argument hiding
+
+ if (matchToken(Token.ASSIGN)) {
+ decompiler.addToken(Token.ASSIGN);
+
+ init = assignExpr(context == Token.FOR);
+ nf.addChildToBack(name, init);
+ }
+ nf.addChildToBack(pn, name);
+ if (!matchToken(Token.COMMA))
+ break;
+ }
+ return pn;
+ }
+
+ private Node expr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = assignExpr(inForInit);
+ while (matchToken(Token.COMMA)) {
+ decompiler.addToken(Token.COMMA);
+ if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
+ addStrictWarning("msg.no.side.effects", "");
+ pn = nf.createBinary(Token.COMMA, pn, assignExpr(inForInit));
+ }
+ return pn;
+ }
+
+ private Node assignExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = condExpr(inForInit);
+
+ int tt = peekToken();
+ if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) {
+ consumeToken();
+ decompiler.addToken(tt);
+ pn = nf.createAssignment(tt, pn, assignExpr(inForInit));
+ }
+
+ return pn;
+ }
+
+ private Node condExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = orExpr(inForInit);
+
+ if (matchToken(Token.HOOK)) {
+ decompiler.addToken(Token.HOOK);
+ Node ifTrue = assignExpr(false);
+ mustMatchToken(Token.COLON, "msg.no.colon.cond");
+ decompiler.addToken(Token.COLON);
+ Node ifFalse = assignExpr(inForInit);
+ return nf.createCondExpr(pn, ifTrue, ifFalse);
+ }
+
+ return pn;
+ }
+
+ private Node orExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = andExpr(inForInit);
+ if (matchToken(Token.OR)) {
+ decompiler.addToken(Token.OR);
+ pn = nf.createBinary(Token.OR, pn, orExpr(inForInit));
+ }
+
+ return pn;
+ }
+
+ private Node andExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = bitOrExpr(inForInit);
+ if (matchToken(Token.AND)) {
+ decompiler.addToken(Token.AND);
+ pn = nf.createBinary(Token.AND, pn, andExpr(inForInit));
+ }
+
+ return pn;
+ }
+
+ private Node bitOrExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = bitXorExpr(inForInit);
+ while (matchToken(Token.BITOR)) {
+ decompiler.addToken(Token.BITOR);
+ pn = nf.createBinary(Token.BITOR, pn, bitXorExpr(inForInit));
+ }
+ return pn;
+ }
+
+ private Node bitXorExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = bitAndExpr(inForInit);
+ while (matchToken(Token.BITXOR)) {
+ decompiler.addToken(Token.BITXOR);
+ pn = nf.createBinary(Token.BITXOR, pn, bitAndExpr(inForInit));
+ }
+ return pn;
+ }
+
+ private Node bitAndExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = eqExpr(inForInit);
+ while (matchToken(Token.BITAND)) {
+ decompiler.addToken(Token.BITAND);
+ pn = nf.createBinary(Token.BITAND, pn, eqExpr(inForInit));
+ }
+ return pn;
+ }
+
+ private Node eqExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = relExpr(inForInit);
+ for (;;) {
+ int tt = peekToken();
+ switch (tt) {
+ case Token.EQ:
+ case Token.NE:
+ case Token.SHEQ:
+ case Token.SHNE:
+ consumeToken();
+ int decompilerToken = tt;
+ int parseToken = tt;
+ if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) {
+ // JavaScript 1.2 uses shallow equality for == and != .
+ // In addition, convert === and !== for decompiler into
+ // == and != since the decompiler is supposed to show
+ // canonical source and in 1.2 ===, !== are allowed
+ // only as an alias to ==, !=.
+ switch (tt) {
+ case Token.EQ:
+ parseToken = Token.SHEQ;
+ break;
+ case Token.NE:
+ parseToken = Token.SHNE;
+ break;
+ case Token.SHEQ:
+ decompilerToken = Token.EQ;
+ break;
+ case Token.SHNE:
+ decompilerToken = Token.NE;
+ break;
+ }
+ }
+ decompiler.addToken(decompilerToken);
+ pn = nf.createBinary(parseToken, pn, relExpr(inForInit));
+ continue;
+ }
+ break;
+ }
+ return pn;
+ }
+
+ private Node relExpr(boolean inForInit)
+ throws IOException, ParserException
+ {
+ Node pn = shiftExpr();
+ for (;;) {
+ int tt = peekToken();
+ switch (tt) {
+ case Token.IN:
+ if (inForInit)
+ break;
+ // fall through
+ case Token.INSTANCEOF:
+ case Token.LE:
+ case Token.LT:
+ case Token.GE:
+ case Token.GT:
+ consumeToken();
+ decompiler.addToken(tt);
+ pn = nf.createBinary(tt, pn, shiftExpr());
+ continue;
+ }
+ break;
+ }
+ return pn;
+ }
+
+ private Node shiftExpr()
+ throws IOException, ParserException
+ {
+ Node pn = addExpr();
+ for (;;) {
+ int tt = peekToken();
+ switch (tt) {
+ case Token.LSH:
+ case Token.URSH:
+ case Token.RSH:
+ consumeToken();
+ decompiler.addToken(tt);
+ pn = nf.createBinary(tt, pn, addExpr());
+ continue;
+ }
+ break;
+ }
+ return pn;
+ }
+
+ private Node addExpr()
+ throws IOException, ParserException
+ {
+ Node pn = mulExpr();
+ for (;;) {
+ int tt = peekToken();
+ if (tt == Token.ADD || tt == Token.SUB) {
+ consumeToken();
+ decompiler.addToken(tt);
+ // flushNewLines
+ pn = nf.createBinary(tt, pn, mulExpr());
+ continue;
+ }
+ break;
+ }
+
+ return pn;
+ }
+
+ private Node mulExpr()
+ throws IOException, ParserException
+ {
+ Node pn = unaryExpr();
+ for (;;) {
+ int tt = peekToken();
+ switch (tt) {
+ case Token.MUL:
+ case Token.DIV:
+ case Token.MOD:
+ consumeToken();
+ decompiler.addToken(tt);
+ pn = nf.createBinary(tt, pn, unaryExpr());
+ continue;
+ }
+ break;
+ }
+
+ return pn;
+ }
+
+ private Node unaryExpr()
+ throws IOException, ParserException
+ {
+ int tt;
+
+ tt = peekToken();
+
+ switch(tt) {
+ case Token.VOID:
+ case Token.NOT:
+ case Token.BITNOT:
+ case Token.TYPEOF:
+ consumeToken();
+ decompiler.addToken(tt);
+ return nf.createUnary(tt, unaryExpr());
+
+ case Token.ADD:
+ consumeToken();
+ // Convert to special POS token in decompiler and parse tree
+ decompiler.addToken(Token.POS);
+ return nf.createUnary(Token.POS, unaryExpr());
+
+ case Token.SUB:
+ consumeToken();
+ // Convert to special NEG token in decompiler and parse tree
+ decompiler.addToken(Token.NEG);
+ return nf.createUnary(Token.NEG, unaryExpr());
+
+ case Token.INC:
+ case Token.DEC:
+ consumeToken();
+ decompiler.addToken(tt);
+ return nf.createIncDec(tt, false, memberExpr(true));
+
+ case Token.DELPROP:
+ consumeToken();
+ decompiler.addToken(Token.DELPROP);
+ return nf.createUnary(Token.DELPROP, unaryExpr());
+
+ case Token.ERROR:
+ consumeToken();
+ break;
+
+ // XML stream encountered in expression.
+ case Token.LT:
+ if (compilerEnv.isXmlAvailable()) {
+ consumeToken();
+ Node pn = xmlInitializer();
+ return memberExprTail(true, pn);
+ }
+ // Fall thru to the default handling of RELOP
+
+ default:
+ Node pn = memberExpr(true);
+
+ // Don't look across a newline boundary for a postfix incop.
+ tt = peekTokenOrEOL();
+ if (tt == Token.INC || tt == Token.DEC) {
+ consumeToken();
+ decompiler.addToken(tt);
+ return nf.createIncDec(tt, true, pn);
+ }
+ return pn;
+ }
+ return nf.createName("err"); // Only reached on error. Try to continue.
+
+ }
+
+ private Node xmlInitializer() throws IOException
+ {
+ int tt = ts.getFirstXMLToken();
+ if (tt != Token.XML && tt != Token.XMLEND) {
+ reportError("msg.syntax");
+ return null;
+ }
+
+ /* Make a NEW node to append to. */
+ Node pnXML = nf.createLeaf(Token.NEW);
+
+ String xml = ts.getString();
+ boolean fAnonymous = xml.trim().startsWith("<>");
+
+ Node pn = nf.createName(fAnonymous ? "XMLList" : "XML");
+ nf.addChildToBack(pnXML, pn);
+
+ pn = null;
+ Node expr;
+ for (;;tt = ts.getNextXMLToken()) {
+ switch (tt) {
+ case Token.XML:
+ xml = ts.getString();
+ decompiler.addName(xml);
+ mustMatchToken(Token.LC, "msg.syntax");
+ decompiler.addToken(Token.LC);
+ expr = (peekToken() == Token.RC)
+ ? nf.createString("")
+ : expr(false);
+ mustMatchToken(Token.RC, "msg.syntax");
+ decompiler.addToken(Token.RC);
+ if (pn == null) {
+ pn = nf.createString(xml);
+ } else {
+ pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
+ }
+ if (ts.isXMLAttribute()) {
+ /* Need to put the result in double quotes */
+ expr = nf.createUnary(Token.ESCXMLATTR, expr);
+ Node prepend = nf.createBinary(Token.ADD,
+ nf.createString("\""),
+ expr);
+ expr = nf.createBinary(Token.ADD,
+ prepend,
+ nf.createString("\""));
+ } else {
+ expr = nf.createUnary(Token.ESCXMLTEXT, expr);
+ }
+ pn = nf.createBinary(Token.ADD, pn, expr);
+ break;
+ case Token.XMLEND:
+ xml = ts.getString();
+ decompiler.addName(xml);
+ if (pn == null) {
+ pn = nf.createString(xml);
+ } else {
+ pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
+ }
+
+ nf.addChildToBack(pnXML, pn);
+ return pnXML;
+ default:
+ reportError("msg.syntax");
+ return null;
+ }
+ }
+ }
+
+ private void argumentList(Node listNode)
+ throws IOException, ParserException
+ {
+ boolean matched;
+ matched = matchToken(Token.RP);
+ if (!matched) {
+ boolean first = true;
+ do {
+ if (!first)
+ decompiler.addToken(Token.COMMA);
+ first = false;
+ nf.addChildToBack(listNode, assignExpr(false));
+ } while (matchToken(Token.COMMA));
+
+ mustMatchToken(Token.RP, "msg.no.paren.arg");
+ }
+ decompiler.addToken(Token.RP);
+ }
+
+ private Node memberExpr(boolean allowCallSyntax)
+ throws IOException, ParserException
+ {
+ int tt;
+
+ Node pn;
+
+ /* Check for new expressions. */
+ tt = peekToken();
+ if (tt == Token.NEW) {
+ /* Eat the NEW token. */
+ consumeToken();
+ decompiler.addToken(Token.NEW);
+
+ /* Make a NEW node to append to. */
+ pn = nf.createCallOrNew(Token.NEW, memberExpr(false));
+
+ if (matchToken(Token.LP)) {
+ decompiler.addToken(Token.LP);
+ /* Add the arguments to pn, if any are supplied. */
+ argumentList(pn);
+ }
+
+ /* XXX there's a check in the C source against
+ * "too many constructor arguments" - how many
+ * do we claim to support?
+ */
+
+ /* Experimental syntax: allow an object literal to follow a new expression,
+ * which will mean a kind of anonymous class built with the JavaAdapter.
+ * the object literal will be passed as an additional argument to the constructor.
+ */
+ tt = peekToken();
+ if (tt == Token.LC) {
+ nf.addChildToBack(pn, primaryExpr());
+ }
+ } else {
+ pn = primaryExpr();
+ }
+
+ return memberExprTail(allowCallSyntax, pn);
+ }
+
+ private Node memberExprTail(boolean allowCallSyntax, Node pn)
+ throws IOException, ParserException
+ {
+ tailLoop:
+ for (;;) {
+ int tt = peekToken();
+ switch (tt) {
+
+ case Token.DOT:
+ case Token.DOTDOT:
+ {
+ int memberTypeFlags;
+ String s;
+
+ consumeToken();
+ decompiler.addToken(tt);
+ memberTypeFlags = 0;
+ if (tt == Token.DOTDOT) {
+ mustHaveXML();
+ memberTypeFlags = Node.DESCENDANTS_FLAG;
+ }
+ if (!compilerEnv.isXmlAvailable()) {
+ mustMatchToken(Token.NAME, "msg.no.name.after.dot");
+ s = ts.getString();
+ decompiler.addName(s);
+ pn = nf.createPropertyGet(pn, null, s, memberTypeFlags);
+ break;
+ }
+
+ tt = nextToken();
+ switch (tt) {
+ // handles: name, ns::name, ns::*, ns::[expr]
+ case Token.NAME:
+ s = ts.getString();
+ decompiler.addName(s);
+ pn = propertyName(pn, s, memberTypeFlags);
+ break;
+
+ // handles: *, *::name, *::*, *::[expr]
+ case Token.MUL:
+ decompiler.addName("*");
+ pn = propertyName(pn, "*", memberTypeFlags);
+ break;
+
+ // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*',
+ // '@::attr', '@::*', '@*', '@*::attr', '@*::*'
+ case Token.XMLATTR:
+ decompiler.addToken(Token.XMLATTR);
+ pn = attributeAccess(pn, memberTypeFlags);
+ break;
+
+ default:
+ reportError("msg.no.name.after.dot");
+ }
+ }
+ break;
+
+ case Token.DOTQUERY:
+ consumeToken();
+ mustHaveXML();
+ decompiler.addToken(Token.DOTQUERY);
+ pn = nf.createDotQuery(pn, expr(false), ts.getLineno());
+ mustMatchToken(Token.RP, "msg.no.paren");
+ decompiler.addToken(Token.RP);
+ break;
+
+ case Token.LB:
+ consumeToken();
+ decompiler.addToken(Token.LB);
+ pn = nf.createElementGet(pn, null, expr(false), 0);
+ mustMatchToken(Token.RB, "msg.no.bracket.index");
+ decompiler.addToken(Token.RB);
+ break;
+
+ case Token.LP:
+ if (!allowCallSyntax) {
+ break tailLoop;
+ }
+ consumeToken();
+ decompiler.addToken(Token.LP);
+ pn = nf.createCallOrNew(Token.CALL, pn);
+ /* Add the arguments to pn, if any are supplied. */
+ argumentList(pn);
+ break;
+
+ default:
+ break tailLoop;
+ }
+ }
+ return pn;
+ }
+
+ /*
+ * Xml attribute expression:
+ * '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*'
+ */
+ private Node attributeAccess(Node pn, int memberTypeFlags)
+ throws IOException
+ {
+ memberTypeFlags |= Node.ATTRIBUTE_FLAG;
+ int tt = nextToken();
+
+ switch (tt) {
+ // handles: @name, @ns::name, @ns::*, @ns::[expr]
+ case Token.NAME:
+ {
+ String s = ts.getString();
+ decompiler.addName(s);
+ pn = propertyName(pn, s, memberTypeFlags);
+ }
+ break;
+
+ // handles: @*, @*::name, @*::*, @*::[expr]
+ case Token.MUL:
+ decompiler.addName("*");
+ pn = propertyName(pn, "*", memberTypeFlags);
+ break;
+
+ // handles @[expr]
+ case Token.LB:
+ decompiler.addToken(Token.LB);
+ pn = nf.createElementGet(pn, null, expr(false), memberTypeFlags);
+ mustMatchToken(Token.RB, "msg.no.bracket.index");
+ decompiler.addToken(Token.RB);
+ break;
+
+ default:
+ reportError("msg.no.name.after.xmlAttr");
+ pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags);
+ break;
+ }
+
+ return pn;
+ }
+
+ /**
+ * Check if :: follows name in which case it becomes qualified name
+ */
+ private Node propertyName(Node pn, String name, int memberTypeFlags)
+ throws IOException, ParserException
+ {
+ String namespace = null;
+ if (matchToken(Token.COLONCOLON)) {
+ decompiler.addToken(Token.COLONCOLON);
+ namespace = name;
+
+ int tt = nextToken();
+ switch (tt) {
+ // handles name::name
+ case Token.NAME:
+ name = ts.getString();
+ decompiler.addName(name);
+ break;
+
+ // handles name::*
+ case Token.MUL:
+ decompiler.addName("*");
+ name = "*";
+ break;
+
+ // handles name::[expr]
+ case Token.LB:
+ decompiler.addToken(Token.LB);
+ pn = nf.createElementGet(pn, namespace, expr(false),
+ memberTypeFlags);
+ mustMatchToken(Token.RB, "msg.no.bracket.index");
+ decompiler.addToken(Token.RB);
+ return pn;
+
+ default:
+ reportError("msg.no.name.after.coloncolon");
+ name = "?";
+ }
+ }
+
+ pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags);
+ return pn;
+ }
+
+ private Node primaryExpr()
+ throws IOException, ParserException
+ {
+ Node pn;
+
+ int ttFlagged = nextFlaggedToken();
+ int tt = ttFlagged & CLEAR_TI_MASK;
+
+ switch(tt) {
+
+ case Token.FUNCTION:
+ return function(FunctionNode.FUNCTION_EXPRESSION);
+
+ case Token.LB: {
+ ObjArray elems = new ObjArray();
+ int skipCount = 0;
+ decompiler.addToken(Token.LB);
+ boolean after_lb_or_comma = true;
+ for (;;) {
+ tt = peekToken();
+
+ if (tt == Token.COMMA) {
+ consumeToken();
+ decompiler.addToken(Token.COMMA);
+ if (!after_lb_or_comma) {
+ after_lb_or_comma = true;
+ } else {
+ elems.add(null);
+ ++skipCount;
+ }
+ } else if (tt == Token.RB) {
+ consumeToken();
+ decompiler.addToken(Token.RB);
+ break;
+ } else {
+ if (!after_lb_or_comma) {
+ reportError("msg.no.bracket.arg");
+ }
+ elems.add(assignExpr(false));
+ after_lb_or_comma = false;
+ }
+ }
+ return nf.createArrayLiteral(elems, skipCount);
+ }
+
+ case Token.LC: {
+ ObjArray elems = new ObjArray();
+ decompiler.addToken(Token.LC);
+ if (!matchToken(Token.RC)) {
+
+ boolean first = true;
+ commaloop:
+ do {
+ Object property;
+
+ if (!first)
+ decompiler.addToken(Token.COMMA);
+ else
+ first = false;
+
+ tt = peekToken();
+ switch(tt) {
+ case Token.NAME:
+ case Token.STRING:
+ consumeToken();
+ // map NAMEs to STRINGs in object literal context
+ // but tell the decompiler the proper type
+ String s = ts.getString();
+ if (tt == Token.NAME) {
+ if (s.equals("get") &&
+ peekToken() == Token.NAME) {
+ decompiler.addToken(Token.GET);
+ consumeToken();
+ s = ts.getString();
+ decompiler.addName(s);
+ property = ScriptRuntime.getIndexObject(s);
+ if (!getterSetterProperty(elems, property,
+ true))
+ break commaloop;
+ break;
+ } else if (s.equals("set") &&
+ peekToken() == Token.NAME) {
+ decompiler.addToken(Token.SET);
+ consumeToken();
+ s = ts.getString();
+ decompiler.addName(s);
+ property = ScriptRuntime.getIndexObject(s);
+ if (!getterSetterProperty(elems, property,
+ false))
+ break commaloop;
+ break;
+ }
+ decompiler.addName(s);
+ } else {
+ decompiler.addString(s);
+ }
+ property = ScriptRuntime.getIndexObject(s);
+ plainProperty(elems, property);
+ break;
+
+ case Token.NUMBER:
+ consumeToken();
+ double n = ts.getNumber();
+ decompiler.addNumber(n);
+ property = ScriptRuntime.getIndexObject(n);
+ plainProperty(elems, property);
+ break;
+
+ case Token.RC:
+ // trailing comma is OK.
+ break commaloop;
+ default:
+ reportError("msg.bad.prop");
+ break commaloop;
+ }
+ } while (matchToken(Token.COMMA));
+
+ mustMatchToken(Token.RC, "msg.no.brace.prop");
+ }
+ decompiler.addToken(Token.RC);
+ return nf.createObjectLiteral(elems);
+ }
+
+ case Token.LP:
+
+ /* Brendan's IR-jsparse.c makes a new node tagged with
+ * TOK_LP here... I'm not sure I understand why. Isn't
+ * the grouping already implicit in the structure of the
+ * parse tree? also TOK_LP is already overloaded (I
+ * think) in the C IR as 'function call.' */
+ decompiler.addToken(Token.LP);
+ pn = expr(false);
+ pn.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE);
+ decompiler.addToken(Token.RP);
+ mustMatchToken(Token.RP, "msg.no.paren");
+ return pn;
+
+ case Token.XMLATTR:
+ mustHaveXML();
+ decompiler.addToken(Token.XMLATTR);
+ pn = attributeAccess(null, 0);
+ return pn;
+
+ case Token.NAME: {
+ String name = ts.getString();
+ if ((ttFlagged & TI_CHECK_LABEL) != 0) {
+ if (peekToken() == Token.COLON) {
+ // Do not consume colon, it is used as unwind indicator
+ // to return to statementHelper.
+ // XXX Better way?
+ return nf.createLabel(ts.getLineno());
+ }
+ }
+
+ decompiler.addName(name);
+ if (compilerEnv.isXmlAvailable()) {
+ pn = propertyName(null, name, 0);
+ } else {
+ pn = nf.createName(name);
+ }
+ return pn;
+ }
+
+ case Token.NUMBER: {
+ double n = ts.getNumber();
+ decompiler.addNumber(n);
+ return nf.createNumber(n);
+ }
+
+ case Token.STRING: {
+ String s = ts.getString();
+ decompiler.addString(s);
+ return nf.createString(s);
+ }
+
+ case Token.DIV:
+ case Token.ASSIGN_DIV: {
+ // Got / or /= which should be treated as regexp in fact
+ ts.readRegExp(tt);
+ String flags = ts.regExpFlags;
+ ts.regExpFlags = null;
+ String re = ts.getString();
+ decompiler.addRegexp(re, flags);
+ int index = currentScriptOrFn.addRegexp(re, flags);
+ return nf.createRegExp(index);
+ }
+
+ case Token.NULL:
+ case Token.THIS:
+ case Token.FALSE:
+ case Token.TRUE:
+ decompiler.addToken(tt);
+ return nf.createLeaf(tt);
+
+ case Token.RESERVED:
+ reportError("msg.reserved.id");
+ break;
+
+ case Token.ERROR:
+ /* the scanner or one of its subroutines reported the error. */
+ break;
+
+ case Token.EOF:
+ reportError("msg.unexpected.eof");
+ break;
+
+ default:
+ reportError("msg.syntax");
+ break;
+ }
+ return null; // should never reach here
+ }
+
+ private void plainProperty(ObjArray elems, Object property)
+ throws IOException {
+ mustMatchToken(Token.COLON, "msg.no.colon.prop");
+
+ // OBJLIT is used as ':' in object literal for
+ // decompilation to solve spacing ambiguity.
+ decompiler.addToken(Token.OBJECTLIT);
+ elems.add(property);
+ elems.add(assignExpr(false));
+ }
+
+ private boolean getterSetterProperty(ObjArray elems, Object property,
+ boolean isGetter) throws IOException {
+ Node f = function(FunctionNode.FUNCTION_EXPRESSION);
+ if (f.getType() != Token.FUNCTION) {
+ reportError("msg.bad.prop");
+ return false;
+ }
+ int fnIndex = f.getExistingIntProp(Node.FUNCTION_PROP);
+ FunctionNode fn = currentScriptOrFn.getFunctionNode(fnIndex);
+ if (fn.getFunctionName().length() != 0) {
+ reportError("msg.bad.prop");
+ return false;
+ }
+ elems.add(property);
+ if (isGetter) {
+ elems.add(nf.createUnary(Token.GET, f));
+ } else {
+ elems.add(nf.createUnary(Token.SET, f));
+ }
+ return true;
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,420 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Roger Lawrence
+ * Mike McCabe
+ * Igor Bukanov
+ * Bob Jervis
+ * Milen Nankov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+/**
+ * This class implements the JavaScript scanner.
+ *
+ * It is based on the C source files jsscan.c and jsscan.h
+ * in the jsref package.
+ *
+ * @see org.mozilla.javascript.Parser
+ *
+ * @author Mike McCabe
+ * @author Brendan Eich
+ */
+
+public class Token
+{
+
+ // debug flags
+ public static final boolean printTrees = false;
+ static final boolean printICode = false;
+ static final boolean printNames = printTrees || printICode;
+
+ /**
+ * Token types. These values correspond to JSTokenType values in
+ * jsscan.c.
+ */
+
+ public final static int
+ // start enum
+ ERROR = -1, // well-known as the only code < EOF
+ EOF = 0, // end of file token - (not EOF_CHAR)
+ EOL = 1, // end of line
+
+ // Interpreter reuses the following as bytecodes
+ FIRST_BYTECODE_TOKEN = 2,
+
+ ENTERWITH = 2,
+ LEAVEWITH = 3,
+ RETURN = 4,
+ GOTO = 5,
+ IFEQ = 6,
+ IFNE = 7,
+ SETNAME = 8,
+ BITOR = 9,
+ BITXOR = 10,
+ BITAND = 11,
+ EQ = 12,
+ NE = 13,
+ LT = 14,
+ LE = 15,
+ GT = 16,
+ GE = 17,
+ LSH = 18,
+ RSH = 19,
+ URSH = 20,
+ ADD = 21,
+ SUB = 22,
+ MUL = 23,
+ DIV = 24,
+ MOD = 25,
+ NOT = 26,
+ BITNOT = 27,
+ POS = 28,
+ NEG = 29,
+ NEW = 30,
+ DELPROP = 31,
+ TYPEOF = 32,
+ GETPROP = 33,
+ SETPROP = 34,
+ GETELEM = 35,
+ SETELEM = 36,
+ CALL = 37,
+ NAME = 38,
+ NUMBER = 39,
+ STRING = 40,
+ NULL = 41,
+ THIS = 42,
+ FALSE = 43,
+ TRUE = 44,
+ SHEQ = 45, // shallow equality (===)
+ SHNE = 46, // shallow inequality (!==)
+ REGEXP = 47,
+ BINDNAME = 48,
+ THROW = 49,
+ RETHROW = 50, // rethrow caught execetion: catch (e if ) use it
+ IN = 51,
+ INSTANCEOF = 52,
+ LOCAL_LOAD = 53,
+ GETVAR = 54,
+ SETVAR = 55,
+ CATCH_SCOPE = 56,
+ ENUM_INIT_KEYS = 57,
+ ENUM_INIT_VALUES = 58,
+ ENUM_NEXT = 59,
+ ENUM_ID = 60,
+ THISFN = 61,
+ RETURN_RESULT = 62, // to return prevoisly stored return result
+ ARRAYLIT = 63, // array literal
+ OBJECTLIT = 64, // object literal
+ GET_REF = 65, // *reference
+ SET_REF = 66, // *reference = something
+ DEL_REF = 67, // delete reference
+ REF_CALL = 68, // f(args) = something or f(args)++
+ REF_SPECIAL = 69, // reference for special properties like __proto
+
+ // For XML support:
+ DEFAULTNAMESPACE = 70, // default xml namespace =
+ ESCXMLATTR = 71,
+ ESCXMLTEXT = 72,
+ REF_MEMBER = 73, // Reference for x.@y, x..y etc.
+ REF_NS_MEMBER = 74, // Reference for x.ns::y, x..ns::y etc.
+ REF_NAME = 75, // Reference for @y, @[y] etc.
+ REF_NS_NAME = 76; // Reference for ns::y, @ns::y@[y] etc.
+
+ // End of interpreter bytecodes
+ public final static int
+ LAST_BYTECODE_TOKEN = REF_NS_NAME,
+
+ TRY = 77,
+ SEMI = 78, // semicolon
+ LB = 79, // left and right brackets
+ RB = 80,
+ LC = 81, // left and right curlies (braces)
+ RC = 82,
+ LP = 83, // left and right parentheses
+ RP = 84,
+ COMMA = 85, // comma operator
+
+ ASSIGN = 86, // simple assignment (=)
+ ASSIGN_BITOR = 87, // |=
+ ASSIGN_BITXOR = 88, // ^=
+ ASSIGN_BITAND = 89, // |=
+ ASSIGN_LSH = 90, // <<=
+ ASSIGN_RSH = 91, // >>=
+ ASSIGN_URSH = 92, // >>>=
+ ASSIGN_ADD = 93, // +=
+ ASSIGN_SUB = 94, // -=
+ ASSIGN_MUL = 95, // *=
+ ASSIGN_DIV = 96, // /=
+ ASSIGN_MOD = 97; // %=
+
+ public final static int
+ FIRST_ASSIGN = ASSIGN,
+ LAST_ASSIGN = ASSIGN_MOD,
+
+ HOOK = 98, // conditional (?:)
+ COLON = 99,
+ OR = 100, // logical or (||)
+ AND = 101, // logical and (&&)
+ INC = 102, // increment/decrement (++ --)
+ DEC = 103,
+ DOT = 104, // member operator (.)
+ FUNCTION = 105, // function keyword
+ EXPORT = 106, // export keyword
+ IMPORT = 107, // import keyword
+ IF = 108, // if keyword
+ ELSE = 109, // else keyword
+ SWITCH = 110, // switch keyword
+ CASE = 111, // case keyword
+ DEFAULT = 112, // default keyword
+ WHILE = 113, // while keyword
+ DO = 114, // do keyword
+ FOR = 115, // for keyword
+ BREAK = 116, // break keyword
+ CONTINUE = 117, // continue keyword
+ VAR = 118, // var keyword
+ WITH = 119, // with keyword
+ CATCH = 120, // catch keyword
+ FINALLY = 121, // finally keyword
+ VOID = 122, // void keyword
+ RESERVED = 123, // reserved keywords
+
+ EMPTY = 124,
+
+ /* types used for the parse tree - these never get returned
+ * by the scanner.
+ */
+
+ BLOCK = 125, // statement block
+ LABEL = 126, // label
+ TARGET = 127,
+ LOOP = 128,
+ EXPR_VOID = 129, // expression statement in functions
+ EXPR_RESULT = 130, // expression statement in scripts
+ JSR = 131,
+ SCRIPT = 132, // top-level node for entire script
+ TYPEOFNAME = 133, // for typeof(simple-name)
+ USE_STACK = 134,
+ SETPROP_OP = 135, // x.y op= something
+ SETELEM_OP = 136, // x[y] op= something
+ LOCAL_BLOCK = 137,
+ SET_REF_OP = 138, // *reference op= something
+
+ // For XML support:
+ DOTDOT = 139, // member operator (..)
+ COLONCOLON = 140, // namespace::name
+ XML = 141, // XML type
+ DOTQUERY = 142, // .() -- e.g., x.emps.emp.(name == "terry")
+ XMLATTR = 143, // @
+ XMLEND = 144,
+
+ // Optimizer-only-tokens
+ TO_OBJECT = 145,
+ TO_DOUBLE = 146,
+
+ GET = 147, // JS 1.5 get pseudo keyword
+ SET = 148, // JS 1.5 set pseudo keyword
+ CONST = 149,
+ SETCONST = 150,
+ SETCONSTVAR = 151,
+
+ IECC = 152, // Internet Explorer conditional comment
+
+ LAST_TOKEN = 153;
+
+ public static String name(int token)
+ {
+ if (!printNames) {
+ return String.valueOf(token);
+ }
+ switch (token) {
+ case ERROR: return "ERROR";
+ case EOF: return "EOF";
+ case EOL: return "EOL";
+ case ENTERWITH: return "ENTERWITH";
+ case LEAVEWITH: return "LEAVEWITH";
+ case RETURN: return "RETURN";
+ case GOTO: return "GOTO";
+ case IFEQ: return "IFEQ";
+ case IFNE: return "IFNE";
+ case SETNAME: return "SETNAME";
+ case BITOR: return "BITOR";
+ case BITXOR: return "BITXOR";
+ case BITAND: return "BITAND";
+ case EQ: return "EQ";
+ case NE: return "NE";
+ case LT: return "LT";
+ case LE: return "LE";
+ case GT: return "GT";
+ case GE: return "GE";
+ case LSH: return "LSH";
+ case RSH: return "RSH";
+ case URSH: return "URSH";
+ case ADD: return "ADD";
+ case SUB: return "SUB";
+ case MUL: return "MUL";
+ case DIV: return "DIV";
+ case MOD: return "MOD";
+ case NOT: return "NOT";
+ case BITNOT: return "BITNOT";
+ case POS: return "POS";
+ case NEG: return "NEG";
+ case NEW: return "NEW";
+ case DELPROP: return "DELPROP";
+ case TYPEOF: return "TYPEOF";
+ case GETPROP: return "GETPROP";
+ case SETPROP: return "SETPROP";
+ case GETELEM: return "GETELEM";
+ case SETELEM: return "SETELEM";
+ case CALL: return "CALL";
+ case NAME: return "NAME";
+ case NUMBER: return "NUMBER";
+ case STRING: return "STRING";
+ case NULL: return "NULL";
+ case THIS: return "THIS";
+ case FALSE: return "FALSE";
+ case TRUE: return "TRUE";
+ case SHEQ: return "SHEQ";
+ case SHNE: return "SHNE";
+ case REGEXP: return "OBJECT";
+ case BINDNAME: return "BINDNAME";
+ case THROW: return "THROW";
+ case RETHROW: return "RETHROW";
+ case IN: return "IN";
+ case INSTANCEOF: return "INSTANCEOF";
+ case LOCAL_LOAD: return "LOCAL_LOAD";
+ case GETVAR: return "GETVAR";
+ case SETVAR: return "SETVAR";
+ case CATCH_SCOPE: return "CATCH_SCOPE";
+ case ENUM_INIT_KEYS: return "ENUM_INIT_KEYS";
+ case ENUM_INIT_VALUES: return "ENUM_INIT_VALUES";
+ case ENUM_NEXT: return "ENUM_NEXT";
+ case ENUM_ID: return "ENUM_ID";
+ case THISFN: return "THISFN";
+ case RETURN_RESULT: return "RETURN_RESULT";
+ case ARRAYLIT: return "ARRAYLIT";
+ case OBJECTLIT: return "OBJECTLIT";
+ case GET_REF: return "GET_REF";
+ case SET_REF: return "SET_REF";
+ case DEL_REF: return "DEL_REF";
+ case REF_CALL: return "REF_CALL";
+ case REF_SPECIAL: return "REF_SPECIAL";
+ case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
+ case ESCXMLTEXT: return "ESCXMLTEXT";
+ case ESCXMLATTR: return "ESCXMLATTR";
+ case REF_MEMBER: return "REF_MEMBER";
+ case REF_NS_MEMBER: return "REF_NS_MEMBER";
+ case REF_NAME: return "REF_NAME";
+ case REF_NS_NAME: return "REF_NS_NAME";
+ case TRY: return "TRY";
+ case SEMI: return "SEMI";
+ case LB: return "LB";
+ case RB: return "RB";
+ case LC: return "LC";
+ case RC: return "RC";
+ case LP: return "LP";
+ case RP: return "RP";
+ case COMMA: return "COMMA";
+ case ASSIGN: return "ASSIGN";
+ case ASSIGN_BITOR: return "ASSIGN_BITOR";
+ case ASSIGN_BITXOR: return "ASSIGN_BITXOR";
+ case ASSIGN_BITAND: return "ASSIGN_BITAND";
+ case ASSIGN_LSH: return "ASSIGN_LSH";
+ case ASSIGN_RSH: return "ASSIGN_RSH";
+ case ASSIGN_URSH: return "ASSIGN_URSH";
+ case ASSIGN_ADD: return "ASSIGN_ADD";
+ case ASSIGN_SUB: return "ASSIGN_SUB";
+ case ASSIGN_MUL: return "ASSIGN_MUL";
+ case ASSIGN_DIV: return "ASSIGN_DIV";
+ case ASSIGN_MOD: return "ASSIGN_MOD";
+ case HOOK: return "HOOK";
+ case COLON: return "COLON";
+ case OR: return "OR";
+ case AND: return "AND";
+ case INC: return "INC";
+ case DEC: return "DEC";
+ case DOT: return "DOT";
+ case FUNCTION: return "FUNCTION";
+ case EXPORT: return "EXPORT";
+ case IMPORT: return "IMPORT";
+ case IF: return "IF";
+ case ELSE: return "ELSE";
+ case SWITCH: return "SWITCH";
+ case CASE: return "CASE";
+ case DEFAULT: return "DEFAULT";
+ case WHILE: return "WHILE";
+ case DO: return "DO";
+ case FOR: return "FOR";
+ case BREAK: return "BREAK";
+ case CONTINUE: return "CONTINUE";
+ case VAR: return "VAR";
+ case WITH: return "WITH";
+ case CATCH: return "CATCH";
+ case FINALLY: return "FINALLY";
+ case RESERVED: return "RESERVED";
+ case EMPTY: return "EMPTY";
+ case BLOCK: return "BLOCK";
+ case LABEL: return "LABEL";
+ case TARGET: return "TARGET";
+ case LOOP: return "LOOP";
+ case EXPR_VOID: return "EXPR_VOID";
+ case EXPR_RESULT: return "EXPR_RESULT";
+ case JSR: return "JSR";
+ case SCRIPT: return "SCRIPT";
+ case TYPEOFNAME: return "TYPEOFNAME";
+ case USE_STACK: return "USE_STACK";
+ case SETPROP_OP: return "SETPROP_OP";
+ case SETELEM_OP: return "SETELEM_OP";
+ case LOCAL_BLOCK: return "LOCAL_BLOCK";
+ case SET_REF_OP: return "SET_REF_OP";
+ case DOTDOT: return "DOTDOT";
+ case COLONCOLON: return "COLONCOLON";
+ case XML: return "XML";
+ case DOTQUERY: return "DOTQUERY";
+ case XMLATTR: return "XMLATTR";
+ case XMLEND: return "XMLEND";
+ case TO_OBJECT: return "TO_OBJECT";
+ case TO_DOUBLE: return "TO_DOUBLE";
+ case GET: return "GET";
+ case SET: return "SET";
+ case CONST: return "CONST";
+ case SETCONST: return "SETCONST";
+ }
+
+ // Token without name
+ throw new IllegalStateException(String.valueOf(token));
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,1359 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Roger Lawrence
+ * Mike McCabe
+ * Igor Bukanov
+ * Ethan Hugg
+ * Bob Jervis
+ * Terry Lucas
+ * Milen Nankov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+import java.io.*;
+
+/**
+ * This class implements the JavaScript scanner.
+ *
+ * It is based on the C source files jsscan.c and jsscan.h
+ * in the jsref package.
+ *
+ * @see org.mozilla.javascript.Parser
+ *
+ * @author Mike McCabe
+ * @author Brendan Eich
+ */
+
+class TokenStream
+{
+ /*
+ * For chars - because we need something out-of-range
+ * to check. (And checking EOF by exception is annoying.)
+ * Note distinction from EOF token type!
+ */
+ private final static int
+ EOF_CHAR = -1;
+
+ TokenStream(Parser parser, Reader sourceReader, String sourceString,
+ int lineno)
+ {
+ this.parser = parser;
+ this.lineno = lineno;
+ if (sourceReader != null) {
+ if (sourceString != null) Kit.codeBug();
+ this.sourceReader = sourceReader;
+ this.sourceBuffer = new char[512];
+ this.sourceEnd = 0;
+ } else {
+ if (sourceString == null) Kit.codeBug();
+ this.sourceString = sourceString;
+ this.sourceEnd = sourceString.length();
+ }
+ this.sourceCursor = 0;
+ }
+
+ /* This function uses the cached op, string and number fields in
+ * TokenStream; if getToken has been called since the passed token
+ * was scanned, the op or string printed may be incorrect.
+ */
+ String tokenToString(int token)
+ {
+ if (Token.printTrees) {
+ String name = Token.name(token);
+
+ switch (token) {
+ case Token.STRING:
+ case Token.REGEXP:
+ case Token.NAME:
+ return name + " `" + this.string + "'";
+
+ case Token.NUMBER:
+ return "NUMBER " + this.number;
+ }
+
+ return name;
+ }
+ return "";
+ }
+
+ static boolean isKeyword(String s)
+ {
+ return Token.EOF != stringToKeyword(s);
+ }
+
+ private static int stringToKeyword(String name)
+ {
+// #string_id_map#
+// The following assumes that Token.EOF == 0
+ final int
+ Id_break = Token.BREAK,
+ Id_case = Token.CASE,
+ Id_continue = Token.CONTINUE,
+ Id_default = Token.DEFAULT,
+ Id_delete = Token.DELPROP,
+ Id_do = Token.DO,
+ Id_else = Token.ELSE,
+ Id_export = Token.EXPORT,
+ Id_false = Token.FALSE,
+ Id_for = Token.FOR,
+ Id_function = Token.FUNCTION,
+ Id_if = Token.IF,
+ Id_in = Token.IN,
+ Id_new = Token.NEW,
+ Id_null = Token.NULL,
+ Id_return = Token.RETURN,
+ Id_switch = Token.SWITCH,
+ Id_this = Token.THIS,
+ Id_true = Token.TRUE,
+ Id_typeof = Token.TYPEOF,
+ Id_var = Token.VAR,
+ Id_void = Token.VOID,
+ Id_while = Token.WHILE,
+ Id_with = Token.WITH,
+
+ // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c
+ Id_abstract = Token.RESERVED,
+ Id_boolean = Token.RESERVED,
+ Id_byte = Token.RESERVED,
+ Id_catch = Token.CATCH,
+ Id_char = Token.RESERVED,
+ Id_class = Token.RESERVED,
+ Id_const = Token.CONST,
+ Id_debugger = Token.RESERVED,
+ Id_double = Token.RESERVED,
+ Id_enum = Token.RESERVED,
+ Id_extends = Token.RESERVED,
+ Id_final = Token.RESERVED,
+ Id_finally = Token.FINALLY,
+ Id_float = Token.RESERVED,
+ Id_goto = Token.RESERVED,
+ Id_implements = Token.RESERVED,
+ Id_import = Token.IMPORT,
+ Id_instanceof = Token.INSTANCEOF,
+ Id_int = Token.RESERVED,
+ Id_interface = Token.RESERVED,
+ Id_long = Token.RESERVED,
+ Id_native = Token.RESERVED,
+ Id_package = Token.RESERVED,
+ Id_private = Token.RESERVED,
+ Id_protected = Token.RESERVED,
+ Id_public = Token.RESERVED,
+ Id_short = Token.RESERVED,
+ Id_static = Token.RESERVED,
+ Id_super = Token.RESERVED,
+ Id_synchronized = Token.RESERVED,
+ Id_throw = Token.THROW,
+ Id_throws = Token.RESERVED,
+ Id_transient = Token.RESERVED,
+ Id_try = Token.TRY,
+ Id_volatile = Token.RESERVED;
+
+ int id;
+ String s = name;
+// #generated# Last update: 2001-06-01 17:45:01 CEST
+ L0: { id = 0; String X = null; int c;
+ L: switch (s.length()) {
+ case 2: c=s.charAt(1);
+ if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} }
+ else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} }
+ else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} }
+ break L;
+ case 3: switch (s.charAt(0)) {
+ case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L;
+ case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L;
+ case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L;
+ case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L;
+ case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L;
+ } break L;
+ case 4: switch (s.charAt(0)) {
+ case 'b': X="byte";id=Id_byte; break L;
+ case 'c': c=s.charAt(3);
+ if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} }
+ else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} }
+ break L;
+ case 'e': c=s.charAt(3);
+ if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} }
+ else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} }
+ break L;
+ case 'g': X="goto";id=Id_goto; break L;
+ case 'l': X="long";id=Id_long; break L;
+ case 'n': X="null";id=Id_null; break L;
+ case 't': c=s.charAt(3);
+ if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} }
+ else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} }
+ break L;
+ case 'v': X="void";id=Id_void; break L;
+ case 'w': X="with";id=Id_with; break L;
+ } break L;
+ case 5: switch (s.charAt(2)) {
+ case 'a': X="class";id=Id_class; break L;
+ case 'e': X="break";id=Id_break; break L;
+ case 'i': X="while";id=Id_while; break L;
+ case 'l': X="false";id=Id_false; break L;
+ case 'n': c=s.charAt(0);
+ if (c=='c') { X="const";id=Id_const; }
+ else if (c=='f') { X="final";id=Id_final; }
+ break L;
+ case 'o': c=s.charAt(0);
+ if (c=='f') { X="float";id=Id_float; }
+ else if (c=='s') { X="short";id=Id_short; }
+ break L;
+ case 'p': X="super";id=Id_super; break L;
+ case 'r': X="throw";id=Id_throw; break L;
+ case 't': X="catch";id=Id_catch; break L;
+ } break L;
+ case 6: switch (s.charAt(1)) {
+ case 'a': X="native";id=Id_native; break L;
+ case 'e': c=s.charAt(0);
+ if (c=='d') { X="delete";id=Id_delete; }
+ else if (c=='r') { X="return";id=Id_return; }
+ break L;
+ case 'h': X="throws";id=Id_throws; break L;
+ case 'm': X="import";id=Id_import; break L;
+ case 'o': X="double";id=Id_double; break L;
+ case 't': X="static";id=Id_static; break L;
+ case 'u': X="public";id=Id_public; break L;
+ case 'w': X="switch";id=Id_switch; break L;
+ case 'x': X="export";id=Id_export; break L;
+ case 'y': X="typeof";id=Id_typeof; break L;
+ } break L;
+ case 7: switch (s.charAt(1)) {
+ case 'a': X="package";id=Id_package; break L;
+ case 'e': X="default";id=Id_default; break L;
+ case 'i': X="finally";id=Id_finally; break L;
+ case 'o': X="boolean";id=Id_boolean; break L;
+ case 'r': X="private";id=Id_private; break L;
+ case 'x': X="extends";id=Id_extends; break L;
+ } break L;
+ case 8: switch (s.charAt(0)) {
+ case 'a': X="abstract";id=Id_abstract; break L;
+ case 'c': X="continue";id=Id_continue; break L;
+ case 'd': X="debugger";id=Id_debugger; break L;
+ case 'f': X="function";id=Id_function; break L;
+ case 'v': X="volatile";id=Id_volatile; break L;
+ } break L;
+ case 9: c=s.charAt(0);
+ if (c=='i') { X="interface";id=Id_interface; }
+ else if (c=='p') { X="protected";id=Id_protected; }
+ else if (c=='t') { X="transient";id=Id_transient; }
+ break L;
+ case 10: c=s.charAt(1);
+ if (c=='m') { X="implements";id=Id_implements; }
+ else if (c=='n') { X="instanceof";id=Id_instanceof; }
+ break L;
+ case 12: X="synchronized";id=Id_synchronized; break L;
+ }
+ if (X!=null && X!=s && !X.equals(s)) id = 0;
+ }
+// #/generated#
+// #/string_id_map#
+ if (id == 0) { return Token.EOF; }
+ return id & 0xff;
+ }
+
+ final int getLineno() { return lineno; }
+
+ final String getString() { return string; }
+
+ final double getNumber() { return number; }
+
+ final boolean eof() { return hitEOF; }
+
+ final int getToken() throws IOException
+ {
+ int c;
+
+ retry:
+ for (;;) {
+ // Eat whitespace, possibly sensitive to newlines.
+ for (;;) {
+ c = getChar();
+ if (c == EOF_CHAR) {
+ return Token.EOF;
+ } else if (c == '\n') {
+ dirtyLine = false;
+ return Token.EOL;
+ } else if (!isJSSpace(c)) {
+ if (c != '-') {
+ dirtyLine = true;
+ }
+ break;
+ }
+ }
+
+ if (c == '@') return Token.XMLATTR;
+
+ // identifier/keyword/instanceof?
+ // watch out for starting with a <backslash>
+ boolean identifierStart;
+ boolean isUnicodeEscapeStart = false;
+ if (c == '\\') {
+ c = getChar();
+ if (c == 'u') {
+ identifierStart = true;
+ isUnicodeEscapeStart = true;
+ stringBufferTop = 0;
+ } else {
+ identifierStart = false;
+ ungetChar(c);
+ c = '\\';
+ }
+ } else {
+ identifierStart = Character.isJavaIdentifierStart((char)c);
+ if (identifierStart) {
+ stringBufferTop = 0;
+ addToString(c);
+ }
+ }
+
+ if (identifierStart) {
+ boolean containsEscape = isUnicodeEscapeStart;
+ for (;;) {
+ if (isUnicodeEscapeStart) {
+ // strictly speaking we should probably push-back
+ // all the bad characters if the <backslash>uXXXX
+ // sequence is malformed. But since there isn't a
+ // correct context(is there?) for a bad Unicode
+ // escape sequence in an identifier, we can report
+ // an error here.
+ int escapeVal = 0;
+ for (int i = 0; i != 4; ++i) {
+ c = getChar();
+ escapeVal = Kit.xDigitToInt(c, escapeVal);
+ // Next check takes care about c < 0 and bad escape
+ if (escapeVal < 0) { break; }
+ }
+ if (escapeVal < 0) {
+ parser.addError("msg.invalid.escape");
+ return Token.ERROR;
+ }
+ addToString(escapeVal);
+ isUnicodeEscapeStart = false;
+ } else {
+ c = getChar();
+ if (c == '\\') {
+ c = getChar();
+ if (c == 'u') {
+ isUnicodeEscapeStart = true;
+ containsEscape = true;
+ } else {
+ parser.addError("msg.illegal.character");
+ return Token.ERROR;
+ }
+ } else {
+ if (c == EOF_CHAR
+ || !Character.isJavaIdentifierPart((char)c))
+ {
+ break;
+ }
+ addToString(c);
+ }
+ }
+ }
+ ungetChar(c);
+
+ String str = getStringFromBuffer();
+ if (!containsEscape) {
+ // OPT we shouldn't have to make a string (object!) to
+ // check if it's a keyword.
+
+ // Return the corresponding token if it's a keyword
+ int result = stringToKeyword(str);
+ if (result != Token.EOF) {
+ if (result != Token.RESERVED) {
+ return result;
+ } else if (!parser.compilerEnv.
+ isReservedKeywordAsIdentifier())
+ {
+ return result;
+ } else {
+ // If implementation permits to use future reserved
+ // keywords in violation with the EcmaScript,
+ // treat it as name but issue warning
+ parser.addWarning("msg.reserved.keyword", str);
+ }
+ }
+ }
+ this.string = (String)allStrings.intern(str);
+ return Token.NAME;
+ }
+
+ // is it a number?
+ if (isDigit(c) || (c == '.' && isDigit(peekChar()))) {
+
+ stringBufferTop = 0;
+ int base = 10;
+
+ if (c == '0') {
+ c = getChar();
+ if (c == 'x' || c == 'X') {
+ base = 16;
+ c = getChar();
+ } else if (isDigit(c)) {
+ base = 8;
+ } else {
+ addToString('0');
+ }
+ }
+
+ if (base == 16) {
+ while (0 <= Kit.xDigitToInt(c, 0)) {
+ addToString(c);
+ c = getChar();
+ }
+ } else {
+ while ('0' <= c && c <= '9') {
+ /*
+ * We permit 08 and 09 as decimal numbers, which
+ * makes our behavior a superset of the ECMA
+ * numeric grammar. We might not always be so
+ * permissive, so we warn about it.
+ */
+ if (base == 8 && c >= '8') {
+ parser.addWarning("msg.bad.octal.literal",
+ c == '8' ? "8" : "9");
+ base = 10;
+ }
+ addToString(c);
+ c = getChar();
+ }
+ }
+
+ boolean isInteger = true;
+
+ if (base == 10 && (c == '.' || c == 'e' || c == 'E')) {
+ isInteger = false;
+ if (c == '.') {
+ do {
+ addToString(c);
+ c = getChar();
+ } while (isDigit(c));
+ }
+ if (c == 'e' || c == 'E') {
+ addToString(c);
+ c = getChar();
+ if (c == '+' || c == '-') {
+ addToString(c);
+ c = getChar();
+ }
+ if (!isDigit(c)) {
+ parser.addError("msg.missing.exponent");
+ return Token.ERROR;
+ }
+ do {
+ addToString(c);
+ c = getChar();
+ } while (isDigit(c));
+ }
+ }
+ ungetChar(c);
+ String numString = getStringFromBuffer();
+
+ double dval;
+ if (base == 10 && !isInteger) {
+ try {
+ // Use Java conversion to number from string...
+ dval = Double.valueOf(numString).doubleValue();
+ }
+ catch (NumberFormatException ex) {
+ parser.addError("msg.caught.nfe");
+ return Token.ERROR;
+ }
+ } else {
+ dval = ScriptRuntime.stringToNumber(numString, 0, base);
+ }
+
+ this.number = dval;
+ return Token.NUMBER;
+ }
+
+ // is it a string?
+ if (c == '"' || c == '\'') {
+ // We attempt to accumulate a string the fast way, by
+ // building it directly out of the reader. But if there
+ // are any escaped characters in the string, we revert to
+ // building it out of a StringBuffer.
+
+ int quoteChar = c;
+ stringBufferTop = 0;
+
+ c = getChar();
+ while (c != quoteChar) {
+ if (c == '\n' || c == EOF_CHAR) {
+ ungetChar(c);
+ parser.addError("msg.unterminated.string.lit");
+ return Token.ERROR;
+ }
+
+ if (c == '\\') {
+ // We've hit an escaped character
+
+ c = getChar();
+
+ switch (c) {
+
+ case '\\': // backslash
+ case 'b': // backspace
+ case 'f': // form feed
+ case 'n': // line feed
+ case 'r': // carriage return
+ case 't': // horizontal tab
+ case 'v': // vertical tab
+ case 'd': // octal sequence
+ case 'u': // unicode sequence
+ case 'x': // hexadecimal sequence
+
+ // Only keep the '\' character for those
+ // characters that need to be escaped...
+ // Don't escape quoting characters...
+ addToString('\\');
+ break;
+
+ case '\n':
+ // Remove line terminator after escape
+ c = getChar();
+ break;
+ }
+ }
+
+ addToString(c);
+ c = getChar();
+ }
+
+ String str = getStringFromBuffer();
+ this.string = (String)allStrings.intern(str);
+ return Token.STRING;
+ }
+
+ switch (c) {
+ case ';': return Token.SEMI;
+ case '[': return Token.LB;
+ case ']': return Token.RB;
+ case '{': return Token.LC;
+ case '}': return Token.RC;
+ case '(': return Token.LP;
+ case ')': return Token.RP;
+ case ',': return Token.COMMA;
+ case '?': return Token.HOOK;
+ case ':':
+ if (matchChar(':')) {
+ return Token.COLONCOLON;
+ } else {
+ return Token.COLON;
+ }
+ case '.':
+ if (matchChar('.')) {
+ return Token.DOTDOT;
+ } else if (matchChar('(')) {
+ return Token.DOTQUERY;
+ } else {
+ return Token.DOT;
+ }
+
+ case '|':
+ if (matchChar('|')) {
+ return Token.OR;
+ } else if (matchChar('=')) {
+ return Token.ASSIGN_BITOR;
+ } else {
+ return Token.BITOR;
+ }
+
+ case '^':
+ if (matchChar('=')) {
+ return Token.ASSIGN_BITXOR;
+ } else {
+ return Token.BITXOR;
+ }
+
+ case '&':
+ if (matchChar('&')) {
+ return Token.AND;
+ } else if (matchChar('=')) {
+ return Token.ASSIGN_BITAND;
+ } else {
+ return Token.BITAND;
+ }
+
+ case '=':
+ if (matchChar('=')) {
+ if (matchChar('='))
+ return Token.SHEQ;
+ else
+ return Token.EQ;
+ } else {
+ return Token.ASSIGN;
+ }
+
+ case '!':
+ if (matchChar('=')) {
+ if (matchChar('='))
+ return Token.SHNE;
+ else
+ return Token.NE;
+ } else {
+ return Token.NOT;
+ }
+
+ case '<':
+ /* NB:treat HTML begin-comment as comment-till-eol */
+ if (matchChar('!')) {
+ if (matchChar('-')) {
+ if (matchChar('-')) {
+ skipLine();
+ continue retry;
+ }
+ ungetChar('-');
+ }
+ ungetChar('!');
+ }
+ if (matchChar('<')) {
+ if (matchChar('=')) {
+ return Token.ASSIGN_LSH;
+ } else {
+ return Token.LSH;
+ }
+ } else {
+ if (matchChar('=')) {
+ return Token.LE;
+ } else {
+ return Token.LT;
+ }
+ }
+
+ case '>':
+ if (matchChar('>')) {
+ if (matchChar('>')) {
+ if (matchChar('=')) {
+ return Token.ASSIGN_URSH;
+ } else {
+ return Token.URSH;
+ }
+ } else {
+ if (matchChar('=')) {
+ return Token.ASSIGN_RSH;
+ } else {
+ return Token.RSH;
+ }
+ }
+ } else {
+ if (matchChar('=')) {
+ return Token.GE;
+ } else {
+ return Token.GT;
+ }
+ }
+
+ case '*':
+ if (matchChar('=')) {
+ return Token.ASSIGN_MUL;
+ } else {
+ return Token.MUL;
+ }
+
+ case '/':
+ // is it a // comment?
+ if (matchChar('/')) {
+ skipLine();
+ continue retry;
+ }
+ if (matchChar('*')) {
+ boolean lookForSlash = false;
+ StringBuffer sb = new StringBuffer();
+ for (;;) {
+ c = getChar();
+ if (c == EOF_CHAR) {
+ parser.addError("msg.unterminated.comment");
+ return Token.ERROR;
+ }
+ sb.append((char) c);
+ if (c == '*') {
+ lookForSlash = true;
+ } else if (c == '/') {
+ if (lookForSlash) {
+ sb.delete(sb.length()-2, sb.length());
+ String s = sb.toString();
+ if (s.startsWith("@cc_on") ||
+ s.startsWith("@if") ||
+ s.startsWith("@elif") ||
+ s.startsWith("@else") ||
+ s.startsWith("@end")) {
+ this.string = s;
+ return Token.IECC;
+ } else {
+ continue retry;
+ }
+ }
+ } else {
+ lookForSlash = false;
+ }
+ }
+ }
+
+ if (matchChar('=')) {
+ return Token.ASSIGN_DIV;
+ } else {
+ return Token.DIV;
+ }
+
+ case '%':
+ if (matchChar('=')) {
+ return Token.ASSIGN_MOD;
+ } else {
+ return Token.MOD;
+ }
+
+ case '~':
+ return Token.BITNOT;
+
+ case '+':
+ if (matchChar('=')) {
+ return Token.ASSIGN_ADD;
+ } else if (matchChar('+')) {
+ return Token.INC;
+ } else {
+ return Token.ADD;
+ }
+
+ case '-':
+ if (matchChar('=')) {
+ c = Token.ASSIGN_SUB;
+ } else if (matchChar('-')) {
+ if (!dirtyLine) {
+ // treat HTML end-comment after possible whitespace
+ // after line start as comment-utill-eol
+ if (matchChar('>')) {
+ skipLine();
+ continue retry;
+ }
+ }
+ c = Token.DEC;
+ } else {
+ c = Token.SUB;
+ }
+ dirtyLine = true;
+ return c;
+
+ default:
+ parser.addError("msg.illegal.character");
+ return Token.ERROR;
+ }
+ }
+ }
+
+ private static boolean isAlpha(int c)
+ {
+ // Use 'Z' < 'a'
+ if (c <= 'Z') {
+ return 'A' <= c;
+ } else {
+ return 'a' <= c && c <= 'z';
+ }
+ }
+
+ static boolean isDigit(int c)
+ {
+ return '0' <= c && c <= '9';
+ }
+
+ /* As defined in ECMA. jsscan.c uses C isspace() (which allows
+ * \v, I think.) note that code in getChar() implicitly accepts
+ * '\r' == \u000D as well.
+ */
+ static boolean isJSSpace(int c)
+ {
+ if (c <= 127) {
+ return c == 0x20 || c == 0x9 || c == 0xC || c == 0xB;
+ } else {
+ return c == 0xA0
+ || Character.getType((char)c) == Character.SPACE_SEPARATOR;
+ }
+ }
+
+ private static boolean isJSFormatChar(int c)
+ {
+ return c > 127 && Character.getType((char)c) == Character.FORMAT;
+ }
+
+ /**
+ * Parser calls the method when it gets / or /= in literal context.
+ */
+ void readRegExp(int startToken)
+ throws IOException
+ {
+ stringBufferTop = 0;
+ if (startToken == Token.ASSIGN_DIV) {
+ // Miss-scanned /=
+ addToString('=');
+ } else {
+ if (startToken != Token.DIV) Kit.codeBug();
+ }
+
+ int c;
+ while ((c = getChar()) != '/') {
+ if (c == '\n' || c == EOF_CHAR) {
+ ungetChar(c);
+ throw parser.reportError("msg.unterminated.re.lit");
+ }
+ if (c == '\\') {
+ addToString(c);
+ c = getChar();
+ }
+
+ addToString(c);
+ }
+ int reEnd = stringBufferTop;
+
+ while (true) {
+ if (matchChar('g'))
+ addToString('g');
+ else if (matchChar('i'))
+ addToString('i');
+ else if (matchChar('m'))
+ addToString('m');
+ else
+ break;
+ }
+
+ if (isAlpha(peekChar())) {
+ throw parser.reportError("msg.invalid.re.flag");
+ }
+
+ this.string = new String(stringBuffer, 0, reEnd);
+ this.regExpFlags = new String(stringBuffer, reEnd,
+ stringBufferTop - reEnd);
+ }
+
+ boolean isXMLAttribute()
+ {
+ return xmlIsAttribute;
+ }
+
+ int getFirstXMLToken() throws IOException
+ {
+ xmlOpenTagsCount = 0;
+ xmlIsAttribute = false;
+ xmlIsTagContent = false;
+ ungetChar('<');
+ return getNextXMLToken();
+ }
+
+ int getNextXMLToken() throws IOException
+ {
+ stringBufferTop = 0; // remember the XML
+
+ for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+ if (xmlIsTagContent) {
+ switch (c) {
+ case '>':
+ addToString(c);
+ xmlIsTagContent = false;
+ xmlIsAttribute = false;
+ break;
+ case '/':
+ addToString(c);
+ if (peekChar() == '>') {
+ c = getChar();
+ addToString(c);
+ xmlIsTagContent = false;
+ xmlOpenTagsCount--;
+ }
+ break;
+ case '{':
+ ungetChar(c);
+ this.string = getStringFromBuffer();
+ return Token.XML;
+ case '\'':
+ case '"':
+ addToString(c);
+ if (!readQuotedString(c)) return Token.ERROR;
+ break;
+ case '=':
+ addToString(c);
+ xmlIsAttribute = true;
+ break;
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ addToString(c);
+ break;
+ default:
+ addToString(c);
+ xmlIsAttribute = false;
+ break;
+ }
+
+ if (!xmlIsTagContent && xmlOpenTagsCount == 0) {
+ this.string = getStringFromBuffer();
+ return Token.XMLEND;
+ }
+ } else {
+ switch (c) {
+ case '<':
+ addToString(c);
+ c = peekChar();
+ switch (c) {
+ case '!':
+ c = getChar(); // Skip !
+ addToString(c);
+ c = peekChar();
+ switch (c) {
+ case '-':
+ c = getChar(); // Skip -
+ addToString(c);
+ c = getChar();
+ if (c == '-') {
+ addToString(c);
+ if(!readXmlComment()) return Token.ERROR;
+ } else {
+ // throw away the string in progress
+ stringBufferTop = 0;
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return Token.ERROR;
+ }
+ break;
+ case '[':
+ c = getChar(); // Skip [
+ addToString(c);
+ if (getChar() == 'C' &&
+ getChar() == 'D' &&
+ getChar() == 'A' &&
+ getChar() == 'T' &&
+ getChar() == 'A' &&
+ getChar() == '[')
+ {
+ addToString('C');
+ addToString('D');
+ addToString('A');
+ addToString('T');
+ addToString('A');
+ addToString('[');
+ if (!readCDATA()) return Token.ERROR;
+
+ } else {
+ // throw away the string in progress
+ stringBufferTop = 0;
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return Token.ERROR;
+ }
+ break;
+ default:
+ if(!readEntity()) return Token.ERROR;
+ break;
+ }
+ break;
+ case '?':
+ c = getChar(); // Skip ?
+ addToString(c);
+ if (!readPI()) return Token.ERROR;
+ break;
+ case '/':
+ // End tag
+ c = getChar(); // Skip /
+ addToString(c);
+ if (xmlOpenTagsCount == 0) {
+ // throw away the string in progress
+ stringBufferTop = 0;
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return Token.ERROR;
+ }
+ xmlIsTagContent = true;
+ xmlOpenTagsCount--;
+ break;
+ default:
+ // Start tag
+ xmlIsTagContent = true;
+ xmlOpenTagsCount++;
+ break;
+ }
+ break;
+ case '{':
+ ungetChar(c);
+ this.string = getStringFromBuffer();
+ return Token.XML;
+ default:
+ addToString(c);
+ break;
+ }
+ }
+ }
+
+ stringBufferTop = 0; // throw away the string in progress
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return Token.ERROR;
+ }
+
+ /**
+ *
+ */
+ private boolean readQuotedString(int quote) throws IOException
+ {
+ for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+ addToString(c);
+ if (c == quote) return true;
+ }
+
+ stringBufferTop = 0; // throw away the string in progress
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return false;
+ }
+
+ /**
+ *
+ */
+ private boolean readXmlComment() throws IOException
+ {
+ for (int c = getChar(); c != EOF_CHAR;) {
+ addToString(c);
+ if (c == '-' && peekChar() == '-') {
+ c = getChar();
+ addToString(c);
+ if (peekChar() == '>') {
+ c = getChar(); // Skip >
+ addToString(c);
+ return true;
+ } else {
+ continue;
+ }
+ }
+ c = getChar();
+ }
+
+ stringBufferTop = 0; // throw away the string in progress
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return false;
+ }
+
+ /**
+ *
+ */
+ private boolean readCDATA() throws IOException
+ {
+ for (int c = getChar(); c != EOF_CHAR;) {
+ addToString(c);
+ if (c == ']' && peekChar() == ']') {
+ c = getChar();
+ addToString(c);
+ if (peekChar() == '>') {
+ c = getChar(); // Skip >
+ addToString(c);
+ return true;
+ } else {
+ continue;
+ }
+ }
+ c = getChar();
+ }
+
+ stringBufferTop = 0; // throw away the string in progress
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return false;
+ }
+
+ /**
+ *
+ */
+ private boolean readEntity() throws IOException
+ {
+ int declTags = 1;
+ for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+ addToString(c);
+ switch (c) {
+ case '<':
+ declTags++;
+ break;
+ case '>':
+ declTags--;
+ if (declTags == 0) return true;
+ break;
+ }
+ }
+
+ stringBufferTop = 0; // throw away the string in progress
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return false;
+ }
+
+ /**
+ *
+ */
+ private boolean readPI() throws IOException
+ {
+ for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+ addToString(c);
+ if (c == '?' && peekChar() == '>') {
+ c = getChar(); // Skip >
+ addToString(c);
+ return true;
+ }
+ }
+
+ stringBufferTop = 0; // throw away the string in progress
+ this.string = null;
+ parser.addError("msg.XML.bad.form");
+ return false;
+ }
+
+ private String getStringFromBuffer()
+ {
+ return new String(stringBuffer, 0, stringBufferTop);
+ }
+
+ private void addToString(int c)
+ {
+ int N = stringBufferTop;
+ if (N == stringBuffer.length) {
+ char[] tmp = new char[stringBuffer.length * 2];
+ System.arraycopy(stringBuffer, 0, tmp, 0, N);
+ stringBuffer = tmp;
+ }
+ stringBuffer[N] = (char)c;
+ stringBufferTop = N + 1;
+ }
+
+ private void ungetChar(int c)
+ {
+ // can not unread past across line boundary
+ if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n')
+ Kit.codeBug();
+ ungetBuffer[ungetCursor++] = c;
+ }
+
+ private boolean matchChar(int test) throws IOException
+ {
+ int c = getChar();
+ if (c == test) {
+ return true;
+ } else {
+ ungetChar(c);
+ return false;
+ }
+ }
+
+ private int peekChar() throws IOException
+ {
+ int c = getChar();
+ ungetChar(c);
+ return c;
+ }
+
+ private int getChar() throws IOException
+ {
+ if (ungetCursor != 0) {
+ return ungetBuffer[--ungetCursor];
+ }
+
+ for(;;) {
+ int c;
+ if (sourceString != null) {
+ if (sourceCursor == sourceEnd) {
+ hitEOF = true;
+ return EOF_CHAR;
+ }
+ c = sourceString.charAt(sourceCursor++);
+ } else {
+ if (sourceCursor == sourceEnd) {
+ if (!fillSourceBuffer()) {
+ hitEOF = true;
+ return EOF_CHAR;
+ }
+ }
+ c = sourceBuffer[sourceCursor++];
+ }
+
+ if (lineEndChar >= 0) {
+ if (lineEndChar == '\r' && c == '\n') {
+ lineEndChar = '\n';
+ continue;
+ }
+ lineEndChar = -1;
+ lineStart = sourceCursor - 1;
+ lineno++;
+ }
+
+ if (c <= 127) {
+ if (c == '\n' || c == '\r') {
+ lineEndChar = c;
+ c = '\n';
+ }
+ } else {
+ if (isJSFormatChar(c)) {
+ continue;
+ }
+ if (ScriptRuntime.isJSLineTerminator(c)) {
+ lineEndChar = c;
+ c = '\n';
+ }
+ }
+ return c;
+ }
+ }
+
+ private void skipLine() throws IOException
+ {
+ // skip to end of line
+ int c;
+ while ((c = getChar()) != EOF_CHAR && c != '\n') { }
+ ungetChar(c);
+ }
+
+ final int getOffset()
+ {
+ int n = sourceCursor - lineStart;
+ if (lineEndChar >= 0) { --n; }
+ return n;
+ }
+
+ final String getLine()
+ {
+ if (sourceString != null) {
+ // String case
+ int lineEnd = sourceCursor;
+ if (lineEndChar >= 0) {
+ --lineEnd;
+ } else {
+ for (; lineEnd != sourceEnd; ++lineEnd) {
+ int c = sourceString.charAt(lineEnd);
+ if (ScriptRuntime.isJSLineTerminator(c)) {
+ break;
+ }
+ }
+ }
+ return sourceString.substring(lineStart, lineEnd);
+ } else {
+ // Reader case
+ int lineLength = sourceCursor - lineStart;
+ if (lineEndChar >= 0) {
+ --lineLength;
+ } else {
+ // Read until the end of line
+ for (;; ++lineLength) {
+ int i = lineStart + lineLength;
+ if (i == sourceEnd) {
+ try {
+ if (!fillSourceBuffer()) { break; }
+ } catch (IOException ioe) {
+ // ignore it, we're already displaying an error...
+ break;
+ }
+ // i recalculuation as fillSourceBuffer can move saved
+ // line buffer and change lineStart
+ i = lineStart + lineLength;
+ }
+ int c = sourceBuffer[i];
+ if (ScriptRuntime.isJSLineTerminator(c)) {
+ break;
+ }
+ }
+ }
+ return new String(sourceBuffer, lineStart, lineLength);
+ }
+ }
+
+ private boolean fillSourceBuffer() throws IOException
+ {
+ if (sourceString != null) Kit.codeBug();
+ if (sourceEnd == sourceBuffer.length) {
+ if (lineStart != 0) {
+ System.arraycopy(sourceBuffer, lineStart, sourceBuffer, 0,
+ sourceEnd - lineStart);
+ sourceEnd -= lineStart;
+ sourceCursor -= lineStart;
+ lineStart = 0;
+ } else {
+ char[] tmp = new char[sourceBuffer.length * 2];
+ System.arraycopy(sourceBuffer, 0, tmp, 0, sourceEnd);
+ sourceBuffer = tmp;
+ }
+ }
+ int n = sourceReader.read(sourceBuffer, sourceEnd,
+ sourceBuffer.length - sourceEnd);
+ if (n < 0) {
+ return false;
+ }
+ sourceEnd += n;
+ return true;
+ }
+
+ // stuff other than whitespace since start of line
+ private boolean dirtyLine;
+
+ String regExpFlags;
+
+ // Set this to an inital non-null value so that the Parser has
+ // something to retrieve even if an error has occured and no
+ // string is found. Fosters one class of error, but saves lots of
+ // code.
+ private String string = "";
+ private double number;
+
+ private char[] stringBuffer = new char[128];
+ private int stringBufferTop;
+ private ObjToIntMap allStrings = new ObjToIntMap(50);
+
+ // Room to backtrace from to < on failed match of the last - in <!--
+ private final int[] ungetBuffer = new int[3];
+ private int ungetCursor;
+
+ private boolean hitEOF = false;
+
+ private int lineStart = 0;
+ private int lineno;
+ private int lineEndChar = -1;
+
+ private String sourceString;
+ private Reader sourceReader;
+ private char[] sourceBuffer;
+ private int sourceEnd;
+ private int sourceCursor;
+
+ // for xml tokenizer
+ private boolean xmlIsAttribute;
+ private boolean xmlIsTagContent;
+ private int xmlOpenTagsCount;
+
+ private Parser parser;
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Added: trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,295 @@
+// (C)2002 Douglas Crockford
+// www.JSLint.com
+// Rhino Edition
+
+var JSLINT;JSLINT=function(){var adsafe={activexobject:true,alert:true,back:true,body:true,close:true,confirm:true,cookie:true,constructor:true,createpopup:true,defaultstatus:true,defaultview:true,document:true,documentelement:true,domain:true,'eval':true,execScript:true,external:true,forms:true,forward:true,frameelement:true,fromcharcode:true,history:true,home:true,location:true,moveby:true,moveto:true,navigate:true,opener:true,parent:true,print:true,prompt:true,prototype:true,referrer:true,resizeby:true,resizeto:true,self:true,showhelp:true,showmodaldialog:true,status:true,stop:true,top:true,window:true,write:true,writeln:true,__proto__:true},allOptions={adsafe:true,bitwise:true,browser:true,cap:true,debug:true,eqeqeq:true,evil:true,fragment:true,laxbreak:true,nomen:true,passfail:true,plusplus:true,rhino:true,undef:true,white:true,widget:true},anonname,browser={alert:true,blur:true,clearInterval:true,clearTimeout:true,close:true,closed:true,confirm:true,console:true,Debug!
:true,defaultStatus:true,document:true,event:true,focus:true,frames:true,getComputedStyle:true,history:true,Image:true,length:true,location:true,moveBy:true,moveTo:true,name:true,navigator:true,onblur:true,onerror:true,onfocus:true,onload:true,onresize:true,onunload:true,open:true,opener:true,opera:true,parent:true,print:true,prompt:true,resizeBy:true,resizeTo:true,screen:true,scroll:true,scrollBy:true,scrollTo:true,self:true,setInterval:true,setTimeout:true,status:true,top:true,window:true,XMLHttpRequest:true},escapes={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},funct,functions,globals,implied,inblock,indent,jsonmode,lines,lookahead,member,membersOnly,nexttoken,noreach,option,prereg,prevtoken,rhino={defineClass:true,deserialize:true,gc:true,help:true,load:true,loadClass:true,print:true,quit:true,readFile:true,readUrl:true,runCommand:true,seal:true,serialize:true,spawn:true,sync:true,toint32:true,version:true},scope,stack,standard={Array:tr!
ue,Boolean:true,Date:true,decodeURI:true,decodeURIComponent:true,encod
eURI:true,encodeURIComponent:true,Error:true,escape:true,'eval':true,EvalError:true,Function:true,isFinite:true,isNaN:true,Math:true,Number:true,Object:true,parseInt:true,parseFloat:true,RangeError:true,ReferenceError:true,RegExp:true,String:true,SyntaxError:true,TypeError:true,unescape:true,URIError:true},syntax={},token,verb,warnings,widget={alert:true,appleScript:true,animator:true,appleScript:true,beep:true,bytesToUIString:true,Canvas:true,chooseColor:true,chooseFile:true,chooseFolder:true,convertPathToHFS:true,convertPathToPlatform:true,closeWidget:true,COM:true,CustomAnimation:true,escape:true,FadeAnimation:true,filesystem:true,focusWidget:true,form:true,Frame:true,HotKey:true,Image:true,include:true,isApplicationRunning:true,iTunes:true,konfabulatorVersion:true,log:true,MenuItem:true,MoveAnimation:true,openURL:true,play:true,Point:true,popupMenu:true,preferenceGroups:true,preferences:true,print:true,prompt:true,random:true,reloadWidget:true,resolvePath:true,resumeUpda!
tes:true,RotateAnimation:true,runCommand:true,runCommandInBg:true,saveAs:true,savePreferences:true,screen:true,ScrollBar:true,showWidgetPreferences:true,sleep:true,speak:true,suppressUpdates:true,system:true,tellWidget:true,Text:true,TextArea:true,unescape:true,updateNow:true,URL:true,widget:true,Window:true,XMLDOM:true,XMLHttpRequest:true,yahooCheckLogin:true,yahooLogin:true,yahooLogout:true},wmode,xmode,xtype,tx=/^\s*([(){}[.,:;'"~]|\](\]>)?|\?>?|==?=?|\/(\*(global|extern|jslint|member|members)?|=|\/)?|\*[\/=]?|\+[+=]?|-[-=]?|%[=>]?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=%\?]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+-]?[0-9]+)?)/,rx=/^(\\[^\x00-\x1f]|\[(\\[^\x00-\x1f]|[^\x00-\x1f\\\/])*\]|[^\x00-\x1f\\\/\[])+\/[gim]*/,lx=/\*\/|\/\*/,ix=/^([a-zA-Z_$][a-zA-Z0-9_$]*$)/,jx=/(javascript|jscript|ecmascript)\s*:/i;Object.prototype.begetObject=function(){function F(){}
+F.prototype=this;return new F();};Object.prototype.combine=function(o){var n;for(n in o){if(o.hasOwnProperty(n)){this[n]=o[n];}}};String.prototype.entityify=function(){return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');};String.prototype.isAlpha=function(){return(this>='a'&&this<='z\uffff')||(this>='A'&&this<='Z\uffff');};String.prototype.isDigit=function(){return(this>='0'&&this<='9');};String.prototype.supplant=function(o){return this.replace(/{([^{}]*)}/g,function(a,b){var r=o[b];return typeof r==='string'||typeof r==='number'?r:a;});};String.prototype.name=function(){if(ix.test(this)){return this;}
+if(/[&<"\\\x00-\x1f]/.test(this)){return'"'+this.replace(/[&<"\\\x00-\x1f]/g,function(a){var c=escapes[a];if(c){return c;}
+c=a.charCodeAt();return'\\u00'+
+Math.floor(c/16).toString(16)+
+(c%16).toString(16);})+'"';}
+return'"'+this+'"';};function populateGlobals(){if(option.rhino){globals.combine(rhino);}
+if(option.browser){globals.combine(browser);}
+if(option.widget){globals.combine(widget);}}
+function quit(m,l,ch){throw{name:'JSLintError',line:l,character:ch,message:m+" ("+Math.floor((l/lines.length)*100)+"% scanned)."};}
+function warning(m,t,a,b,c,d){var ch,l,w;t=t||nexttoken;if(t.id==='(end)'){t=token;}
+l=t.line||0;ch=t.from||0;w={id:'(error)',raw:m,evidence:lines[l]||'',line:l,character:ch,a:a,b:b,c:c,d:d};w.reason=m.supplant(w);JSLINT.errors.push(w);if(option.passfail){quit('Stopping. ',l,ch);}
+warnings+=1;if(warnings===50){quit("Too many errors.",l,ch);}
+return w;}
+function warningAt(m,l,ch,a,b,c,d){return warning(m,{line:l,from:ch},a,b,c,d);}
+function error(m,t,a,b,c,d){var w=warning(m,t,a,b,c,d);quit("Stopping, unable to continue.",w.line,w.character);}
+function errorAt(m,l,ch,a,b,c,d){return error(m,{line:l,from:ch},a,b,c,d);}
+var lex=function(){var character,from,line,s;function nextLine(){line+=1;if(line>=lines.length){return false;}
+character=0;s=lines[line];return true;}
+function it(type,value){var i,t;if(option.adsafe&&adsafe[value.toLowerCase()]===true){warning("Adsafe restricted word '{a}'.",{line:line,from:character},value);}
+if(type==='(punctuator)'||(type==='(identifier)'&&syntax.hasOwnProperty(value))){t=syntax[value];if(!t.id){t=syntax[type];}}else{t=syntax[type];}
+t=t.begetObject();if(type==='(string)'){if(/(javascript|jscript|ecmascript)\s*:/i.test(value)){warningAt("JavaScript URL.",line,from);}}
+t.value=value;t.line=line;t.character=character;t.from=from;i=t.id;prereg=i&&(('(,=:[!&|?{};'.indexOf(i.charAt(i.length-1))>=0)||i==='return');return t;}
+return{init:function(source){if(typeof source==='string'){lines=source.replace(/\r\n/g,'\n').replace(/\r/g,'\n').split('\n');}else{lines=source;}
+line=0;character=0;from=0;s=lines[0];},token:function(){var c,d,i,l,r,t;function match(x){var r=x.exec(s),r1;if(r){l=r[0].length;r1=r[1];c=r1.charAt(0);s=s.substr(l);character+=l;from=character-r1.length;return r1;}}
+function string(x){var c,j,r='';if(jsonmode&&x!=='"'){warningAt("Strings must use doublequote.",line,character);}
+if(xmode===x||xmode==='string'){return it('(punctuator)',x);}
+function esc(n){var i=parseInt(s.substr(j+1,n),16);j+=n;if(i>=32&&i<=127&&i!==34&&i!==92&&i!==39){warningAt("Unnecessary escapement.",line,character);}
+character+=n;c=String.fromCharCode(i);}
+for(j=0;j<s.length;j+=1){c=s.charAt(j);if(c===x){character+=1;s=s.substr(j+1);return it('(string)',r,x);}
+if(c<' '){if(c==='\n'||c==='\r'){break;}
+warningAt("Control character in string: {a}.",line,character+j,s.substring(0,j));}else if(c==='<'){if(s.charAt(j+1)==='/'&&xmode&&xmode!=='CDATA'){warningAt("Expected '<\\/' and instead saw '</'.",line,character);}}else if(c==='\\'){j+=1;character+=1;c=s.charAt(j);switch(c){case'\\':case'\'':case'"':case'/':break;case'b':c='\b';break;case'f':c='\f';break;case'n':c='\n';break;case'r':c='\r';break;case't':c='\t';break;case'u':esc(4);break;case'v':c='\v';break;case'x':if(jsonmode){warningAt("Avoid \\x-.",line,character);}
+esc(2);break;default:warningAt("Bad escapement.",line,character);}}
+r+=c;character+=1;}
+errorAt("Unclosed string.",line,from);}
+for(;;){if(!s){return it(nextLine()?'(endline)':'(end)','');}
+t=match(tx);if(!t){t='';c='';while(s&&s<'!'){s=s.substr(1);}
+if(s){errorAt("Unexpected '{a}'.",line,character,s.substr(0,1));}}
+if(c.isAlpha()||c==='_'||c==='$'){return it('(identifier)',t);}
+if(c.isDigit()){if(!isFinite(Number(t))){warningAt("Bad number '{a}'.",line,character,t);}
+if(s.substr(0,1).isAlpha()){warningAt("Missing space after '{a}'.",line,character,t);}
+if(c==='0'){d=t.substr(1,1);if(d.isDigit()){warningAt("Don't use extra leading zeros '{a}'.",line,character,t);}else if(jsonmode&&(d==='x'||d==='X')){warningAt("Avoid 0x-. '{a}'.",line,character,t);}}
+if(t.substr(t.length-1)==='.'){warningAt("A trailing decimal point can be confused with a dot '{a}'.",line,character,t);}
+return it('(number)',t);}
+switch(t){case'"':case"'":return string(t);case'//':s='';break;case'/*':for(;;){i=s.search(lx);if(i>=0){break;}
+if(!nextLine()){errorAt("Unclosed comment.",line,character);}}
+character+=i+2;if(s.substr(i,1)==='/'){errorAt("Nested comment.",line,character);}
+s=s.substr(i+2);break;case'/*extern':case'/*global':case'/*members':case'/*member':case'/*jslint':case'*/':return{value:t,type:'special',line:line,character:character,from:from};case'':break;case'/':if(prereg){r=rx.exec(s);if(r){c=r[0];l=c.length;character+=l;s=s.substr(l);return it('(regex)',c);}
+errorAt("Bad regular expression.",line,character);}
+return it('(punctuator)',t);default:return it('(punctuator)',t);}}},skip:function(p){var i,t=p;if(nexttoken.id){if(!t){t='';if(nexttoken.id.substr(0,1)==='<'){lookahead.push(nexttoken);return true;}}else if(nexttoken.id.indexOf(t)>=0){return true;}}
+token=nexttoken;nexttoken=syntax['(end)'];for(;;){i=s.indexOf(t||'<');if(i>=0){character+=i+t.length;s=s.substr(i+t.length);return true;}
+if(!nextLine()){break;}}
+return false;}};}();function addlabel(t,type){if(t==='hasOwnProperty'){error("'hasOwnProperty' is a really bad name.");}
+if(funct===true){scope[t]=true;}else{if(funct.hasOwnProperty(t)){warning(funct[t]===true?"'{a}' was used before it was defined.":"'{a}' is already defined.",nexttoken,t);}
+scope[t]=funct;funct[t]=type;}}
+function doOption(){var b,obj,filter,t,v;switch(nexttoken.value){case'*/':error("Unbegun comment.");break;case'/*extern':case'/*global':obj=globals;break;case'/*members':case'/*member':if(!membersOnly){membersOnly={};}
+obj=membersOnly;break;case'/*jslint':if(option.adsafe){error("Adsafe restriction.");}
+obj=option;filter=allOptions;}
+for(;;){t=lex.token();if(t.id===','){t=lex.token();}
+while(t.id==='(endline)'){t=lex.token();}
+if(t.type==='special'&&t.value==='*/'){break;}
+if(t.type!=='(string)'&&t.type!=='(identifier)'){error("Bad option.",t);}
+if(filter){if(filter[t.value]!==true){error("Bad option.",t);}
+v=lex.token();if(v.id!==':'){error("Expected '{a}' and instead saw '{b}'.",t,':',t.value);}
+v=lex.token();if(v.value==='true'){b=true;}else if(v.value==='false'){b=false;}else{error("Expected '{a}' and instead saw '{b}'.",t,'true',t.value);}}else{b=true;}
+obj[t.value]=b;}
+if(filter){populateGlobals();}}
+function peek(p){var i=p||0,j=0,t;while(j<=i){t=lookahead[j];if(!t){t=lookahead[j]=lex.token();}
+j+=1;}
+return t;}
+var badbreak={')':true,']':true,'++':true,'--':true};function advance(id,t){var l;switch(token.id){case'(number)':if(nexttoken.id==='.'){warning("A dot following a number can be confused with a decimal point.",token);}
+break;case'-':if(nexttoken.id==='-'||nexttoken.id==='--'){warning("Confusing minusses.");}
+break;case'+':if(nexttoken.id==='+'||nexttoken.id==='++'){warning("Confusing plusses.");}
+break;}
+if(token.type==='(string)'||token.identifier){anonname=token.value;}
+if(id&&nexttoken.id!==id){if(t){if(nexttoken.id==='(end)'){warning("Unmatched '{a}'.",t,t.id);}else{warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",nexttoken,id,t.id,t.line+1,nexttoken.value);}}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,id,nexttoken.value);}}
+prevtoken=token;token=nexttoken;for(;;){nexttoken=lookahead.shift()||lex.token();if(nexttoken.type==='special'){doOption();}else{if(nexttoken.id==='<!['){if(xtype==='html'){error("Unexpected '{a}'.",nexttoken,'<![');}
+if(xmode==='script'){nexttoken=lex.token();if(nexttoken.value!=='CDATA'){error("Missing '{a}'.",nexttoken,'CDATA');}
+nexttoken=lex.token();if(nexttoken.id!=='['){error("Missing '{a}'.",nexttoken,'[');}
+xmode='CDATA';}else if(xmode==='xml'){lex.skip(']]>');}else{error("Unexpected '{a}'.",nexttoken,'<![');}}else if(nexttoken.id===']]>'){if(xmode==='CDATA'){xmode='script';}else{error("Unexpected '{a}'.",nexttoken,']]>');}}else if(nexttoken.id!=='(endline)'){break;}
+if(xmode==='"'||xmode==="'"){error("Missing '{a}'.",token,xmode);}
+l=!xmode&&!option.laxbreak&&(token.type==='(string)'||token.type==='(number)'||token.type==='(identifier)'||badbreak[token.id]);}}
+if(l){switch(nexttoken.id){case'{':case'}':case']':break;case')':switch(token.id){case')':case'}':case']':break;default:warning("Line breaking error '{a}'.",token,')');}
+break;default:warning("Line breaking error '{a}'.",token,token.value);}}
+if(xtype==='widget'&&xmode==='script'&&nexttoken.id){l=nexttoken.id.charAt(0);if(l==='<'||l==='&'){nexttoken.nud=nexttoken.led=null;nexttoken.lbp=0;nexttoken.reach=true;}}}
+function parse(rbp,initial){var left;var o;if(nexttoken.id==='(end)'){error("Unexpected early end of program.",token);}
+advance();if(initial){anonname='anonymous';verb=token.value;}
+if(initial&&token.fud){token.fud();}else{if(token.nud){o=token.exps;left=token.nud();}else{if(nexttoken.type==='(number)'&&token.id==='.'){warning("A leading decimal point can be confused with a dot: '.{a}'.",token,nexttoken.value);advance();return token;}else{error("Expected an identifier and instead saw '{a}'.",token,token.id);}}
+while(rbp<nexttoken.lbp){o=nexttoken.exps;advance();if(token.led){left=token.led(left);}else{error("Expected an operator and instead saw '{a}'.",token,token.id);}}
+if(initial&&!o){warning("Expected an assignment or function call and instead saw an expression.",token);}}
+if(!option.evil&&left&&left.value==='eval'){warning("eval is evil.",left);}
+return left;}
+function adjacent(left,right){left=left||token;right=right||nexttoken;if(option.white){if(left.character!==right.from){warning("Unexpected space after '{a}'.",nexttoken,left.value);}}}
+function nospace(left,right){left=left||token;right=right||nexttoken;if(option.white){if(left.line===right.line){adjacent(left,right);}}}
+function nonadjacent(left,right){left=left||token;right=right||nexttoken;if(option.white){if(left.character===right.from){warning("Missing space after '{a}'.",nexttoken,left.value);}}}
+function indentation(bias){var i;if(option.white&&nexttoken.id!=='(end)'){i=indent+(bias||0);if(nexttoken.from!==i){warning("Expected '{a}' to have an indentation of {b} instead of {c}.",nexttoken,nexttoken.value,i,nexttoken.from);}}}
+function symbol(s,p){return syntax[s]||(syntax[s]={id:s,lbp:p,value:s});}
+function delim(s){return symbol(s,0);}
+function stmt(s,f){var x=delim(s);x.identifier=x.reserved=true;x.fud=f;return x;}
+function blockstmt(s,f){var x=stmt(s,f);x.block=true;return x;}
+function reserveName(x){var c=x.id.charAt(0);if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){x.identifier=x.reserved=true;}
+return x;}
+function prefix(s,f){var x=symbol(s,150);reserveName(x);x.nud=(typeof f==='function')?f:function(){if(option.plusplus&&(this.id==='++'||this.id==='--')){warning("Unexpected use of '{a}'.",this,this.id);}
+parse(150);return this;};return x;}
+function type(s,f){var x=delim(s);x.type=s;x.nud=f;return x;}
+function reserve(s,f){var x=type(s,f);x.identifier=x.reserved=true;return x;}
+function reservevar(s){return reserve(s,function(){return this;});}
+function infix(s,f,p){var x=symbol(s,p);reserveName(x);x.led=(typeof f==='function')?f:function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);return[this.id,left,parse(p)];};return x;}
+function relation(s,f){var x=symbol(s,100);x.led=function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);var right=parse(100);if((left&&left.id==='NaN')||(right&&right.id==='NaN')){warning("Use the isNaN function to compare with NaN.",this);}else if(f){f.apply(this,[left,right]);}
+return[this.id,left,right];};return x;}
+function isPoorRelation(node){return(node.type==='(number)'&&!+node.value)||(node.type==='(string)'&&!node.value)||node.type==='true'||node.type==='false'||node.type==='undefined'||node.type==='null';}
+function assignop(s,f){symbol(s,20).exps=true;return infix(s,function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);if(left){if(left.id==='.'||left.id==='['||(left.identifier&&!left.reserved)){parse(19);return left;}
+if(left===syntax['function']){warning("Expected an identifier in an assignment and instead saw a function invocation.",token);}}
+error("Bad assignment.",this);},20);}
+function bitwise(s,f,p){var x=symbol(s,p);reserveName(x);x.led=(typeof f==='function')?f:function(left){if(option.bitwise){warning("Unexpected use of '{a}'.",this,this.id);}
+nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);return[this.id,left,parse(p)];};return x;}
+function bitwiseassignop(s){symbol(s,20).exps=true;return infix(s,function(left){if(option.bitwise){warning("Unexpected use of '{a}'.",this,this.id);}
+nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);if(left){if(left.id==='.'||left.id==='['||(left.identifier&&!left.reserved)){parse(19);return left;}
+if(left===syntax['function']){warning("Expected an identifier in an assignment, and instead saw a function invocation.",token);}}
+error("Bad assignment.",this);},20);}
+function suffix(s,f){var x=symbol(s,150);x.led=function(left){if(option.plusplus){warning("Unexpected use of '{a}'.",this,this.id);}
+return[f,left];};return x;}
+function optionalidentifier(){if(nexttoken.reserved){warning("Expected an identifier and instead saw '{a}' (a reserved word).",nexttoken,nexttoken.id);}
+if(nexttoken.identifier){if(option.nomen){if(nexttoken.value.charAt(0)==='_'||nexttoken.value.indexOf('$')>=0){warning("Unexpected characters in '{a}'.",nexttoken,nexttoken.value);}}
+advance();return token.value;}}
+function identifier(){var i=optionalidentifier();if(i){return i;}
+if(token.id==='function'&&nexttoken.id==='('){warning("Missing name in function statement.");}else{error("Expected an identifier and instead saw '{a}'.",nexttoken,nexttoken.value);}}
+function reachable(s){var i=0;var t;if(nexttoken.id!==';'||noreach){return;}
+for(;;){t=peek(i);if(t.reach){return;}
+if(t.id!=='(endline)'){if(t.id==='function'){warning("Inner functions should be listed at the top of the outer function.",t);break;}
+warning("Unreachable '{a}' after '{b}'.",t,t.value,s);break;}
+i+=1;}}
+function statement(){var i=indent,s=scope,t=nexttoken;if(t.id===';'){warning("Unnecessary semicolon.",t);advance(';');return;}
+if(t.identifier&&!t.reserved&&peek().id===':'){advance();advance(':');scope=s.begetObject();addlabel(t.value,'label');if(!nexttoken.labelled){warning("Label '{a}' on {b} statement.",nexttoken,t.value,nexttoken.value);}
+if(jx.test(t.value+':')){warning("Label '{a}' looks like a javascript url.",t,t.value);}
+nexttoken.label=t.value;t=nexttoken;}
+parse(0,true);if(!t.block){if(nexttoken.id!==';'){warningAt("Missing semicolon.",token.line,token.from+token.value.length);}else{adjacent(token,nexttoken);advance(';');nonadjacent(token,nexttoken);}}
+indent=i;scope=s;}
+function statements(){while(!nexttoken.reach&&nexttoken.id!=='(end)'){if(nexttoken.id===';'){warning("Unnecessary semicolon.");advance(';');}
+indentation();statement();}}
+function block(f){var b=inblock,s=scope;inblock=f;if(f){scope=scope.begetObject();}
+nonadjacent(token,nexttoken);var t=nexttoken;if(nexttoken.id==='{'){advance('{');if(nexttoken.id!=='}'||token.line!==nexttoken.line){indent+=4;if(!f&&nexttoken.from===indent+4){indent+=4;}
+statements();indent-=4;indentation();}
+advance('}',t);}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'{',nexttoken.value);noreach=true;statement();noreach=false;}
+verb=null;scope=s;inblock=b;}
+function idValue(){return this;}
+function countMember(m){if(membersOnly&&membersOnly[m]!==true){warning("Unexpected member '{a}'.",nexttoken,m);}
+if(typeof member[m]==='number'){member[m]+=1;}else{member[m]=1;}}
+var scriptstring={onblur:true,onchange:true,onclick:true,ondblclick:true,onfocus:true,onkeydown:true,onkeypress:true,onkeyup:true,onload:true,onmousedown:true,onmousemove:true,onmouseout:true,onmouseover:true,onmouseup:true,onreset:true,onselect:true,onsubmit:true,onunload:true};var xmltype={HTML:{doBegin:function(n){if(!option.cap){warning("HTML case error.");}
+xmltype.html.doBegin();}},html:{doBegin:function(n){xtype='html';xmltype.html.script=false;option.browser=true;populateGlobals();},doTagName:function(n,p){var i;var t=xmltype.html.tag[n];var x;if(!t){error("Unrecognized tag '<{a}>'.",nexttoken,n===n.toLowerCase()?n:n+' (capitalization error)');}
+x=t.parent;if(x){if(x.indexOf(' '+p+' ')<0){error("A '<{a}>' must be within '<{b}>'.",token,n,x);}}else{i=stack.length;do{if(i<=0){error("A '<{a}>' must be within '<{b}>'.",token,n,'body');}
+i-=1;}while(stack[i].name!=='body');}
+xmltype.html.script=n==='script';return t.empty;},doAttribute:function(n,a){if(n==='script'){if(a==='src'){xmltype.html.script=false;return'string';}else if(a==='language'){warning("The 'language' attribute is deprecated.",token);return false;}}
+if(a==='href'){return'href';}
+return scriptstring[a]&&'script';},doIt:function(n){return xmltype.html.script?'script':n!=='html'&&xmltype.html.tag[n].special&&'special';},tag:{a:{},abbr:{},acronym:{},address:{},applet:{},area:{empty:true,parent:' map '},b:{},base:{empty:true,parent:' head '},bdo:{},big:{},blockquote:{},body:{parent:' html noframes '},br:{empty:true},button:{},canvas:{parent:' body p div th td '},caption:{parent:' table '},center:{},cite:{},code:{},col:{empty:true,parent:' table colgroup '},colgroup:{parent:' table '},dd:{parent:' dl '},del:{},dfn:{},dir:{},div:{},dl:{},dt:{parent:' dl '},em:{},embed:{},fieldset:{},font:{},form:{},frame:{empty:true,parent:' frameset '},frameset:{parent:' html frameset '},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},head:{parent:' html '},html:{},hr:{empty:true},i:{},iframe:{},img:{empty:true},input:{empty:true},ins:{},kbd:{},label:{},legend:{parent:' fieldset '},li:{parent:' dir menu ol ul '},link:{empty:true,parent:' head '},map:{},menu:{},meta:{empty:true,paren!
t:' head noscript '},noframes:{parent:' html body '},noscript:{parent:' applet blockquote body button center dd del div fieldset form frameset head html iframe ins li map noframes noscript object td th '},object:{},ol:{},optgroup:{parent:' select '},option:{parent:' optgroup select '},p:{},param:{empty:true,parent:' applet object '},pre:{},q:{},samp:{},script:{parent:' head body p div span abbr acronym address bdo blockquote cite code del dfn em ins kbd pre samp strong table tbody td th tr var '},select:{},small:{},span:{},strong:{},style:{parent:' head ',special:true},sub:{},sup:{},table:{},tbody:{parent:' table '},td:{parent:' tr '},textarea:{},tfoot:{parent:' table '},th:{parent:' tr '},thead:{parent:' table '},title:{parent:' head '},tr:{parent:' table tbody thead tfoot '},tt:{},u:{},ul:{},'var':{}}},widget:{doBegin:function(n){xtype='widget';option.widget=true;populateGlobals();},doTagName:function(n,p){var t=xmltype.widget.tag[n];if(!t){error("Unrecognized tag '<{a}>'!
.",nexttoken,n);}
+var x=t.parent;if(x.indexOf(' '+p+' ')<0){error("A '<{a}>' must be within '<{b}>'.",token,n,x);}},doAttribute:function(n,a){var t=xmltype.widget.tag[a];if(!t){error("Unrecognized attribute '<{a} {b}>'.",nexttoken,n,a);}
+var x=t.parent;if(x.indexOf(' '+n+' ')<0){error("Attribute '{a}' does not belong in '<{b}>'.",nexttoken,a,n);}
+return t.script?'script':a==='name'&&n!=='setting'?'define':'string';},doIt:function(n){var x=xmltype.widget.tag[n];return x&&x.script&&'script';},tag:{"about-box":{parent:' widget '},"about-image":{parent:' about-box '},"about-text":{parent:' about-box '},"about-version":{parent:' about-box '},action:{parent:' widget ',script:true},alignment:{parent:' canvas frame image scrollbar text textarea window '},anchorStyle:{parent:' text '},author:{parent:' widget '},autoHide:{parent:' scrollbar '},beget:{parent:' canvas frame image scrollbar text window '},bgColor:{parent:' text textarea '},bgColour:{parent:' text textarea '},bgOpacity:{parent:' text textarea '},canvas:{parent:' frame window '},checked:{parent:' image menuItem '},clipRect:{parent:' image '},color:{parent:' about-text about-version shadow text textarea '},colorize:{parent:' image '},colour:{parent:' about-text about-version shadow text textarea '},columns:{parent:' textarea '},company:{parent:' widget '},contextMe!
nuItems:{parent:' canvas frame image scrollbar text textarea window '},copyright:{parent:' widget '},data:{parent:' about-text about-version text textarea '},debug:{parent:' widget '},defaultValue:{parent:' preference '},defaultTracking:{parent:' widget '},description:{parent:' preference '},directory:{parent:' preference '},editable:{parent:' textarea '},enabled:{parent:' menuItem '},extension:{parent:' preference '},file:{parent:' action preference '},fillMode:{parent:' image '},font:{parent:' about-text about-version text textarea '},fontStyle:{parent:' textarea '},frame:{parent:' frame window '},group:{parent:' preference '},hAlign:{parent:' canvas frame image scrollbar text textarea '},handleLinks:{parent:' textArea '},height:{parent:' canvas frame image scrollbar text textarea window '},hidden:{parent:' preference '},hLineSize:{parent:' frame '},hOffset:{parent:' about-text about-version canvas frame image scrollbar shadow text textarea window '},hotkey:{parent:' widg!
et '},hRegistrationPoint:{parent:' canvas frame image scrollbar text '
},hScrollBar:{parent:' frame '},hslAdjustment:{parent:' image '},hslTinting:{parent:' image '},icon:{parent:' preferenceGroup '},id:{parent:' canvas frame hotkey image preference text textarea timer scrollbar widget window '},image:{parent:' about-box frame window widget '},interval:{parent:' action timer '},key:{parent:' hotkey '},kind:{parent:' preference '},level:{parent:' window '},lines:{parent:' textarea '},loadingSrc:{parent:' image '},locked:{parent:' window '},max:{parent:' scrollbar '},maxLength:{parent:' preference '},menuItem:{parent:' contextMenuItems '},min:{parent:' scrollbar '},minimumVersion:{parent:' widget '},minLength:{parent:' preference '},missingSrc:{parent:' image '},modifier:{parent:' hotkey '},name:{parent:' canvas frame hotkey image preference preferenceGroup scrollbar setting text textarea timer widget window '},notSaved:{parent:' preference '},onClick:{parent:' canvas frame image scrollbar text textarea ',script:true},onContextMenu:{parent:' canv!
as frame image scrollbar text textarea window ',script:true},onDragDrop:{parent:' canvas frame image scrollbar text textarea ',script:true},onDragEnter:{parent:' canvas frame image scrollbar text textarea ',script:true},onDragExit:{parent:' canvas frame image scrollbar text textarea ',script:true},onFirstDisplay:{parent:' window ',script:true},onGainFocus:{parent:' textarea window ',script:true},onKeyDown:{parent:' hotkey text textarea window ',script:true},onKeyPress:{parent:' textarea window ',script:true},onKeyUp:{parent:' hotkey text textarea window ',script:true},onImageLoaded:{parent:' image ',script:true},onLoseFocus:{parent:' textarea window ',script:true},onMouseDown:{parent:' canvas frame image scrollbar text textarea window ',script:true},onMouseDrag:{parent:' canvas frame image scrollbar text textArea window ',script:true},onMouseEnter:{parent:' canvas frame image scrollbar text textarea window ',script:true},onMouseExit:{parent:' canvas frame image scrollbar te!
xt textarea window ',script:true},onMouseMove:{parent:' canvas frame i
mage scrollbar text textarea window ',script:true},onMouseUp:{parent:' canvas frame image scrollbar text textarea window ',script:true},onMouseWheel:{parent:' frame ',script:true},onMultiClick:{parent:' canvas frame image scrollbar text textarea window ',script:true},onSelect:{parent:' menuItem ',script:true},onTextInput:{parent:' window ',script:true},onTimerFired:{parent:' timer ',script:true},onValueChanged:{parent:' scrollbar ',script:true},opacity:{parent:' canvas frame image scrollbar shadow text textarea window '},option:{parent:' preference widget '},optionValue:{parent:' preference '},order:{parent:' preferenceGroup '},orientation:{parent:' scrollbar '},pageSize:{parent:' scrollbar '},preference:{parent:' widget '},preferenceGroup:{parent:' widget '},remoteAsync:{parent:' image '},requiredPlatform:{parent:' widget '},root:{parent:' window '},rotation:{parent:' canvas frame image scrollbar text '},scrollbar:{parent:' frame text textarea window '},scrolling:{parent:' !
text '},scrollX:{parent:' frame '},scrollY:{parent:' frame '},secure:{parent:' preference textarea '},setting:{parent:' settings '},settings:{parent:' widget '},shadow:{parent:' about-text about-version text window '},size:{parent:' about-text about-version text textarea '},spellcheck:{parent:' textarea '},src:{parent:' image '},srcHeight:{parent:' image '},srcWidth:{parent:' image '},style:{parent:' about-text about-version canvas frame image preference scrollbar text textarea window '},subviews:{parent:' frame '},superview:{parent:' canvas frame image scrollbar text textarea '},text:{parent:' frame text textarea window '},textarea:{parent:' frame window '},timer:{parent:' widget '},thumbColor:{parent:' scrollbar textarea '},ticking:{parent:' timer '},ticks:{parent:' preference '},tickLabel:{parent:' preference '},tileOrigin:{parent:' image '},title:{parent:' menuItem preference preferenceGroup window '},tooltip:{parent:' frame image text textarea '},tracking:{parent:' can!
vas image '},trigger:{parent:' action '},truncation:{parent:' text '},
type:{parent:' preference '},url:{parent:' about-box about-text about-version '},useFileIcon:{parent:' image '},vAlign:{parent:' canvas frame image scrollbar text textarea '},value:{parent:' preference scrollbar setting '},version:{parent:' widget '},visible:{parent:' canvas frame image scrollbar text textarea window '},vLineSize:{parent:' frame '},vOffset:{parent:' about-text about-version canvas frame image scrollbar shadow text textarea window '},vRegistrationPoint:{parent:' canvas frame image scrollbar text '},vScrollBar:{parent:' frame '},width:{parent:' canvas frame image scrollbar text textarea window '},window:{parent:' canvas frame image scrollbar text textarea widget '},wrap:{parent:' text '},zOrder:{parent:' canvas frame image scrollbar text textarea window '}}}};function xmlword(tag){var w=nexttoken.value;if(!nexttoken.identifier){if(nexttoken.id==='<'){if(tag){error("Expected '{a}' and instead saw '{b}'.",token,'<','<');}else{error("Missing '{a}'.",token,'>')!
;}}else if(nexttoken.id==='(end)'){error("Bad structure.");}else{warning("Missing quote.",token);}}
+advance();while(nexttoken.id==='-'||nexttoken.id===':'){w+=nexttoken.id;advance();if(!nexttoken.identifier){error("Bad name '{a}'.",nexttoken,w+nexttoken.value);}
+w+=nexttoken.value;advance();}
+return w;}
+function closetag(n){return'</'+n+'>';}
+function xml(){var a,e,n,q,t;xmode='xml';stack=null;for(;;){switch(nexttoken.value){case'<':if(!stack){stack=[];}
+advance('<');t=nexttoken;n=xmlword(true);t.name=n;if(!xtype){if(xmltype[n]){xmltype[n].doBegin();n=xtype;e=false;}else{if(option.fragment){xmltype.html.doBegin();stack=[{name:'body'}];e=xmltype[xtype].doTagName(n,'body');}else{error("Unrecognized tag '<{a}>'.",nexttoken,n);}}}else{if(option.cap&&xtype==='html'){n=n.toLowerCase();}
+if(stack.length===0){error("What the hell is this?");}
+e=xmltype[xtype].doTagName(n,stack[stack.length-1].name);}
+t.type=n;for(;;){if(nexttoken.id==='/'){advance('/');e=true;break;}
+if(nexttoken.id&&nexttoken.id.substr(0,1)==='>'){break;}
+a=xmlword();switch(xmltype[xtype].doAttribute(n,a)){case'script':xmode='string';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
+xmode=q;wmode=option.white;option.white=false;advance(q);statements();option.white=wmode;if(nexttoken.id!==q){error("Missing close quote on script attribute.");}
+xmode='xml';advance(q);break;case'value':advance('=');if(!nexttoken.identifier&&nexttoken.type!=='(string)'&&nexttoken.type!=='(number)'){error("Bad value '{a}'.",nexttoken,nexttoken.value);}
+advance();break;case'string':case'href':advance('=');if(nexttoken.type!=='(string)'){error("Bad value '{a}'.",nexttoken,nexttoken.value);}
+advance();break;case'define':advance('=');if(nexttoken.type!=='(string)'){error("Bad value '{a}'.",nexttoken,nexttoken.value);}
+addlabel(nexttoken.value,'var');advance();break;default:if(nexttoken.id==='='){advance('=');if(!nexttoken.identifier&&nexttoken.type!=='(string)'&&nexttoken.type!=='(number)'){}
+advance();}}}
+switch(xmltype[xtype].doIt(n)){case'script':xmode='script';advance('>');indent=nexttoken.from;statements();if(nexttoken.id!=='</'&&nexttoken.id!=='(end)'){warning("Unexpected '{a}'.",nexttoken,nexttoken.id);}
+xmode='xml';break;case'special':e=true;n=closetag(t.name);if(!lex.skip(n)){error("Missing '{a}'.",t,n);}
+break;default:lex.skip('>');}
+if(!e){stack.push(t);}
+break;case'</':advance('</');n=xmlword(true);t=stack.pop();if(!t){error("Unexpected '{a}'.",nexttoken,closetag(n));}
+if(t.name!==n){error("Expected '{a}' and instead saw '{b}'.",nexttoken,closetag(t.name),closetag(n));}
+if(nexttoken.id!=='>'){error("Missing '{a}'.",nexttoken,'>');}
+if(stack.length>0){lex.skip('>');}else{advance('>');}
+break;case'<!':for(;;){advance();if(nexttoken.id==='>'){break;}
+if(nexttoken.id==='<'||nexttoken.id==='(end)'){error("Missing '{a}'.",token,'>');}}
+lex.skip('>');break;case'<!--':lex.skip('-->');break;case'<%':lex.skip('%>');break;case'<?':for(;;){advance();if(nexttoken.id==='?>'){break;}
+if(nexttoken.id==='<?'||nexttoken.id==='<'||nexttoken.id==='>'||nexttoken.id==='(end)'){error("Missing '{a}'.",token,'?>');}}
+lex.skip('?>');break;case'<=':case'<<':case'<<=':error("Missing '{a}'.",nexttoken,'<');break;case'(end)':return;}
+if(stack&&stack.length===0){return;}
+if(!lex.skip('')){t=stack.pop();if(t.value){error("Missing '{a}'.",t,closetag(t.name));}else{return;}}
+advance();}}
+type('(number)',idValue);type('(string)',idValue);syntax['(identifier)']={type:'(identifier)',lbp:0,identifier:true,nud:function(){var v=this.value,s=scope[v];if(s===funct){if(funct!==true){switch(funct[v]){case'unused':funct[v]='var';break;case'label':warning("'{a}' is a statement label.",token,v);break;}}}else if(funct===true){if(option.undef){warning("'{a}' is undefined.",token,v);}else{implied[v]=true;globals[v]=true;}}else{switch(funct[v]){case'closure':case'function':case'var':case'unused':warning("'{a}' used out of scope.",token,v);break;case'label':warning("'{a}' is a statement label.",token,v);break;case'outer':case true:break;default:if(s===true){funct[v]=true;}else if(typeof s!=='object'){if(option.undef){warning("'{a}' is undefined.",token,v);}else{implied[v]=true;globals[v]=true;funct[v]=true;}}else{switch(s[v]){case'function':case'var':case'unused':s[v]='closure';funct[v]='outer';break;case'closure':case'parameter':funct[v]='outer';break;case'label':warning("'!
{a}' is a statement label.",token,v);}}}}
+return this;},led:function(){error("Expected an operator and instead saw '{a}'.",nexttoken,nexttoken.value);}};type('(regex)',function(){return[this.id,this.value,this.flags];});delim('(endline)');delim('(begin)');delim('(end)').reach=true;delim('</').reach=true;delim('<![').reach=true;delim('<%');delim('<?');delim('<!');delim('<!--');delim('%>');delim('?>');delim('(error)').reach=true;delim('}').reach=true;delim(')');delim(']');delim(']]>').reach=true;delim('"').reach=true;delim("'").reach=true;delim(';');delim(':').reach=true;delim(',');reserve('else');reserve('case').reach=true;reserve('catch');reserve('default').reach=true;reserve('finally');reservevar('arguments');reservevar('eval');reservevar('false');reservevar('Infinity');reservevar('NaN');reservevar('null');reservevar('this');reservevar('true');reservevar('undefined');assignop('=','assign',20);assignop('+=','assignadd',20);assignop('-=','assignsub',20);assignop('*=','assignmult',20);assignop('/=','assigndiv',20).nu!
d=function(){error("A regular expression literal can be confused with '/='.");};assignop('%=','assignmod',20);bitwiseassignop('&=','assignbitand',20);bitwiseassignop('|=','assignbitor',20);bitwiseassignop('^=','assignbitxor',20);bitwiseassignop('<<=','assignshiftleft',20);bitwiseassignop('>>=','assignshiftright',20);bitwiseassignop('>>>=','assignshiftrightunsigned',20);infix('?',function(left){parse(10);advance(':');parse(10);},30);infix('||','or',40);infix('&&','and',50);bitwise('|','bitor',70);bitwise('^','bitxor',80);bitwise('&','bitand',90);relation('==',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'===','==');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'===',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'===',right.value);}
+return['==',left,right];});relation('===');relation('!=',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'!==','!=');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'!==',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'!==',right.value);}
+return['!=',left,right];});relation('!==');relation('<');relation('>');relation('<=');relation('>=');bitwise('<<','shiftleft',120);bitwise('>>','shiftright',120);bitwise('>>>','shiftrightunsigned',120);infix('in','in',120);infix('instanceof','instanceof',120);infix('+',function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);var right=parse(130);if(left&&right&&left.id==='(string)'&&right.id==='(string)'){left.value+=right.value;left.character=right.character;if(option.adsafe&&adsafe[left.value.toLowerCase()]===true){warning("Adsafe restricted word '{a}'.",left,left.value);}
+if(jx.test(left.value)){warning("JavaScript URL.",left);}
+return left;}
+return[this.id,left,right];},130);prefix('+','num');infix('-','sub',130);prefix('-','neg');infix('*','mult',140);infix('/','div',140);infix('%','mod',140);suffix('++','postinc');prefix('++','preinc');syntax['++'].exps=true;suffix('--','postdec');prefix('--','predec');syntax['--'].exps=true;prefix('delete',function(){var p=parse(0);if(p.id!=='.'&&p.id!=='['){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'.',nexttoken.value);}}).exps=true;prefix('~',function(){if(option.bitwise){warning("Unexpected '{a}'.",this,'~');}
+parse(150);return this;});prefix('!','not');prefix('typeof','typeof');prefix('new',function(){var c=parse(155),i;if(c){if(c.identifier){c['new']=true;switch(c.value){case'Object':warning("Use the object literal notation {}.",token);break;case'Array':warning("Use the array literal notation [].",token);break;case'Number':case'String':case'Boolean':warning("Do not use the {a} function as a constructor.",token,c.value);break;case'Function':if(!option.evil){warning("The Function constructor is eval.");}
+break;default:if(c.id!=='function'){i=c.value.substr(0,1);if(i<'A'||i>'Z'){warning("A constructor name should start with an uppercase letter.",token);}}}}else{if(c.id!=='.'&&c.id!=='['&&c.id!=='('){warning("Bad constructor.",token);}}}else{warning("Weird construction. Delete 'new'.",this);}
+adjacent(token,nexttoken);if(nexttoken.id==='('){advance('(');nospace();if(nexttoken.id!==')'){for(;;){parse(10);if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(')');nospace(prevtoken,token);}else{warning("Missing '()' invoking a constructor.");}
+return syntax['function'];});syntax['new'].exps=true;infix('.',function(left){adjacent(prevtoken,token);var m=identifier();if(typeof m==='string'){countMember(m);}
+if(!option.evil&&left&&left.value==='document'&&(m==='write'||m==='writeln')){warning("document.write can be a form of eval.",left);}
+this.left=left;this.right=m;return this;},160);infix('(',function(left){adjacent(prevtoken,token);nospace();var n=0;var p=[];if(left&&left.type==='(identifier)'){if(left.value.match(/^[A-Z](.*[a-z].*)?$/)){if(left.value!=='Number'&&left.value!=='String'&&left.value!=='Boolean'&&left.value!=='Date'){warning("Missing 'new' prefix when invoking a constructor.",left);}}}
+if(nexttoken.id!==')'){for(;;){p[p.length]=parse(10);n+=1;if(nexttoken.id!==','){break;}
+advance(',');nonadjacent(token,nexttoken);}}
+advance(')');nospace(prevtoken,token);if(typeof left==='object'){if(left.value==='parseInt'&&n===1){warning("Missing radix parameter.",left);}
+if(!option.evil){if(left.value==='eval'||left.value==='Function'){warning("eval is evil.",left);}else if(p[0]&&p[0].id==='(string)'&&(left.value==='setTimeout'||left.value==='setInterval')){warning("Implied eval is evil. Pass a function instead of a string.",left);}}
+if(!left.identifier&&left.id!=='.'&&left.id!=='['&&left.id!=='('){warning("Bad invocation.",left);}}
+return syntax['function'];},155).exps=true;prefix('(',function(){nospace();var v=parse(0);advance(')',this);nospace(prevtoken,token);return v;});infix('[',function(left){nospace();var e=parse(0),s;if(e&&e.type==='(string)'){countMember(e.value);if(ix.test(e.value)){s=syntax[e.value];if(!s||!s.reserved){warning("['{a}'] is better written in dot notation.",e,e.value);}}}
+advance(']',this);nospace(prevtoken,token);this.left=left;this.right=e;return this;},160);prefix('[',function(){if(nexttoken.id===']'){advance(']');return;}
+var b=token.line!==nexttoken.line;if(b){indent+=4;if(nexttoken.from===indent+4){indent+=4;}}
+for(;;){if(b&&token.line!==nexttoken.line){indentation();}
+parse(10);if(nexttoken.id===','){adjacent(token,nexttoken);advance(',');if(nexttoken.id===','||nexttoken.id===']'){warning("Extra comma.",token);}
+nonadjacent(token,nexttoken);}else{if(b){indent-=4;indentation();}
+advance(']',this);return;}}},160);(function(x){x.nud=function(){var i,s;if(nexttoken.id==='}'){advance('}');return;}
+var b=token.line!==nexttoken.line;if(b){indent+=4;if(nexttoken.from===indent+4){indent+=4;}}
+for(;;){if(b){indentation();}
+i=optionalidentifier(true);if(!i){if(nexttoken.id==='(string)'){i=nexttoken.value;if(ix.test(i)){s=syntax[i];}
+advance();}else if(nexttoken.id==='(number)'){i=nexttoken.value.toString();advance();}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'}',nexttoken.value);}}
+countMember(i);advance(':');nonadjacent(token,nexttoken);parse(10);if(nexttoken.id===','){adjacent(token,nexttoken);advance(',');if(nexttoken.id===','||nexttoken.id==='}'){warning("Extra comma.",token);}
+nonadjacent(token,nexttoken);}else{if(b){indent-=4;indentation();}
+advance('}',this);return;}}};x.fud=function(){error("Expected to see a statement and instead saw a block.");};})(delim('{'));function varstatement(){for(;;){nonadjacent(token,nexttoken);addlabel(identifier(),'unused');if(nexttoken.id==='='){nonadjacent(token,nexttoken);advance('=');nonadjacent(token,nexttoken);if(peek(0).id==='='){error("Variable {a} was not declared correctly.",nexttoken,nexttoken.value);}
+parse(20);}
+if(nexttoken.id!==','){return;}
+adjacent(token,nexttoken);advance(',');nonadjacent(token,nexttoken);}}
+stmt('var',varstatement);stmt('new',function(){error("'new' should not be used as a statement.");});function functionparams(){var i,t=nexttoken,p=[];advance('(');nospace();if(nexttoken.id===')'){advance(')');nospace(prevtoken,token);return;}
+for(;;){i=identifier();p.push(i);addlabel(i,'parameter');if(nexttoken.id===','){advance(',');nonadjacent(token,nexttoken);}else{advance(')',t);nospace(prevtoken,token);return p.join(', ');}}}
+function doFunction(i){var s=scope;scope=s.begetObject();funct={'(name)':i||'"'+anonname+'"','(line)':nexttoken.line+1,'(context)':funct};functions.push(funct);if(i){addlabel(i,'function');}
+funct['(params)']=functionparams();block(false);scope=s;funct=funct['(context)'];}
+blockstmt('function',function(){if(inblock){warning("Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.",token);}
+var i=identifier();adjacent(token,nexttoken);addlabel(i,'unused');doFunction(i);if(nexttoken.id==='('&&nexttoken.line===token.line){error("Function statements are not invocable. Wrap the function expression in parens.");}});prefix('function',function(){var i=optionalidentifier();if(i){adjacent(token,nexttoken);}else{nonadjacent(token,nexttoken);}
+doFunction(i);});blockstmt('if',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Assignment in control part.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);if(nexttoken.id==='else'){nonadjacent(token,nexttoken);advance('else');if(nexttoken.id==='if'||nexttoken.id==='switch'){statement();}else{block(true);}}});blockstmt('try',function(){var b,e;block(true);if(nexttoken.id==='catch'){advance('catch');nonadjacent(token,nexttoken);advance('(');e=nexttoken.value;if(nexttoken.type!=='(identifier)'){warning("Expected an identifier and instead saw '{a}'.",nexttoken,e);}else{addlabel(e,'unused');}
+advance();advance(')');block(false);b=true;}
+if(nexttoken.id==='finally'){advance('finally');block(false);return;}else if(!b){error("Expected '{a}' and instead saw '{b}'.",nexttoken,'catch',nexttoken.value);}});blockstmt('while',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Assignment in control part.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);}).labelled=true;reserve('with');blockstmt('switch',function(){var t=nexttoken;var g=false;advance('(');nonadjacent(this,t);nospace();this.condition=parse(20);advance(')',t);nospace(prevtoken,token);nonadjacent(token,nexttoken);t=nexttoken;advance('{');nonadjacent(token,nexttoken);indent+=4;this.cases=[];for(;;){switch(nexttoken.id){case'case':switch(verb){case'break':case'case':case'continue':case'return':case'switch':case'throw':break;default:warning("Expected a 'break' statement before 'case'.",token);}
+indentation(-4);advance('case');this.cases.push(parse(20));g=true;advance(':');verb='case';break;case'default':switch(verb){case'break':case'continue':case'return':case'throw':break;default:warning("Expected a 'break' statement before 'default'.",token);}
+indentation(-4);advance('default');g=true;advance(':');break;case'}':indent-=4;indentation();advance('}',t);if(this.cases.length===1||this.condition.id==='true'||this.condition.id==='false'){warning("This 'switch' should be an 'if'.",this);}
+return;case'(end)':error("Missing '{a}'.",nexttoken,'}');return;default:if(g){switch(token.id){case',':error("Each value should have its own case label.");return;case':':statements();break;default:error("Missing ':' on a case clause.",token);}}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'case',nexttoken.value);}}}}).labelled=true;stmt('debugger',function(){if(!option.debug){warning("All 'debugger' statements should be removed.");}});stmt('do',function(){block(true);advance('while');var t=nexttoken;nonadjacent(token,t);advance('(');nospace();parse(20);advance(')',t);nospace(prevtoken,token);}).labelled=true;blockstmt('for',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();if(peek(nexttoken.id==='var'?1:0).id==='in'){if(nexttoken.id==='var'){advance('var');addlabel(identifier(),'var');}else{advance();}
+advance('in');parse(20);advance(')',t);block(true);return;}else{if(nexttoken.id!==';'){if(nexttoken.id==='var'){advance('var');varstatement();}else{for(;;){parse(0);if(nexttoken.id!==','){break;}
+advance(',');}}}
+advance(';');if(nexttoken.id!==';'){parse(20);}
+advance(';');if(nexttoken.id===';'){error("Expected '{a}' and instead saw '{b}'.",nexttoken,')',';');}
+if(nexttoken.id!==')'){for(;;){parse(0);if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(')',t);nospace(prevtoken,token);block(true);}}).labelled=true;function nolinebreak(t){if(t.line!==nexttoken.line){warning("Line breaking error '{a}'.",t,t.id);}}
+stmt('break',function(){var v=nexttoken.value;nolinebreak(this);if(nexttoken.id!==';'){if(funct===true){warning("Put '{a}' and the statement it labels in a function.",nexttoken,v);}else if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+advance();}
+reachable('break');});stmt('continue',function(){var v=nexttoken.value;nolinebreak(this);if(nexttoken.id!==';'){if(funct===true){warning("Put '{a}' and the statement it labels in a function.",nexttoken,v);}else if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+advance();}
+reachable('continue');});stmt('return',function(){nolinebreak(this);if(nexttoken.id!==';'&&!nexttoken.reach){nonadjacent(token,nexttoken);parse(20);}
+reachable('return');});stmt('throw',function(){nolinebreak(this);nonadjacent(token,nexttoken);parse(20);reachable('throw');});reserve('abstract');reserve('boolean');reserve('byte');reserve('char');reserve('class');reserve('const');reserve('double');reserve('enum');reserve('export');reserve('extends');reserve('final');reserve('float');reserve('goto');reserve('implements');reserve('import');reserve('int');reserve('interface');reserve('long');reserve('native');reserve('package');reserve('private');reserve('protected');reserve('public');reserve('short');reserve('static');reserve('super');reserve('synchronized');reserve('throws');reserve('transient');reserve('void');reserve('volatile');function jsonValue(){function jsonObject(){var t=nexttoken;advance('{');if(nexttoken.id!=='}'){for(;;){if(nexttoken.id==='(end)'){error("Missing '}' to match '{' from line {a}.",nexttoken,t.line+1);}else if(nexttoken.id==='}'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){e!
rror("Unexpected comma.",nexttoken);}else if(nexttoken.id!=='(string)'){warning("Expected a string and instead saw {a}.",nexttoken,nexttoken.value);}
+advance();advance(':');jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance('}');}
+function jsonArray(){var t=nexttoken;advance('[');if(nexttoken.id!==']'){for(;;){if(nexttoken.id==='(end)'){error("Missing ']' to match '[' from line {a}.",nexttoken,t.line+1);}else if(nexttoken.id===']'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}
+jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(']');}
+switch(nexttoken.id){case'{':jsonObject();break;case'[':jsonArray();break;case'true':case'false':case'null':case'(number)':case'(string)':advance();break;case'-':advance('-');if(token.character!==nexttoken.from){warning("Unexpected space after '-'.",token);}
+adjacent(token,nexttoken);advance('(number)');break;default:error("Expected a JSON value.",nexttoken);}}
+var itself=function(s,o){option=o||{};JSLINT.errors=[];globals=standard.begetObject();scope=globals.begetObject();funct=true;functions=[];xmode=false;xtype='';stack=null;member={};membersOnly=null;implied={};inblock=false;lookahead=[];indent=0;jsonmode=false;warnings=0;lex.init(s);prereg=true;prevtoken=token=nexttoken=syntax['(begin)'];populateGlobals();try{advance();if(nexttoken.value.charAt(0)==='<'){xml();}else if(nexttoken.id==='{'||nexttoken.id==='['){option.laxbreak=true;jsonmode=true;jsonValue();}else{statements();}
+advance('(end)');}catch(e){if(e){JSLINT.errors.push({reason:e.message,line:e.line||nexttoken.line,character:e.character||nexttoken.from},null);}}
+return JSLINT.errors.length===0;};itself.report=function(option){var a=[],c,e,f,i,k,l,m='',n,o=[],s,v,cl,va,un,ou,gl,la;function detail(h,s){if(s.length){o.push('<div><i>'+h+'</i> '+
+s.sort().join(', ')+'</div>');}}
+s=[];for(k in implied){if(implied.hasOwnProperty(k)){s.push(k);}}
+k=JSLINT.errors.length;if(k||s.length>0){o.push('<div id=errors><i>Error:</i>');if(s.length>0){o.push('<p><i>Implied global:</i> '+s.sort().join(', ')+'</p>');c=true;}
+for(i=0;i<k;i+=1){c=JSLINT.errors[i];if(c){e=c.evidence||'';o.push('<p>Problem at line '+(c.line+1)+' character '+(c.character+1)+': '+c.reason.entityify()+'</p><p class=evidence>'+
+(e&&(e.length>80?e.substring(0,77)+'...':e).entityify())+'</p>');}}
+o.push('</div>');if(!c){return o.join('');}}
+if(!option){o.push('<div id=functions>');s=[];for(k in scope){if(scope.hasOwnProperty(k)){s.push(k);}}
+if(s.length===0){o.push('<div><i>No new global variables introduced.</i></div>');}else{o.push('<div><i>Global</i> '+s.join(', ')+'</div>');}
+for(i=0;i<functions.length;i+=1){f=functions[i];cl=[];va=[];un=[];ou=[];gl=[];la=[];for(k in f){if(f.hasOwnProperty(k)){v=f[k];switch(v){case'closure':cl.push(k);break;case'var':va.push(k);break;case'unused':un.push(k);break;case'label':la.push(k);break;case'outer':ou.push(k);break;case true:if(k!=='(context)'){gl.push(k);}
+break;}}}
+o.push('<br><div class=function><i>'+f['(line)']+'</i> '+
+(f['(name)']||'')+'('+
+(f['(params)']||'')+')</div>');detail('Closure',cl);detail('Variable',va);detail('Unused',un);detail('Label',la);detail('Outer',ou);detail('Global',gl);}
+for(k in member){if(typeof member[k]==='number'){a.push(k);}}
+if(a.length){a=a.sort();m='<br><div class=function>/*members ';l=10;for(i=0;i<a.length;i+=1){k=a[i];n=k.name();if(l+n.length>72){o.push(m+'</div>');m='<div> ';l=1;}
+l+=n.length+2;if(member[k]===1){n='<i>'+n+'</i>';}
+if(i<a.length-1){n+=', ';}
+m+=n;}
+o.push(m+' */</div>');}
+o.push('</div>');}
+return o.join('');};return itself;}();(function(a){if(!a[0]){print("Usage: jslint.js file.js");quit(1);}
+var input=readFile(a[0]);if(!input){print("jslint: Couldn't open file '"+a[0]+"'.");quit(1);}
+if(!JSLINT(input,{rhino:true,passfail:false})){for(var i=0;i<JSLINT.errors.length;i+=1){var e=JSLINT.errors[i];if(e){print('Lint at line '+(e.line+1)+' character '+
+(e.character+1)+': '+e.reason);print((e.evidence||'').replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"));print('');}}}else{print("jslint: No problems found in "+a[0]);quit();}})(arguments);
\ No newline at end of file
Added: trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,177 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.codehaus.plexus.util.FileUtils;
+
+public class AggregationTestCase extends TestCase {
+ private File dir_;
+
+ @Override
+ protected void setUp() throws Exception {
+ dir_ = File.createTempFile(this.getClass().getName(), "-test");
+ dir_.delete();
+ dir_.mkdirs();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ FileUtils.deleteDirectory(dir_);
+ }
+
+ public void test0to1() throws Exception {
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertFalse(target.output.exists());
+
+ target.includes = new String[]{};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertFalse(target.output.exists());
+
+ target.includes = new String[]{"**/*.js"};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertFalse(target.output.exists());
+ }
+
+
+ public void test1to1() throws Exception {
+ File f1 = new File(dir_, "01.js");
+ FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+ target.includes = new String[]{f1.getName()};
+
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f1), FileUtils.fileRead(target.output));
+ }
+
+ public void test2to1() throws Exception {
+ File f1 = new File(dir_, "01.js");
+ FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+ File f2 = new File(dir_, "02.js");
+ FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+
+ target.includes = new String[]{f1.getName(), f2.getName()};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+
+ target.output.delete();
+ target.includes = new String[]{"*.js"};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+// assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+ }
+
+ public void testNoDuplicateAggregation() throws Exception {
+ File f1 = new File(dir_, "01.js");
+ FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+ File f2 = new File(dir_, "02.js");
+ FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+
+ target.includes = new String[]{f1.getName(), f1.getName(), f2.getName()};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+
+ target.output.delete();
+ target.includes = new String[]{f1.getName(), "*.js"};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+ }
+
+ public void test2to1Order() throws Exception {
+ File f1 = new File(dir_, "01.js");
+ FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+ File f2 = new File(dir_, "02.js");
+ FileUtils.fileWrite(f2.getAbsolutePath(), "2");
+
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+
+ target.includes = new String[]{f2.getName(), f1.getName()};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f2) + FileUtils.fileRead(f1), FileUtils.fileRead(target.output));
+ }
+
+ public void test2to1WithNewLine() throws Exception {
+ File f1 = new File(dir_, "01.js");
+ FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+ File f2 = new File(dir_, "02.js");
+ FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+ target.insertNewLine = true;
+ target.includes = new String[]{f1.getName(), f2.getName()};
+
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f1) + "\n" + FileUtils.fileRead(f2) + "\n", FileUtils.fileRead(target.output));
+ }
+
+ public void testAbsolutePathFromInside() throws Exception {
+ File f1 = new File(dir_, "01.js");
+ FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+ File f2 = new File(dir_, "02.js");
+ FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+
+ target.includes = new String[]{f1.getAbsolutePath(), f2.getName()};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+ }
+
+ public void testAbsolutePathFromOutside() throws Exception {
+ File f1 = File.createTempFile("test-01", ".js");
+ try {
+ FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+ File f2 = new File(dir_, "02.js");
+ FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+ Aggregation target = new Aggregation();
+ target.output = new File(dir_, "output.js");
+
+ target.includes = new String[]{f1.getAbsolutePath(), f2.getName()};
+ assertFalse(target.output.exists());
+ target.run(dir_);
+ assertTrue(target.output.exists());
+ assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+ } finally {
+ f1.delete();
+ }
+ }
+}
Property changes on: trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Revision Author
Modified: trunk/cdk/pom.xml
===================================================================
--- trunk/cdk/pom.xml 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/cdk/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -27,9 +27,11 @@
</pluginManagement>
</build>
<modules>
+ <module>generator</module>
<module>maven-cdk-plugin</module>
- <module>generator</module>
+ <module>maven-javascript-plugin</module>
<module>maven-archetype-jsf-component</module>
<module>maven-archetype-jsfwebapp</module>
+
</modules>
</project>
\ No newline at end of file
Modified: trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java
===================================================================
--- trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -31,6 +31,7 @@
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
+import javax.portlet.PortletURL;
import javax.portlet.faces.Bridge;
import org.ajax4jsf.webapp.WebXml;
@@ -235,8 +236,17 @@
*/
@Override
protected String createActionUrl(Map<String, String> parameters){
- return "/ajax4jsfPortletBridge/actionUrl/do/nothitg";
- }
+ RenderResponse renderResponse = (RenderResponse) getPortletResponse();
+ PortletURL portletURL = renderResponse.createActionURL();
+ portletURL.setParameter(AbstractExternalContext.NAMESPACE_PARAMETER,
+ renderResponse.getNamespace());
+ for (Iterator<Map.Entry<String, String>> param = parameters.entrySet()
+ .iterator(); param.hasNext();) {
+ Map.Entry<String, String> parameter = param.next();
+ portletURL.setParameter(parameter.getKey(), parameter.getValue());
+ }
+ return portletURL.toString();
+ }
public String encodeResourceURL(String url) {
return encodeURL(url);
@@ -247,7 +257,7 @@
* @return
*/
protected String encodeURL(String url) {
- return getPortletResponse().encodeURL(url);
+ return getPortletResponse().encodeURL(url);
}
public String getAuthType() {
@@ -307,11 +317,11 @@
}
public void redirect(String url) throws IOException {
- if (null == url) {
+ if (null == url || url.length() < 0) {
throw new NullPointerException("Path to redirect is null");
}
PortalActionURL actionURL = new PortalActionURL(url);
- if(url.startsWith("#") || (!actionURL.isInContext(getRequestContextPath())) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
+ if(url.startsWith("#") || (!actionURL.isInContext(getRequestContextPath())) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
((ActionResponse) getResponse()).sendRedirect(url);
}
}
Modified: trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java
===================================================================
--- trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java 2007-12-11 23:30:42 UTC (rev 4755)
@@ -91,9 +91,11 @@
throw new NullPointerException("Path to redirect is null");
}
PortalActionURL actionURL = new PortalActionURL(url);
- if(!actionURL.isInContext(getRequestContextPath()) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
- throw new IllegalStateException(
- "Redirect to new url not at action phase");
+ if(!actionURL.isInContext(getRequestContextPath()) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
+ dispatch(url);
+
+// throw new IllegalStateException(
+// "Redirect to new url not at action phase");
}
// HACK - if page is in the context, just treat it as navigation case
}
@@ -109,14 +111,14 @@
Entry<String, String> parameter = param.next();
portletURL.setParameter(parameter.getKey(), parameter.getValue());
}
- return portletURL.toString();
+ return portletURL.toString();
}
public void dispatch(String path) throws IOException {
if (null == path) {
throw new NullPointerException("Path to new view is null");
}
- PortletRequestDispatcher dispatcher = getPortletContext()
+ PortletRequestDispatcher dispatcher = getPortletContext()
.getRequestDispatcher(path);
if (null == dispatcher) {
throw new IllegalStateException(
Modified: trunk/framework/impl/pom.xml
===================================================================
--- trunk/framework/impl/pom.xml 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/framework/impl/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -64,30 +64,17 @@
</resourceRoot>
</configuration>
</execution>
- <execution>
- <id>framevork-javascript</id>
- <phase>compile</phase>
- <goals>
- <goal>run</goal>
- </goals>
- <configuration>
- <tasks>
- <copy todir="target/classes/org/ajax4jsf" file="target/compressed/framework.pack.js"/>
- </tasks>
- </configuration>
- </execution>
</executions>
</plugin>
<plugin>
- <groupId>net.sf.alchim</groupId>
- <artifactId>yuicompressor-maven-plugin</artifactId>
+ <groupId>org.richfaces.cdk</groupId>
+ <artifactId>maven-javascript-plugin</artifactId>
+ <version>${project.version}</version>
<executions>
<execution>
<goals>
<goal>compress</goal>
</goals>
- </execution>
- </executions>
<configuration>
<nosuffix>false</nosuffix>
<outputDirectory>${project.build.directory}/compressed/</outputDirectory>
@@ -98,7 +85,7 @@
-->
<!-- insert new line after each concatenation (default: false) -->
<insertNewLine>true</insertNewLine>
- <output>${project.build.directory}/compressed/framework.pack.js</output>
+ <output>${project.build.outputDirectory}/org/ajax4jsf/framework.pack.js</output>
<!-- files to include, path relative to output's directory or absolute path-->
<includes>
<include>${project.build.directory}/compressed/org/ajax4jsf/javascript/scripts/prototype-min.js</include>
@@ -126,6 +113,25 @@
</resource>
</resources>
</configuration>
+
+ </execution>
+ <execution>
+ <id>jslint</id>
+ <goals>
+ <goal>jslint</goal>
+ </goals>
+ <phase>test</phase>
+ <configuration>
+ <includes><include>**/framework.pack.js</include></includes>
+ <resources>
+ <resource>
+ <directory>${project.build.outputDirectory}</directory>
+ </resource>
+ </resources>
+ </configuration>
+
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
Modified: trunk/framework/test/pom.xml
===================================================================
--- trunk/framework/test/pom.xml 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/framework/test/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -68,5 +68,10 @@
<version>2.2.1</version>
<optional>true</optional>
</dependency>
+ <dependency>
+ <groupId>rhino</groupId>
+ <artifactId>js</artifactId>
+ <version>1.6R7</version>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
Modified: trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml
===================================================================
--- trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -106,8 +106,8 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.richfaces.extensions</groupId>
- <artifactId>portlet</artifactId>
+ <groupId>org.richfaces.extensions.portletbridge</groupId>
+ <artifactId>portletbridge-api</artifactId>
<version>3.2.0-SNAPSHOT</version>
<exclusions>
<exclusion>
@@ -121,6 +121,21 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.richfaces.extensions.portletbridge</groupId>
+ <artifactId>portletbridge-impl</artifactId>
+ <version>3.2.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-impl</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-ui</artifactId>
<version>3.2.0-SNAPSHOT</version>
Modified: trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml
===================================================================
--- trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -19,7 +19,7 @@
-->
<expiration-cache>-0</expiration-cache>
<portlet-info>
- <title>Ajax Portlet</title>
+ <title>Seam Booking Example Portlet</title>
</portlet-info>
<supports>
<mime-type>text/html</mime-type>
Modified: trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml
===================================================================
--- trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml 2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml 2007-12-11 23:30:42 UTC (rev 4755)
@@ -35,7 +35,7 @@
<if-exists>overwrite</if-exists>
<parent-ref>default.default</parent-ref>
<window>
- <window-name>otherAjaxportletWindow</window-name>
+ <window-name>seamBookingPortletWindow</window-name>
<instance-ref>SeamBookingPortletInstance</instance-ref>
<default>true</default>
<region>center</region>
18 years, 5 months