Moves struts-sandbox
git-svn-id: https://svn.apache.org/repos/asf/struts/archive/trunk@1672656 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/struts-sandbox/extras/README.txt b/struts-sandbox/extras/README.txt
new file mode 100755
index 0000000..22ced79
--- /dev/null
+++ b/struts-sandbox/extras/README.txt
@@ -0,0 +1,106 @@
+
+ This project provides:
+ - alternate implementation of org.apache.struts.util.MessageResources (and factory)
+ - Struts plugin that configures the specified subclass of
+ org.apache.struts.plugins.resources.CommonsResources (and factory)
+
+ See the user documentation for further details about commons-resources beyond
+ what is provided here as a Plugin and Wrapper.
+
+ http://jakarta.apache.org/commons/resources/
+
+ The Resources plugin provides a configured MessageResources impl "as if" it
+ was specified above as a <message-resource ...
+
+ Available Properties and defaults:
+
+ Property Description Default
+ strutsPluginFactoryClass The factory class used to org.apache.struts.plugins.resources.CommonsResourcesFactory
+ configure this Module.
+
+ implFactoryClass The Jakarta Commons org.apache.commons.resources.impl.WebappPropertyResourcesFactory
+ Resources Factory to use.
+
+ implClass The Jakarta Commons org.apache.commons.resources.impl.WebappPropertyResources
+ Resources implementaion
+ to use.
+
+ bundle The properties file to (bundle is required)
+ load.
+
+ returnNull Determines whether a null false
+ is returned if the
+ specified key is not found
+
+ key Used in combination with null (not needed if null)
+ Struts internal constant
+ (Globals.MESSAGE_KEY) to
+ store the configured
+ MessageResources in the
+ ServletContext
+
+
+
+ Q. Why would I use this instead of the above?
+ A. Because with an overridden Factory and plugin of your own,
+ you can easily customize the default behaviour and unlike
+ the above, you will have direct access to the ActionServlet.
+
+
+
+ Below is an example of how to use this plugin with your Struts 1.1
+ implementation.
+
+
+ in your struts-config.xml....
+
+ (Note - the below is a direct copy from the modified struts-example.war
+ that demonstrates this plugin in action)
+
+...
+...
+ <!-- ========== Message Resources Definitions =========================== -->
+
+<!-- shown here using a subclass of MessageResources -->
+ <message-resources
+ factory="org.apache.struts.plugins.resources.CommonsResourcesFactory"
+ parameter="org.apache.struts.webapp.example.ApplicationResources"/>
+
+ <message-resources
+ factory="org.apache.struts.plugins.resources.CommonsResourcesFactory"
+ parameter="org.apache.struts.webapp.example.AlternateApplicationResources"
+ key="alternate"/>
+
+...
+
+
+
+(below is how you might do this with the plugin)
+
+ NOTE - the same rule applies where if you define multiple message-resources,
+ you must provide a unique key attribute or the later will overwrite
+ the former
+
+...
+ <!-- ========== Plug Ins Configuration ================================== -->
+...
+...
+ <plug-in className="org.apache.struts.plugins.resources.ResourcesPlugin">
+ <set-property property="bundle"
+ value="org.apache.struts.webapp.example.ApplicationResources"/>
+ </plug-in>
+
+ <plug-in className="org.apache.struts.plugins.resources.ResourcesPlugin">
+ <set-property property="strutsPluginFactoryClass"
+ value="org.apache.struts.plugins.resources.CommonsResourcesFactory"/>
+ <set-property property="implFactoryClass"
+ value="org.apache.commons.resources.impl.WebappPropertyResourcesFactory"/>
+ <set-property property="implClass"
+ value="org.apache.commons.resources.impl.WebappPropertyResources"/>
+ <set-property property="key"
+ value="alternate"/>
+ <set-property property="bundle"
+ value="org.apache.struts.webapp.example.AlternateApplicationResources"/>
+ </plug-in>
+...
+...
\ No newline at end of file
diff --git a/struts-sandbox/extras/project.properties b/struts-sandbox/extras/project.properties
new file mode 100755
index 0000000..03427c7
--- /dev/null
+++ b/struts-sandbox/extras/project.properties
@@ -0,0 +1,18 @@
+# -------------------------------------------------------------------
+# Copyright 2001-2004 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# -------------------------------------------------------------------
+
+maven.changelog.factory = org.apache.maven.svnlib.SvnChangeLogFactory
+
diff --git a/struts-sandbox/extras/project.xml b/struts-sandbox/extras/project.xml
new file mode 100755
index 0000000..25743aa
--- /dev/null
+++ b/struts-sandbox/extras/project.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<project>
+<!--
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+
+ <extend>../project.xml</extend>
+ <artifactId>struts-resources-plugin</artifactId>
+
+ <name>Struts Resources Plugin</name>
+
+ <package>org.apache.struts.plugins.resources</package>
+
+ <!-- ################################################################ -->
+ <!-- Project management section -->
+ <!-- ################################################################ -->
+
+
+ <shortDescription>
+ Plugin for providing MessageResources via commons-resources.
+ </shortDescription>
+
+ <description>
+ The Resources plugin allows any Struts-based web application (Struts version 1.1 and higher)
+ to integrate their existing app with
+ commons-resources (http://jakarta.apache.org/commons/resources/).
+
+ </description>
+ <repository>
+ <connection>scm|svn|http|//svn.apache.org/repos/asf/struts/plugins/trunk/resources</connection>
+ <developerConnection>scm|svn|https|//svn.apache.org/repos/asf/struts/plugins/trunk/resources</developerConnection>
+ <url>http://svn.apache.org/repos/asf/struts/plugins/trunk/resources</url>
+ </repository>
+
+ <versions />
+
+ <developers/>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>struts</groupId>
+ <artifactId>struts-action</artifactId>
+ <version>1.3.0-dev</version>
+ <properties>
+ <war.bundle>true</war.bundle>
+ <cactus.bundle>true</cactus.bundle>
+ </properties>
+ <url>http://struts.apache.org/</url>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-resources</groupId>
+ <artifactId>commons-resources</artifactId>
+ <version>1.0-dev</version>
+ <url>http://jakarta.apache.org/commons/resources/</url>
+ <properties>
+ <war.bundle>true</war.bundle>
+ </properties>
+ </dependency>
+
+ </dependencies>
+
+</project>
diff --git a/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/CommonsResources.java b/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/CommonsResources.java
new file mode 100755
index 0000000..db912be
--- /dev/null
+++ b/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/CommonsResources.java
@@ -0,0 +1,98 @@
+/*
+ * $Id$
+ *
+ * Copyright 2003,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.plugins.resources;
+
+import java.util.Locale;
+
+import javax.servlet.ServletContext;
+
+import org.apache.commons.resources.Resources;
+import org.apache.commons.resources.ResourcesFactory;
+import org.apache.commons.resources.impl.WebappResourcesFactoryBase;
+import org.apache.struts.util.MessageResources;
+import org.apache.struts.util.MessageResourcesFactory;
+import org.apache.struts.util.RequestUtils;
+
+/**
+ * Concrete subclass of <code>MessageResources</code> that wraps an
+ * instance of an impl of the supplied
+ * <code>org.apache.commons.resources.Resources</code> interface.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CommonsResources extends MessageResources{
+
+ protected Resources resources;
+
+ /**
+ * The default Locale for our environment.
+ */
+ protected Locale defaultLocale = Locale.getDefault();
+
+
+ public CommonsResources(MessageResourcesFactory factory,
+ ServletContext servletContext,
+ String implFactoryClass, String resourcesImpl,
+ String config, boolean returnNull) throws Exception{
+ super(factory, config, returnNull);
+
+ try {
+ ResourcesFactory commonsFactory =
+ (ResourcesFactory)RequestUtils.applicationInstance(implFactoryClass);
+ if (commonsFactory instanceof WebappResourcesFactoryBase) {
+ WebappResourcesFactoryBase factoryBase = (WebappResourcesFactoryBase) commonsFactory;
+ factoryBase.setServletContext(servletContext);
+ }
+ resources = commonsFactory.getResources(resourcesImpl, config);
+
+ } catch (Exception e) {
+ // log output
+ log.debug(e.getMessage());
+ throw e;
+ }
+ }
+
+ public CommonsResources(MessageResourcesFactory factory,
+ String config, boolean returnNull) {
+
+ super(factory, config, returnNull);
+
+ }
+
+ public CommonsResources(MessageResourcesFactory factory,
+ String config) {
+
+ super(factory, config);
+
+ }
+
+ public String getMessage(Locale locale, String key) {
+
+ // explicitly clear the cached on each call
+ // we will cache them down in the impl
+ // such that any subclass may provide it's
+ // own reload capabilities
+ formats.clear();
+ return resources.getString(key, locale, null);
+
+
+ }
+
+
+
+}
diff --git a/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/CommonsResourcesFactory.java b/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/CommonsResourcesFactory.java
new file mode 100755
index 0000000..e25e8de
--- /dev/null
+++ b/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/CommonsResourcesFactory.java
@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.plugins.resources;
+
+import javax.servlet.ServletContext;
+
+import org.apache.struts.util.MessageResources;
+import org.apache.struts.util.MessageResourcesFactory;
+
+
+/**
+ * Factory for <code>CommonsResources</code> instances. The
+ * configuration paramter for such instances is the base Java package
+ * name of the resources entries from which our keys and values will be
+ * loaded.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public class CommonsResourcesFactory extends MessageResourcesFactory {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Create and return a newly instansiated <code>MessageResources</code>.
+ * This method must be implemented by concrete subclasses.
+ *
+ * @param config Configuration parameter(s) for the requested bundle
+ */
+ public MessageResources createResources(String config) {
+
+ return new CommonsResources(this, config, this.returnNull);
+
+ }
+
+ public MessageResources createResources(ServletContext servletContext,
+ String implFactoryClass, String resourcesImpl, String config) throws Exception {
+
+ return new CommonsResources(this, servletContext, implFactoryClass, resourcesImpl,
+ config, this.returnNull);
+
+ }
+
+
+}
diff --git a/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/ResourcesPlugin.java b/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/ResourcesPlugin.java
new file mode 100755
index 0000000..8ab97c9
--- /dev/null
+++ b/struts-sandbox/extras/src/java/org/apache/struts/plugins/resources/ResourcesPlugin.java
@@ -0,0 +1,176 @@
+/*
+ * $Id$
+ *
+ * Copyright 2003,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.plugins.resources;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.Globals;
+import org.apache.struts.action.ActionServlet;
+import org.apache.struts.action.PlugIn;
+import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.util.MessageResources;
+import org.apache.struts.util.MessageResourcesFactory;
+
+
+/**
+ * <p>An implementation of <code>PlugIn</code> which
+ * can be configured to override the default Struts
+ * MessageResources implementation.
+ *
+ * This plugin was created after Struts 1.1, but is
+ * compatible with Struts 1.1 and Struts 1.2.
+ *
+ * @version $Rev$
+ * @see org.apache.struts.action.PlugIn
+ * @since Struts 1.2
+ */
+public class ResourcesPlugin implements PlugIn{
+
+ private static final Log log = LogFactory.getLog(ResourcesPlugin.class);
+
+ protected ActionServlet servlet = null;
+
+ protected ModuleConfig moduleConfig = null;
+
+ private String strutsPluginFactoryClass =
+ "org.apache.struts.plugins.resources.CommonsResourcesFactory";
+
+ private String implFactoryClass =
+ "org.apache.commons.resources.impl.WebappPropertyResourcesFactory";
+
+ private String implClass =
+ "org.apache.commons.resources.impl.WebappPropertyResources";
+
+ private String bundle;
+
+ private String key;
+
+ private boolean returnNull = false;
+
+
+ public boolean isReturnNull() {
+ return this.returnNull;
+ }
+
+
+ public void setReturnNull(boolean returnNull) {
+ this.returnNull = returnNull;
+ }
+
+
+ public void init(ActionServlet servlet, ModuleConfig config) {
+
+ this.servlet = servlet;
+ this.moduleConfig = config;
+
+ MessageResourcesFactory.setFactoryClass(this.strutsPluginFactoryClass);
+ MessageResourcesFactory factoryObject =
+ MessageResourcesFactory.createFactory();
+
+ MessageResources resources = null;
+ if (factoryObject instanceof CommonsResourcesFactory) {
+ CommonsResourcesFactory fctry =
+ (CommonsResourcesFactory) factoryObject;
+ try {
+ resources = fctry.createResources(servlet.getServletContext(),
+ this.implFactoryClass, this.implClass, bundle);
+ } catch (Exception e) {
+ // log output
+ log.debug(e.getMessage());
+ e.printStackTrace();
+ }
+ }else{
+ resources =
+ factoryObject.createResources(this.bundle);
+ }
+ resources.setReturnNull(this.returnNull);
+
+ String bundleKey = this.key;
+ bundleKey = (bundleKey == null ? "" : bundleKey);
+ String k = bundleKey + config.getPrefix();
+ if ("".equals(k))
+ k = Globals.MESSAGES_KEY;
+
+ servlet.getServletContext().setAttribute(k, resources);
+
+ }
+
+ public void destroy() {
+ this.servlet = null;
+ this.moduleConfig = null;
+ }
+
+ public String getImplFactoryClass() {
+ return this.implFactoryClass;
+ }
+
+
+ public void setImplFactoryClass(String implFactoryClass) {
+ this.implFactoryClass = implFactoryClass;
+ }
+
+
+ public String getStrutsPluginFactoryClass() {
+ return this.strutsPluginFactoryClass;
+ }
+
+
+ public void setStrutsPluginFactoryClass(String strutsPluginFactoryClass) {
+ this.strutsPluginFactoryClass = strutsPluginFactoryClass;
+ }
+
+
+ public String getBundle() {
+ return this.bundle;
+ }
+
+
+
+ public void setBundle(String bundle) {
+ this.bundle = bundle;
+ }
+
+
+
+ public String getKey() {
+ return this.key;
+ }
+
+
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+
+ public String getImplClass() {
+ return this.implClass;
+ }
+
+
+
+ public void setImplClass(String implClass) {
+ this.implClass = implClass;
+ }
+
+
+
+
+}
diff --git a/struts-sandbox/mailreader-course/COPYRIGHT.txt b/struts-sandbox/mailreader-course/COPYRIGHT.txt
new file mode 100644
index 0000000..886ace9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/COPYRIGHT.txt
@@ -0,0 +1,14 @@
+
+Copyright 2000-2006 Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/struts-sandbox/mailreader-course/LICENSE.txt b/struts-sandbox/mailreader-course/LICENSE.txt
new file mode 100644
index 0000000..dd5b3a5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/struts-sandbox/mailreader-course/README.txt b/struts-sandbox/mailreader-course/README.txt
new file mode 100644
index 0000000..2bd3f3f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/README.txt
@@ -0,0 +1,17 @@
+This directory is a whiteboard area for working on new material related to
+a set of training courses based on the MailReader example application.
+
+At this time, the material is being built directly with IDEA, and a standard
+build file is not yet available.
+
+For the time being, the dependencies required to build this material may be
+downloaded here:
+
+* http://people.apache.org/~husted/sandbox-action2-lib.zip
+
+For more about the materials under construction, visit
+
+* * http://StrutsUniversity.org/MailReader+Training+Course
+
+----------------------------------------------------------------------------
+
diff --git a/struts-sandbox/mailreader-course/STATUS.txt b/struts-sandbox/mailreader-course/STATUS.txt
new file mode 100644
index 0000000..b1fb5a1
--- /dev/null
+++ b/struts-sandbox/mailreader-course/STATUS.txt
@@ -0,0 +1,58 @@
+==============================================================================
+MALREADER TRAINING COURSE WHITEBOARD STATUS
+------------------------------------------------------------------------------
+Project:
+ http://struts.apache.org/
+Wiki:
+ http://strutsuniversity.org/MailReader+Training+Course
+Mailing Lists:
+ http://struts.apache.org/mail.html -- dev@ with [COURSE] keyword
+Source Code:
+ http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/mailreader-course/
+Committers:
+ Ted Husted [add your name here].
+Status File:
+ http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/mailreader-course/STATUS.txt?view=markup
+
+COURSE SUMMARY
+
+The MailReader Training Course for Struts 2 is a step-by-step introduction to
+the next generation of Struts applications. After completing the course, you
+will be equipped to create and maintain basic Struts applications, including
+all necessary client-side and server-side programming.
+
+Presentations are reinforced by workshops designed to explore common problems
+and best-practice solutions. This course is intended for developers who want
+field-savvy advice on how to get your applications working the "Struts 2 Way".
+
+COURSE OBJECTIVES
+
+ * Present and apply MVC application architecture
+ * Build a working web application
+ * Understand how to unit test web applications
+ * Explore key best practices
+ * Use popular extensions to increase productivity
+
+AUDIENCE
+
+Developers and programmers who want to learn about web application
+development using Apache Struts Action frameworks.
+
+PREREQUISITES
+
+To benefit from the training course, students should have experience
+programming with Java along with a basic knowledge of html. Experience with a
+modern Java IDE, such as NetBeans, Eclipse, or IDEA, is also beneficial.
+
+SOURCE CODE
+
+An example of each completed lab is provided in a folder named for the
+corresponding use case.
+
+SESSSION NOTES
+
+Notes for the presentation introducing each workshop are maintained on the
+Struts University wiki. For the notes and a session outline see:
+
+ * http://StrutsUniversity.org/MailReader+Training+Course
+==============================================================================
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/MainMenu.jsp b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/MainMenu.jsp
new file mode 100644
index 0000000..efed1c9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/MainMenu.jsp
@@ -0,0 +1,10 @@
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<html>
+<head>
+ <title>Main Menu</title>
+</head>
+
+<body>
+<h3>Welcome <bean:write name="RegisterForm" property="username"/> !</h3>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/RegisterForm.jsp b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/RegisterForm.jsp
new file mode 100644
index 0000000..c7549ec
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/RegisterForm.jsp
@@ -0,0 +1,14 @@
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+<html:html>
+ <head>
+ <title>Register Form</title>
+ </head>
+
+ <body>
+ <html:errors/>
+ <html:form action="/RegisterSave">
+ Username: <html:text property="username"/><br>
+ <html:submit value="Register"/>
+ </html:form>
+ </body>
+</html:html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-config.xml b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-config.xml
new file mode 100644
index 0000000..f3584e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-config.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="RegisterForm"
+ type="org.apache.struts.validator.DynaValidatorForm">
+ <form-property
+ name="username"
+ type="java.lang.String"/>
+ </form-bean>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="/Register"
+ name="RegisterForm"
+ forward="/RegisterForm.jsp"
+ validate="false"/>
+
+ <action path="/RegisterSave"
+ extends="/Register"
+ forward="/MainMenu.jsp"/>
+
+ </action-mappings>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-form.tld b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-form.tld
new file mode 100644
index 0000000..c956ee8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-form.tld
@@ -0,0 +1,1698 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
+<taglib>
+ <tlibversion>1.0</tlibversion>
+ <jspversion>1.1</jspversion>
+ <shortname>form</shortname>
+ <tag>
+ <name>base</name>
+ <tagclass>org.apache.struts.taglib.html.BaseTag</tagclass>
+ <bodycontent>empty</bodycontent>
+ </tag>
+ <tag>
+ <name>button</name>
+ <tagclass>org.apache.struts.taglib.html.ButtonTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>cancel</name>
+ <tagclass>org.apache.struts.taglib.html.CancelTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>checkbox</name>
+ <tagclass>org.apache.struts.taglib.html.CheckboxTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>errors</name>
+ <tagclass>org.apache.struts.taglib.html.ErrorsTag</tagclass>
+ <bodycontent>empty</bodycontent>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>file</name>
+ <tagclass>org.apache.struts.taglib.html.FileTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>accept</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>form</name>
+ <tagclass>org.apache.struts.taglib.html.FormTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>enctype</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>focus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onreset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onsubmit</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>type</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>hidden</name>
+ <tagclass>org.apache.struts.taglib.html.HiddenTag</tagclass>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>html</name>
+ <tagclass>org.apache.struts.taglib.html.HtmlTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>xhtml</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>image</name>
+ <tagclass>org.apache.struts.taglib.html.ImageTag</tagclass>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>path</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>isKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>link</name>
+ <tagclass>org.apache.struts.taglib.html.LinkTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>linkName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>multibox</name>
+ <tagclass>org.apache.struts.taglib.html.MultiboxTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>option</name>
+ <tagclass>org.apache.struts.taglib.html.OptionTag</tagclass>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>options</name>
+ <tagclass>org.apache.struts.taglib.html.OptionsTag</tagclass>
+ <bodycontent>empty</bodycontent>
+ <attribute>
+ <name>collection</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>labelName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>labelProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>password</name>
+ <tagclass>org.apache.struts.taglib.html.PasswordTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>radio</name>
+ <tagclass>org.apache.struts.taglib.html.RadioTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>reset</name>
+ <tagclass>org.apache.struts.taglib.html.ResetTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>rewrite</name>
+ <tagclass>org.apache.struts.taglib.html.RewriteTag</tagclass>
+ <bodycontent>empty</bodycontent>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>select</name>
+ <tagclass>org.apache.struts.taglib.html.SelectTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>multiple</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>submit</name>
+ <tagclass>org.apache.struts.taglib.html.SubmitTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>text</name>
+ <tagclass>org.apache.struts.taglib.html.TextTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+ <tag>
+ <name>textarea</name>
+ <tagclass>org.apache.struts.taglib.html.TextareaTag</tagclass>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>cols</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>rows</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+</taglib>
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-html.tld b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-html.tld
new file mode 100644
index 0000000..c44843b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/struts-html.tld
@@ -0,0 +1,8752 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
+ "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+<taglib>
+ <tlib-version>1.3</tlib-version>
+ <jsp-version>1.2</jsp-version>
+ <short-name>html</short-name>
+ <uri>http://struts.apache.org/tags-html</uri>
+ <description>
+ <![CDATA[
+ <p>
+ This taglib contains tags used to create struts
+ input forms, as well as other tags generally useful
+ in the creation of HTML-based user interfaces.
+ </p>
+
+ <p>Many of the tags in this tag library will throw a
+ <code>JspException</code> at runtime when they are utilized incorrectly
+ (such as when you specify an invalid combination of tag attributes). JSP
+ allows you to declare an "error page" in the <code><%@ page %></code>
+ directive. If you wish to process the actual exception that caused the
+ problem, it is passed to the error page as a request attribute under key
+ <code>org.apache.struts.action.EXCEPTION</code>.</p>
+ ]]>
+ </description>
+ <tag>
+ <name>base</name>
+ <tag-class>org.apache.struts.taglib.html.BaseTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><base></code> Element</strong></p>
+
+ <p>Renders an HTML <code><base></code> element with an
+ <code>href</code> attribute pointing to the absolute location of
+ the enclosing JSP page. This tag is valid only when nested inside
+ an HTML <code><head></code> element.</p>
+
+ <p>This tag is useful because it allows you to use relative URL
+ references in the page that are calculated based on the URL of the
+ page itself, rather than the URL to which the most recent submit
+ took place (which is where the browser would normally resolve
+ relative references against).</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target for this base reference.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>server</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The server name to use instead of request.getServerName().</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ref</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The reference from which the base uri will created. Possible values are:
+ </p>
+ <ul>
+ <li><code>page</code> - The base uri will be the jsp page location. (default)</li>
+ <li><code>site</code> - The base uri will be the application context path.</li>
+ </ul>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.3</dd></dl>
+
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>button</name>
+ <tag-class>org.apache.struts.taglib.html.ButtonTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render A Button Input Field</strong></p>
+
+ <p>
+ Renders an HTML <input> element of type
+ <code>button</code>, populated from the specified value or the
+ content of this tag body. This tag is only valid when nested
+ inside a form tag body.
+ </p>
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> if this input field should be
+ disabled.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Click"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>cancel</name>
+ <tag-class>org.apache.struts.taglib.html.CancelTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Cancel Button
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type submit. This tag is only
+ valid when nested inside a form tag body. Pressing of this submit
+ button causes the action servlet to bypass calling the associated
+ form bean validate() method. The action is called normally.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ <strong>WARNING</strong> - If you set this attribute to a
+ value other than the default, this will <em>NOT</em> be
+ recognized as the cancel key by the Struts controller servlet
+ or the <code>Action.isCancelled()</code> method. You will
+ need to do your own cancel detection.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Cancel"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>checkbox</name>
+ <tag-class>org.apache.struts.taglib.html.CheckboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, populated from the specified
+ value or the specified property of the bean associated
+ with our current form. This tag is only valid when
+ nested inside a form tag body.</p>
+
+ <p><strong>NOTE</strong>: The underlying property value
+ associated with this field should be of type <code>boolean</code>,
+ and any <code>value</code> you specify should correspond to one
+ of the Strings that indicate a true value ("true", "yes", or
+ "on"). If you wish to utilize a set of related String values,
+ consider using the <code>multibox</code> tag.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize unchecked checkboxes, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement setting the corresponding
+ boolean property to <code>false</code> in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted. If not specified,
+ the value "on" will be returned.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>errors</name>
+ <tag-class>org.apache.struts.taglib.html.ErrorsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated error messages.
+ </strong></p>
+
+ <p>Displays a set of error messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, an <code>ActionErrors</code>
+ object, a String, or a String array in request scope. If
+ such a bean is not found, nothing will be rendered.</p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name, with optional
+ definitions of message keys specified in the following
+ attributes:</p>
+ <ul>
+ <li><strong>header</strong> - Text that will be rendered
+ before the error messages list. Typically, this message text
+ will end with <code><ul></code> to start the
+ error messages list (default "errors.header").</li>
+ <li><strong>footer</strong> - Text that will be rendered
+ after the error messages list. Typically, this message text
+ will begin with <code></ul></code> to end the error
+ messages list (default "errors.footer").</li>
+ <li><strong>prefix</strong> - Text that will be rendered
+ before each individual error in the list (default "errors.prefix").</li>
+ <li><strong>suffix</strong> - Text that will be rendered
+ after each individual error in the list (default "errors.suffix").</li>
+ </ul>
+
+ <p>See the <code>messages</code> tag for an alternative to this tag that
+ does not rely on HTML in your <code>MessageResources</code>.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of error messages has finished.
+ Defaults to "errors.footer" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of error messages begins.
+ Defaults to "errors.header" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>prefix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before an error message.
+ Defaults to "errors.prefix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which error messages should be
+ displayed. If not specified, all error messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>suffix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after an error message.
+ Defaults to "errors.suffix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>file</name>
+ <tag-class>org.apache.struts.taglib.html.FileTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A File Select Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type file, defaulting to
+ the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ <p>
+ As with the corresponding HTML <input> element, the
+ enclosing form element must specify "POST" for the <code>method</code>
+ attribute, and "multipart/form-data" for the <code>enctype</code>
+ attribute. For example:
+ </p>
+ <pre>
+ <html:form method="POST" enctype="multipart/form-data">
+ <html:file property="theFile" />
+ </html:form></pre>
+
+ <p>
+ WARNING: In order to correctly recognize uploaded files, the ActionForm bean
+ associated with this form must include a statement setting the corresponding
+ org.apache.struts.upload.FormFile property to null in the reset() method.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>accept</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Comma-delimited set of content types that the server you submit to
+ knows how to process. This list can be used by the client browser
+ to limit the set of file options that is made available for selection.
+ If not specified, no content type list will be sent.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. This is ignored
+ by most browsers. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Size of the file selection box to be displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ <strong>NOTE</strong>: When setting this to some value, whether
+ intentional or as the result (for example) of validation errors
+ forcing the user back to the original jsp, this value is ignored
+ by most browsers (for security reasons).
+ This means that your users will have to re-select any previously
+ selected files when submitting the form. Opera web browser will
+ prompt the user so they have a chance to abort the submit.
+ </p>
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value or body content (if any) if
+ property is not specified]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>form</name>
+ <tag-class>org.apache.struts.taglib.html.FormTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Define An Input Form
+ </strong></p>
+
+ <p>
+ Renders an HTML <form> element whose contents are described
+ by the body content of this tag. The form implicitly interacts
+ with the specified request scope or session scope bean to populate
+ the input fields with the current property values from the bean.
+ </p>
+ <p>
+ The form bean is located, and created if necessary, based on the
+ form bean specification for the associated <code>ActionMapping</code>.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this form will be submitted. This
+ value is also used to select the ActionMapping we are
+ assumed to be processing, from which we can identify
+ the appropriate form bean and scope. If a value is not
+ provided, the original URI (servletPath) for the request is
+ used. </p>
+
+ <p>If you are using extension mapping for selecting the
+ controller servlet, this value should be equal to the
+ <code>path</code> attribute of the corresponding
+ <code><action></code> element, optionally
+ followed by the correct extension suffix.</p>
+
+ <p>If you are using path mapping to select the
+ controller servlet, this value should be exactly equal
+ to the <code>path</code> attribute of the corresponding
+ <code><action></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>acceptCharset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The list of character encodings for input data that the server should
+ accept.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ disabled.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>enctype</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The content encoding to be used to submit this form, if the method
+ is POST. This must be set to "multipart/form-data" if you are using
+ the file tag to enable file upload. If not specified, the browser
+ default (normally "application/x-www-form-urlencoded") is used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The field name (among the fields on this form) to which initial
+ focus will be assigned with a JavaScript function. If not specified,
+ no special JavaScript for this purpose will be rendered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focusIndex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If the focus field is a field array, such as a radio button group, you can
+ specify the index in the array to receive focus.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The HTTP method that will be used to submit this request
+ (GET, POST). [POST]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onreset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is reset.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onsubmit</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ read only.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The form's focus <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHMTL mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Window target to which this form is submitted, such as
+ for use in framed presentations.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>frame</name>
+ <tag-class>org.apache.struts.taglib.html.FrameTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML frame element</strong></p>
+
+
+ <p>Renders an HTML <code><frame></code> element
+ with processing for the <code>src</code> attribute that is
+ identical to that performed by the <code><html:link></code>
+ tag for the <code>href</code> attribute. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies.</p>
+
+ <p>The base URL for this frame is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and application
+ prefix.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ logical name of a global Action that contains the actual
+ content-relative URI of the destination of this transfer.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameborder</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should a frame border be generated around this frame (1)
+ or not (0)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Value for the <code>name</code> attribute of the rendered
+ <code><frame></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>longdesc</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>URI of a long description of the frame. This description
+ should supplement the short description provided by the
+ <code>title</code> attribute, and may be particularly useful
+ for non-visual user agents.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginheight</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its top and bottom margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginwidth</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its left and right margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>noresize</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Should users be disallowed from resizing the frame?
+ (true, false).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scrolling</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should scroll bars be created unconditionally (yes),
+ never (no), or only when needed (auto)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>hidden</name>
+ <tag-class>org.apache.struts.taglib.html.HiddenTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Hidden Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type hidden, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>write</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Should the value of this field also be rendered to the
+ response page to make it visible, in addition to creating
+ an HTML type="hidden" element? By default, only the
+ hidden element is created.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>html</name>
+ <tag-class>org.apache.struts.taglib.html.HtmlTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><html></code> Element</strong></p>
+
+ <p>Renders an HTML <code><html></code> element with
+ language attributes extracted from the user's current Locale
+ object, if there is one.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>lang</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Renders a lang attribute with the locale stored in the user's session. If not
+ found in the session, the language from the <code>Accept-Language</code>
+ HTTP header is used. If still not found, the default language for the server
+ is used.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>xhtml</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> in order to render
+ <code>xml:lang</code> and <code>xmlns</code> attributes
+ on the generated <code>html</code> element. This also
+ causes all other html tags to render as XHTML 1.0 (the
+ <html:xhtml/> tag has a similar purpose).
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>image</name>
+ <tag-class>org.apache.struts.taglib.html.ImageTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render an input tag of type "image"
+ </strong></p>
+
+
+ <p>Renders an HTML <code><input></code> tag of type
+ "image". The base URL for this image is calculated directly
+ based on the value specified in the <code>src</code> or
+ <code>page</code> attributes, or indirectly by looking up a
+ message resource string based on the <code>srcKey</code> or
+ <code>pageKey</code> attributes. You <strong>must</strong>
+ specify exactly one of these attributes.</p>
+
+ <p>If you would like to obtain the coordinates of the mouse
+ click that submitted this request, see the information below
+ on the <code>property</code> attribute.</p>
+
+ <p>This tag is only valid when nested inside a form tag body.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alignment option for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width (in pixels) of the border around this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The session attribute key for the Locale used to select
+ internationalized messages. If not specified, defaults to the
+ Struts standard value.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under
+ the mouse pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under
+ the mouse pointer but the pointer was moved outside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not
+ under the mouse pointer but the pointer is moved inside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path of the image for this
+ input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ module-relative path of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The property name of this image tag. The parameter names
+ for the request will appear as "property.x" and "property.y",
+ the x and y representing the coordinates of the mouse click
+ for the image. A way of retrieving these values through a
+ form bean is to define getX(), getY(), setX(), and setY()
+ methods, and specify your property as a blank string
+ (property="").</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The value that will be submitted if this image button
+ is pressed.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>img</name>
+ <tag-class>org.apache.struts.taglib.html.ImgTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML img tag</strong></p>
+
+
+ <p>Renders an HTML <code><img></code> element with
+ the image at the specified URL. Like the link tag, URL
+ rewriting will be applied automatically to the value
+ specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> to maintain session state
+ in the absence of cookies. This will allow dynamic
+ generation of an image where the content displayed for this
+ image will be taken from the attributes of this tag.</p>
+
+ <p>The base URL for this image is calculated directly based on
+ the value specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> or <code>page</code>,
+ or indirectly by looking up a message resource string based on
+ the <code>srcKey</code> or <code>pageKey</code> attributes.
+ You <strong>must</strong> specify exactly one of these
+ attributes.</p>
+
+ <p>Normally, the <code>src</code>, <code>page</code>, or
+ <code>action</code> that you specify will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the <code>src</code> URL --
+ specify a single parameter with the <code>paramId</code>
+ attribute (at its associated attributes to select the value),
+ or specify the <code>name</code> (and optional
+ <code>property</code>) attributes to select a
+ <code>java.util.Map</code> bean that contains one or more
+ parameter ids and corresponding values.</p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter will be called on the JSP bean identified
+ by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ <code>src</code> URL. The value associated with each key
+ must be either a String or a String array representing the
+ parameter value(s), or an object whose toString() method
+ will be called. If a String array is specified, more than
+ one value for the same query parameter name will be
+ created.</p>
+
+ <p>You can specify the alternate text for this image (which
+ most browsers display as pop-up text block when the user
+ hovers the mouse over this image) either directly, through
+ the <code>alt</code> attribute, or indirectly from a message
+ resources bundle, using the <code>bundle</code> and
+ <code>altKey</code> attributes.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Where the image is aligned to. Can be one of the
+ following attributes:</p>
+ <ul>
+ <li>left - left justify, wrapping text on right</li>
+ <li>right -right justify, wrapping test on left</li>
+ <li>top - aligns the image with the top of the text on
+ the same row</li>
+ <li>middle - aligns the image's vertical center with the
+ text base line</li>
+ <li>bottom - aligns the image with the bottom of the
+ text's base line</li>
+ <li>texttop - aligns the image's top with that of the
+ text font on the same line</li>
+ <li>absmiddle - aligns the image's vertical center with the
+ absolute center of the text</li>
+ <li>absbottom - aligns the image with the absolute bottom
+ of the text font on the same row</li>
+ </ul>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>And alternative text to be displayed in browsers that
+ don't support graphics. Also used often as type of
+ context help over images.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the border surrounding the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>height</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The height of the image being displayed. This parameter
+ is very nice to specify (along with <code>width</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>hspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of horizontal spacing between the icon and
+ the text. The text may be in the same paragraph, or
+ be wrapped around the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>imageName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scriptable name to be defined within this page, so
+ that you can reference it with intra-page scripts. In other
+ words, the value specified here will render a "name" element
+ in the generated image tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ismap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the server-side map that this image belongs
+ to.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request or session Locale attribute used
+ to look up internationalized messages.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated src URL. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path, starting with a slash, of
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>page</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify either the <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the module-relative path for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The action, starting with a slash, that will render
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>action</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify the <code>action</code>,
+ <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this src URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the src URL. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this image will be transferred from
+ This image may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. This value will be used unmodified (other
+ than potential URL rewriting) as the value of the "src"
+ attribute in the rendered tag. You <strong>must</strong>
+ specify either the <code>page</code> attribute or the
+ <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the URL of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>usemap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the map as defined within this page for
+ mapping hot-spot areas of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>vspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of vertical spacing between the icon and
+ the text, above and below.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>width</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the image being displayed. This parameter
+ is very nice to specify (along with <code>height</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>javascript</name>
+ <tag-class>
+ org.apache.struts.taglib.html.JavascriptValidatorTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render JavaScript validation based on the
+ validation rules loaded by the ValidatorPlugIn.
+ </strong></p>
+
+ <p>
+ Render JavaScript validation based on the
+ validation rules loaded by the <code>ValidatorPlugIn</code>.
+ The set of validation rules that should be generated is based
+ on the formName attribute passed in, which should match
+ the name attribute of the form element in the xml file.
+ </p>
+ <p>
+ The dynamicJavascript and staticJavascript attributes
+ default to true, but if dynamicJavascript is set to <code>true</code>
+ and staticJavascript is set to <code>false</code> then only
+ the dynamic JavaScript will be rendered. If dynamicJavascript
+ is set to <code>false</code>
+ and staticJavascript is set to <code>true</code> then only
+ the static JavaScript will be rendered which can then be put in
+ separate JSP page so the browser can cache the static JavaScript.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>cdata</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ If set to "true" and XHTML has been enabled, the JavaScript will
+ be wrapped in a CDATA section to prevent XML parsing. The default is
+ "true" to comply with the W3C's recommendation.
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>dynamicJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the dynamic JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>formName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The key (form name) to retrieve a specific
+ set of validation rules. If "dynamicJavascript" is set
+ to <code>true</code> and formName is missing or is not
+ recognized by the <code>ValidatorPlugIn</code>, a
+ JspException will be thrown.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The alternate JavaScript method name to be used
+ instead of the of the default. The default is
+ 'validate' concatenated in front of
+ the key (form name) passed in (ex: validateRegistrationForm).
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ <description>
+ <![CDATA[
+ <p>
+ The current page of a set of validation rules
+ if the page attribute for the field element
+ in the xml file is in use.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHTML mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The src attribute's value when defining
+ the html script element.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>staticJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the static JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>htmlComment</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to enclose the javascript
+ with HTML comments. This attribute is ignored in XHTML
+ mode because the script would be deleted by the XML parser. See
+ the cdata attribute for details on hiding scripts from XML
+ parsers.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>link</name>
+ <tag-class>org.apache.struts.taglib.html.LinkTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML anchor or hyperlink</strong></p>
+
+
+ <p>Renders an HTML <code><a></code> element as an
+ anchor definition (if "linkName" is specified) or as a
+ hyperlink to the specified URL. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies. The content displayed for this
+ hyperlink will be taken from the body of this tag.</p>
+
+ <p>The base URL for this hyperlink is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there. If the forward is module-relative then
+ it must point to an action and NOT to a page.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ name of a <code>Action</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and module
+ prefix.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then indexed parameter with name from indexId attribute
+ will be added to the query string. Indexed parameter looks like
+ "index[32]". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By this attribute different name for the indexed parameter can be
+ specified. Take a look to the "indexed" attribute for details.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>linkName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The anchor name to be defined within this page, so that
+ you can reference it with intra-page hyperlinks. In other
+ words, the value specified here will render a "name" element
+ in the generated anchor tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element loses input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse double click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse move event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse out event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse over event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute,
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The tab order (ascending positive integers) for
+ this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target in which the resource requested by this
+ hyperlink will be displayed, for example in a framed
+ presentation.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>messages</name>
+ <tag-class>org.apache.struts.taglib.html.MessagesTag</tag-class>
+ <tei-class>org.apache.struts.taglib.html.MessagesTei</tei-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated messages.
+ </strong></p>
+
+ <p>Displays a set of messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, <code>ActionErrors</code> object, a String,
+ or a String array in any scope. If
+ such a bean is not found, nothing will be rendered. The messages are
+ placed into the page scope in the body of this tag where they can be displayed
+ by standard JSP methods. (For example: <code><bean:write></code>,<code><c:out></code>)
+ </p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>id</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ The name of a page scope JSP bean that will contain the current
+ element of the collection of messages on each iteration, if it is not
+ <code>null</code>.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the bean in any scope under which our messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which messages should be
+ displayed. If not specified, all messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of messages begins.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of messages has finished.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>message</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By default the tag will retrieve the bean it will
+ iterate over from the <code>Globals.ERROR_KEY</code> constant string,
+ but if this attribute is set to 'true' the bean
+ will be retrieved from the <code>Globals.MESSAGE_KEY</code>
+ constant string. Also if this is set to 'true', any value
+ assigned to the name attribute will be ignored.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>multibox</name>
+ <tag-class>org.apache.struts.taglib.html.MultiboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, whose "checked" status is
+ initialized based on whether the specified value
+ matches one of the elements of the underlying
+ property's array of current values. This element is
+ useful when you have large numbers of checkboxes, and
+ prefer to combine the values into a single
+ array-valued property instead of multiple boolean
+ properties. This tag is only valid when nested
+ inside a form tag body.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where none of the associated checkboxes
+ are selected, the <code>ActionForm</code> bean
+ associated with this form must include a statement
+ setting the corresponding array to zero length in the
+ <code>reset()</code> method.</p>
+
+ <p>The value to be returned to the server, if this checkbox is
+ selected, must be defined by one of the following methods:</p>
+ <ul>
+ <li>Specify a <code>value</code> attribute, whose contents will
+ be used literally as the value to be returned.</li>
+ <li>Specify no <code>value</code> attribute, and the nested
+ body content of this tag will be used as the value to be
+ returned.</li>
+ </ul>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>option</name>
+ <tag-class>org.apache.struts.taglib.html.OptionTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Option
+ </strong></p>
+
+ <p>Render an HTML <code><option></code> element,
+ representing one of the choices for an enclosing
+ <code><select></code> element. The text displayed to the
+ user comes from either the body of this tag, or from a message
+ string looked up based on the <code>bundle</code>,
+ <code>locale</code>, and <code>key</code> attributes.</p>
+
+ <p>If the value of the corresponding bean property matches the
+ specified value, this option will be marked selected. This tag
+ is only valid when nested inside a
+ <code><html:select></code> tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this option should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>key</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If specified, defines the message key to be looked up in
+ the resource bundle specified by <code>bundle</code> for
+ the text displayed to the user for this option. If not
+ specified, the text to be displayed is taken from the body
+ content of this tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attributes key for the Locale instance to use
+ for looking up the message specified by the
+ <code>key</code> attribute. If not specified, uses the
+ standard Struts session attribute name.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to be submitted for this field if this option is
+ selected by the user.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>options</name>
+ <tag-class>org.apache.struts.taglib.html.OptionsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:optionsCollection></code> elements.</p>
+
+ <p>This tag operates in one of two major modes, depending on
+ whether or not the <code>collection</code> attribute is
+ specified. If the <code>collection</code> attribute is
+ included, the following rules apply:</p>
+ <ul>
+ <li>The <strong>collection</strong> attribute is interpreted
+ as the name of a JSP bean, in some scope, that itself
+ represents a collection of individual beans, one per option
+ value to be rendered.</li>
+ <li>The <strong>property</strong> attribute is interpreted as
+ the name of a property of the individual beans included in
+ the collection, and is used to retrieve the value that will
+ be returned to the server if this option is selected.</li>
+ <li>The <strong>labelProperty</strong> attribute is interpreted
+ as the name of a property of the individual beans included
+ in the collection, and is used to retrieve the label that
+ will be displayed to the user for this option. If the
+ <code>labelProperty</code> attribute is not specified, the
+ property named by the <code>property</code> attribute will
+ be used to select both the value returned to the server and
+ the label displayed to the user for this option.</li>
+ </ul>
+
+ <p>If the <code>collection</code> attribute is not specified,
+ the rules described in the remainder of this section apply.</p>
+
+ <p>The collection of values actually selected depends on the presence or
+ absence of the <code>name</code> and <code>property</code> attributes. The
+ following combinations are allowed:</p>
+ <ul>
+ <li><em>Only <code>name</code> is specified</em> - The value of this attribute
+ is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>property</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>name</code> and <code>property</code> are specified</em> -
+ The value of the <code>name</code> attribute identifies a JSP bean
+ in some scope. The value of the <code>property</code> attribute is the
+ name of some property of that bean which will return the collection.</li>
+ </ul>
+
+ <p>The collection of labels displayed to the user can be the same as the
+ option values themselves, or can be different, depending on the presence or
+ absence of the <code>labelName</code> and <code>labelProperty</code>
+ attributes. If this feature is used, the collection of labels must contain
+ the same number of elements as the corresponding collection of values.
+ The following combinations are allowed:</p>
+ <ul>
+ <li><em>Neither <code>labelName</code> nor <code>labelProperty</code> is
+ specified</em> - The labels will be the same as the option values
+ themselves.</li>
+ <li><em>Only <code>labelName</code> is specified</em> - The value of this
+ attribute is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>labelProperty</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>labelName</code> and <code>labelProperty</code> are
+ specified</em> - The value of the <code>labelName</code> attribute
+ identifies a JSP bean in some scope. The value of the
+ <code>labelProperty</code> attribute is the name of some property of
+ that bean which will return the collection.</li>
+ </ul>
+
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>collection</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) which is itself a
+ Collection of other beans, each of which has properties
+ named by the "property" and "labelProperty" attributes
+ that are used to retrieve the value and label for each
+ option, respectively.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of labels to
+ be displayed to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the labelName
+ attribute, that will return the collection of labels to be displayed
+ to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of
+ values to be returned to the server for these options. If not
+ specified, the form bean associated with our form is assumed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of values to returned
+ to the server for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>optionsCollection</name>
+ <tag-class>
+ org.apache.struts.taglib.html.OptionsCollectionTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:options></code> elements.</p>
+
+ <p>This tag operates on a collection of beans, where each bean
+ has a <strong>label</strong> property and a <strong>value</strong>
+ property. The actual names of these properties can be configured
+ using the <code>label</code> and <code>value</code> attributes
+ of this tag.</p>
+
+ <p>This tag differs from the <code><html:options></code> tag
+ in that it makes more consistent use of the <code>name</code> and
+ <code>property</code> attributes, and allows the collection to be
+ more easily obtained from the enclosing form bean.</p>
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>label</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the label to be rendered for each option. Defaults to "label".
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of objects to be
+ rendered for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the value to be rendered for each option. Defaults to "value".
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>password</name>
+ <tag-class>org.apache.struts.taglib.html.PasswordTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Password Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type password, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>redisplay</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Boolean flag indicating whether or not existing values
+ will be redisplayed if they exist. Even though the
+ redisplayed value will be shown as asterisks on the
+ visible HTML page, the cleartext of the actual password
+ value will be visible though the "Show Page Source"
+ menu option of the client browser. You may wish to
+ set this value to <code>false</code> on login pages.
+ Defaults to <code>true</code> for consistency with
+ all other form tags that redisplay their contents.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any)]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>radio</name>
+ <tag-class>org.apache.struts.taglib.html.RadioTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Radio Button Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type radio, populated from
+ the specified property of the bean associated with our current form.
+ This tag is only valid when nested inside a form tag body.
+ </p>
+ <p>
+ If an iterator is used to render a series of radio tags, the
+ idName attribute may be used to specify the name of the bean
+ exposed by the iterator. In this case, the value attribute is
+ used as the name of a property on the idName bean that returns
+ the value of the radio tag in this iteration.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The corresponding bean property for this radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>idName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the bean (in some scope) that will return the
+ value of the radio tag. Usually exposed
+ by an iterator. When the idName attribute is
+ present, the value attribute is used as the name of the
+ property on the idName bean that will return the
+ value of the radio tag for this iteration.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>reset</name>
+ <tag-class>org.apache.struts.taglib.html.ResetTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Reset Button Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type reset.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the input field that will be generated.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button.
+ [Body of this tag (if any), or "Reset"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>rewrite</name>
+ <tag-class>org.apache.struts.taglib.html.RewriteTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an URI</strong></p>
+
+ <p>Renders a request URI based on exactly the same rules
+ as the <code><a href="#link">link</a></code> tag does,
+ but without creating
+ the <code><a></code> hyperlink. This value is useful
+ when you want to generate a string constant for use by
+ a JavaScript procedure.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.0</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>select</name>
+ <tag-class>org.apache.struts.taglib.html.SelectTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Element
+ </strong></p>
+
+ <p>Renders an HTML <select> element, associated
+ with a bean property specified by our attributes. This
+ tag is only valid when nested inside a form tag body.
+ </p>
+
+ <p>This tag operates in two modes, depending upon the
+ state of the <code>multiple</code> attribute, which
+ affects the data type of the associated property you
+ should use:</p>
+ <ul>
+ <li><em>multiple="true" IS NOT selected</em> -
+ The corresponding property should be a scalar
+ value of any supported data type.</li>
+ <li><em>multiple="true" IS selected</em> -
+ The corresponding property should be an array
+ of any supported data type.</li>
+ </ul>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where no selection at all is made, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement resetting the scalar property
+ to a default value (if <code>multiple</code> is not
+ set), or the array property to zero length (if
+ <code>multiple</code> is set) in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>multiple</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If set to any arbitrary value, the rendered
+ select element will support
+ multiple selections.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ to determine which option should be pre-selected when rendering
+ this input field. If not specified, the bean associated with
+ the enclosing <code><html:form></code> tag is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of available options displayed at one time.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to compare with for marking an option selected.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>submit</name>
+ <tag-class>org.apache.struts.taglib.html.SubmitTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Submit Button
+ </strong></p>
+
+ Renders an HTML <input> element of type <code>submit</code>.
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the button label.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>text</name>
+ <tag-class>org.apache.struts.taglib.html.TextTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render An Input Field of Type text</strong></p>
+
+ <p>Render an input field of type text. This tag is only valid when
+ nested inside a form tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>textarea</name>
+ <tag-class>org.apache.struts.taglib.html.TextareaTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Textarea
+ </strong></p>
+
+ Render a textarea element. This tag is only valid when nested
+ inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>cols</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of columns to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>rows</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of rows to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>xhtml</name>
+ <tag-class>org.apache.struts.taglib.html.XhtmlTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render HTML tags as XHTML</strong></p>
+
+ <p>
+ Using this tag in a page tells all other html taglib tags
+ to render themselves as XHTML 1.0. This is useful
+ when composing pages with JSP includes or Tiles.
+ <html:html xhtml="true"> has a similar effect. This
+ tag has no attributes; you use it like this: <html:xhtml/>.
+ </p>
+ <p>
+ <strong>Note</strong>: Included pages do not inherit the rendering
+ style of the including page. Each JSP fragment or Tile must use this
+ tag to render as XHTML.
+ </p>
+ ]]>
+ </description>
+ </tag>
+</taglib>
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..dbcaab7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-1-src/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+
+ <!-- Action Servlet Configuration -->
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
+ <init-param>
+ <param-name>config</param-name>
+ <param-value>/WEB-INF/struts-config.xml</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <!-- Action Servlet Mapping -->
+ <servlet-mapping>
+ <servlet-name>action</servlet-name>
+ <url-pattern>*.do</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/META-INF/context.xml b/struts-sandbox/mailreader-course/struts/lab-1-2-src/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts/lab-1-2-src/WEB-INF/web.xml
new file mode 100644
index 0000000..3afc996
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/WEB-INF/web.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+</web-app>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/MainMenu.jsp b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/MainMenu.jsp
new file mode 100644
index 0000000..8431b18
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/MainMenu.jsp
@@ -0,0 +1,16 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<html>
+<head>
+ <title>Main Menu</title>
+</head>
+
+<body>
+<h3>Main Menu Options for <bean:write name="RegisterForm"
+ property="fullName"/></h3>
+<ul>
+ <li>[TODO] Edit Profile</li>
+ <li>[TODO] Logout</li>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/RegisterForm.jsp b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/RegisterForm.jsp
new file mode 100644
index 0000000..5eb1fbe
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/RegisterForm.jsp
@@ -0,0 +1,89 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<html:html>
+ <head>
+ <title>Register Form</title>
+ </head>
+
+ <body>
+
+ <html:errors/>
+
+ <html:form action="/RegisterSave">
+ <table border="0" width="100%">
+
+ <tr>
+ <th align="right">
+ Username:
+ </th>
+ <td align="left">
+ <html:text property="username" size="16" maxlength="16"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Password:
+ </th>
+ <td align="left">
+ <html:password property="password" size="16"
+ maxlength="16"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Confirm Password:
+ </th>
+ <td align="left">
+ <html:password property="password2" size="16"
+ maxlength="16"/>
+ </td>
+ </tr>
+
+ <!-- Lab 1-2: Insert remaining fields from use case -->
+
+ <tr>
+ <th align="right">
+ Fullname:
+ </th>
+ <td align="left">
+ <html:text property="fullName" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ From Address:
+ </th>
+ <td align="left">
+ <html:text property="fromAddress" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Reply To Address:
+ </th>
+ <td align="left">
+ <html:text property="replyToAddress" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">
+ <html:submit value="SAVE"/>
+ </td>
+ <td align="left">
+ <html:reset value="RESET"/>
+
+ <html:cancel value="CANCEL"/>
+ </td>
+ </tr>
+
+ </table>
+ </html:form>
+
+ </body>
+</html:html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/Register-configure.xml b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/Register-configure.xml
new file mode 100644
index 0000000..acc53f2
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/Register-configure.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="RegisterForm"
+ type="org.apache.struts.validator.DynaValidatorForm">
+ <form-property
+ name="username"
+ type="java.lang.String"/>
+ <form-property
+ name="password"
+ type="java.lang.String"/>
+ <form-property
+ name="password2"
+ type="java.lang.String"/>
+ <!-- Lab 1-2: Insert remaining fields from use case -->
+ <form-property
+ name="fullName"
+ type="java.lang.String"/>
+ <form-property
+ name="fromAddress"
+ type="java.lang.String"/>
+ <form-property
+ name="replyToAddress"
+ type="java.lang.String"/>
+ </form-bean>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="/Register"
+ name="RegisterForm"
+ forward="/RegisterForm.jsp"
+ validate="false"/>
+
+ <action path="/RegisterSave"
+ name="RegisterForm"
+ validate="true"
+ input="/Register.do"
+ forward="/MainMenu.jsp"/>
+
+ </action-mappings>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/Register-validate.xml b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/Register-validate.xml
new file mode 100644
index 0000000..4d06c11
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/Register-validate.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">
+
+<form-validation>
+
+ <formset>
+ <form name="RegisterForm">
+
+ <field property="username" depends="required">
+ <arg position="0" key="username.label"/>
+ </field>
+
+ <field property="password" depends="required">
+ <arg position="0" key="password.label"/>
+ </field>
+
+ <field property="password2" depends="required,validwhen">
+ <arg position="0" key="password2.label"/>
+ <var>
+ <var-name>test</var-name>
+ <var-value>(*this* == password)</var-value>
+ </var>
+ </field>
+
+ <!-- Lab 1-2: Insert remaining fields from use case -->
+
+ <field property="fullName"
+ depends="required">
+ <arg key="fullName.label"/>
+ </field>
+
+ <field property="fromAddress"
+ depends="required,email">
+ <arg key="fromAddress.label"/>
+ </field>
+
+ <field property="replyToAddress"
+ depends="email">
+ <arg key="replyToAddress.label"/>
+ </field>
+
+ </form>
+ </formset>
+</form-validation>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/classes/MessageResources.properties b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/classes/MessageResources.properties
new file mode 100644
index 0000000..07743ed
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/classes/MessageResources.properties
@@ -0,0 +1,14 @@
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+errors.required={0} is required.
+errors.email={0} is not a valid email address.
+username.label=Username
+password.label=Password
+password2.label=Confirm Password
+# Lab 1-2: Insert remaining fields from use case
+fullName.label=Full Name
+fromAddress.label=From Address
+replyToAddress.label=Reply To Address
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/struts-config.xml b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/struts-config.xml
new file mode 100644
index 0000000..aaeac03
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/struts-config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <message-resources
+ parameter="MessageResources"/>
+
+ <plug-in
+ className="org.apache.struts.validator.ValidatorPlugIn">
+ <set-property
+ property="pathnames"
+ value="/org/apache/struts/validator/validator-rules.xml,
+ /WEB-INF/Register-validate.xml"
+ />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/struts-html.tld b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/struts-html.tld
new file mode 100644
index 0000000..c44843b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/struts-html.tld
@@ -0,0 +1,8752 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
+ "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+<taglib>
+ <tlib-version>1.3</tlib-version>
+ <jsp-version>1.2</jsp-version>
+ <short-name>html</short-name>
+ <uri>http://struts.apache.org/tags-html</uri>
+ <description>
+ <![CDATA[
+ <p>
+ This taglib contains tags used to create struts
+ input forms, as well as other tags generally useful
+ in the creation of HTML-based user interfaces.
+ </p>
+
+ <p>Many of the tags in this tag library will throw a
+ <code>JspException</code> at runtime when they are utilized incorrectly
+ (such as when you specify an invalid combination of tag attributes). JSP
+ allows you to declare an "error page" in the <code><%@ page %></code>
+ directive. If you wish to process the actual exception that caused the
+ problem, it is passed to the error page as a request attribute under key
+ <code>org.apache.struts.action.EXCEPTION</code>.</p>
+ ]]>
+ </description>
+ <tag>
+ <name>base</name>
+ <tag-class>org.apache.struts.taglib.html.BaseTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><base></code> Element</strong></p>
+
+ <p>Renders an HTML <code><base></code> element with an
+ <code>href</code> attribute pointing to the absolute location of
+ the enclosing JSP page. This tag is valid only when nested inside
+ an HTML <code><head></code> element.</p>
+
+ <p>This tag is useful because it allows you to use relative URL
+ references in the page that are calculated based on the URL of the
+ page itself, rather than the URL to which the most recent submit
+ took place (which is where the browser would normally resolve
+ relative references against).</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target for this base reference.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>server</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The server name to use instead of request.getServerName().</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ref</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The reference from which the base uri will created. Possible values are:
+ </p>
+ <ul>
+ <li><code>page</code> - The base uri will be the jsp page location. (default)</li>
+ <li><code>site</code> - The base uri will be the application context path.</li>
+ </ul>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.3</dd></dl>
+
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>button</name>
+ <tag-class>org.apache.struts.taglib.html.ButtonTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render A Button Input Field</strong></p>
+
+ <p>
+ Renders an HTML <input> element of type
+ <code>button</code>, populated from the specified value or the
+ content of this tag body. This tag is only valid when nested
+ inside a form tag body.
+ </p>
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> if this input field should be
+ disabled.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Click"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>cancel</name>
+ <tag-class>org.apache.struts.taglib.html.CancelTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Cancel Button
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type submit. This tag is only
+ valid when nested inside a form tag body. Pressing of this submit
+ button causes the action servlet to bypass calling the associated
+ form bean validate() method. The action is called normally.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ <strong>WARNING</strong> - If you set this attribute to a
+ value other than the default, this will <em>NOT</em> be
+ recognized as the cancel key by the Struts controller servlet
+ or the <code>Action.isCancelled()</code> method. You will
+ need to do your own cancel detection.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Cancel"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>checkbox</name>
+ <tag-class>org.apache.struts.taglib.html.CheckboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, populated from the specified
+ value or the specified property of the bean associated
+ with our current form. This tag is only valid when
+ nested inside a form tag body.</p>
+
+ <p><strong>NOTE</strong>: The underlying property value
+ associated with this field should be of type <code>boolean</code>,
+ and any <code>value</code> you specify should correspond to one
+ of the Strings that indicate a true value ("true", "yes", or
+ "on"). If you wish to utilize a set of related String values,
+ consider using the <code>multibox</code> tag.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize unchecked checkboxes, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement setting the corresponding
+ boolean property to <code>false</code> in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted. If not specified,
+ the value "on" will be returned.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>errors</name>
+ <tag-class>org.apache.struts.taglib.html.ErrorsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated error messages.
+ </strong></p>
+
+ <p>Displays a set of error messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, an <code>ActionErrors</code>
+ object, a String, or a String array in request scope. If
+ such a bean is not found, nothing will be rendered.</p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name, with optional
+ definitions of message keys specified in the following
+ attributes:</p>
+ <ul>
+ <li><strong>header</strong> - Text that will be rendered
+ before the error messages list. Typically, this message text
+ will end with <code><ul></code> to start the
+ error messages list (default "errors.header").</li>
+ <li><strong>footer</strong> - Text that will be rendered
+ after the error messages list. Typically, this message text
+ will begin with <code></ul></code> to end the error
+ messages list (default "errors.footer").</li>
+ <li><strong>prefix</strong> - Text that will be rendered
+ before each individual error in the list (default "errors.prefix").</li>
+ <li><strong>suffix</strong> - Text that will be rendered
+ after each individual error in the list (default "errors.suffix").</li>
+ </ul>
+
+ <p>See the <code>messages</code> tag for an alternative to this tag that
+ does not rely on HTML in your <code>MessageResources</code>.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of error messages has finished.
+ Defaults to "errors.footer" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of error messages begins.
+ Defaults to "errors.header" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>prefix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before an error message.
+ Defaults to "errors.prefix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which error messages should be
+ displayed. If not specified, all error messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>suffix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after an error message.
+ Defaults to "errors.suffix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>file</name>
+ <tag-class>org.apache.struts.taglib.html.FileTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A File Select Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type file, defaulting to
+ the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ <p>
+ As with the corresponding HTML <input> element, the
+ enclosing form element must specify "POST" for the <code>method</code>
+ attribute, and "multipart/form-data" for the <code>enctype</code>
+ attribute. For example:
+ </p>
+ <pre>
+ <html:form method="POST" enctype="multipart/form-data">
+ <html:file property="theFile" />
+ </html:form></pre>
+
+ <p>
+ WARNING: In order to correctly recognize uploaded files, the ActionForm bean
+ associated with this form must include a statement setting the corresponding
+ org.apache.struts.upload.FormFile property to null in the reset() method.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>accept</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Comma-delimited set of content types that the server you submit to
+ knows how to process. This list can be used by the client browser
+ to limit the set of file options that is made available for selection.
+ If not specified, no content type list will be sent.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. This is ignored
+ by most browsers. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Size of the file selection box to be displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ <strong>NOTE</strong>: When setting this to some value, whether
+ intentional or as the result (for example) of validation errors
+ forcing the user back to the original jsp, this value is ignored
+ by most browsers (for security reasons).
+ This means that your users will have to re-select any previously
+ selected files when submitting the form. Opera web browser will
+ prompt the user so they have a chance to abort the submit.
+ </p>
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value or body content (if any) if
+ property is not specified]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>form</name>
+ <tag-class>org.apache.struts.taglib.html.FormTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Define An Input Form
+ </strong></p>
+
+ <p>
+ Renders an HTML <form> element whose contents are described
+ by the body content of this tag. The form implicitly interacts
+ with the specified request scope or session scope bean to populate
+ the input fields with the current property values from the bean.
+ </p>
+ <p>
+ The form bean is located, and created if necessary, based on the
+ form bean specification for the associated <code>ActionMapping</code>.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this form will be submitted. This
+ value is also used to select the ActionMapping we are
+ assumed to be processing, from which we can identify
+ the appropriate form bean and scope. If a value is not
+ provided, the original URI (servletPath) for the request is
+ used. </p>
+
+ <p>If you are using extension mapping for selecting the
+ controller servlet, this value should be equal to the
+ <code>path</code> attribute of the corresponding
+ <code><action></code> element, optionally
+ followed by the correct extension suffix.</p>
+
+ <p>If you are using path mapping to select the
+ controller servlet, this value should be exactly equal
+ to the <code>path</code> attribute of the corresponding
+ <code><action></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>acceptCharset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The list of character encodings for input data that the server should
+ accept.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ disabled.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>enctype</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The content encoding to be used to submit this form, if the method
+ is POST. This must be set to "multipart/form-data" if you are using
+ the file tag to enable file upload. If not specified, the browser
+ default (normally "application/x-www-form-urlencoded") is used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The field name (among the fields on this form) to which initial
+ focus will be assigned with a JavaScript function. If not specified,
+ no special JavaScript for this purpose will be rendered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focusIndex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If the focus field is a field array, such as a radio button group, you can
+ specify the index in the array to receive focus.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The HTTP method that will be used to submit this request
+ (GET, POST). [POST]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onreset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is reset.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onsubmit</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ read only.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The form's focus <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHMTL mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Window target to which this form is submitted, such as
+ for use in framed presentations.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>frame</name>
+ <tag-class>org.apache.struts.taglib.html.FrameTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML frame element</strong></p>
+
+
+ <p>Renders an HTML <code><frame></code> element
+ with processing for the <code>src</code> attribute that is
+ identical to that performed by the <code><html:link></code>
+ tag for the <code>href</code> attribute. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies.</p>
+
+ <p>The base URL for this frame is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and application
+ prefix.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ logical name of a global Action that contains the actual
+ content-relative URI of the destination of this transfer.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameborder</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should a frame border be generated around this frame (1)
+ or not (0)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Value for the <code>name</code> attribute of the rendered
+ <code><frame></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>longdesc</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>URI of a long description of the frame. This description
+ should supplement the short description provided by the
+ <code>title</code> attribute, and may be particularly useful
+ for non-visual user agents.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginheight</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its top and bottom margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginwidth</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its left and right margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>noresize</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Should users be disallowed from resizing the frame?
+ (true, false).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scrolling</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should scroll bars be created unconditionally (yes),
+ never (no), or only when needed (auto)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>hidden</name>
+ <tag-class>org.apache.struts.taglib.html.HiddenTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Hidden Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type hidden, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>write</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Should the value of this field also be rendered to the
+ response page to make it visible, in addition to creating
+ an HTML type="hidden" element? By default, only the
+ hidden element is created.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>html</name>
+ <tag-class>org.apache.struts.taglib.html.HtmlTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><html></code> Element</strong></p>
+
+ <p>Renders an HTML <code><html></code> element with
+ language attributes extracted from the user's current Locale
+ object, if there is one.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>lang</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Renders a lang attribute with the locale stored in the user's session. If not
+ found in the session, the language from the <code>Accept-Language</code>
+ HTTP header is used. If still not found, the default language for the server
+ is used.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>xhtml</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> in order to render
+ <code>xml:lang</code> and <code>xmlns</code> attributes
+ on the generated <code>html</code> element. This also
+ causes all other html tags to render as XHTML 1.0 (the
+ <html:xhtml/> tag has a similar purpose).
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>image</name>
+ <tag-class>org.apache.struts.taglib.html.ImageTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render an input tag of type "image"
+ </strong></p>
+
+
+ <p>Renders an HTML <code><input></code> tag of type
+ "image". The base URL for this image is calculated directly
+ based on the value specified in the <code>src</code> or
+ <code>page</code> attributes, or indirectly by looking up a
+ message resource string based on the <code>srcKey</code> or
+ <code>pageKey</code> attributes. You <strong>must</strong>
+ specify exactly one of these attributes.</p>
+
+ <p>If you would like to obtain the coordinates of the mouse
+ click that submitted this request, see the information below
+ on the <code>property</code> attribute.</p>
+
+ <p>This tag is only valid when nested inside a form tag body.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alignment option for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width (in pixels) of the border around this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The session attribute key for the Locale used to select
+ internationalized messages. If not specified, defaults to the
+ Struts standard value.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under
+ the mouse pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under
+ the mouse pointer but the pointer was moved outside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not
+ under the mouse pointer but the pointer is moved inside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path of the image for this
+ input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ module-relative path of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The property name of this image tag. The parameter names
+ for the request will appear as "property.x" and "property.y",
+ the x and y representing the coordinates of the mouse click
+ for the image. A way of retrieving these values through a
+ form bean is to define getX(), getY(), setX(), and setY()
+ methods, and specify your property as a blank string
+ (property="").</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The value that will be submitted if this image button
+ is pressed.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>img</name>
+ <tag-class>org.apache.struts.taglib.html.ImgTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML img tag</strong></p>
+
+
+ <p>Renders an HTML <code><img></code> element with
+ the image at the specified URL. Like the link tag, URL
+ rewriting will be applied automatically to the value
+ specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> to maintain session state
+ in the absence of cookies. This will allow dynamic
+ generation of an image where the content displayed for this
+ image will be taken from the attributes of this tag.</p>
+
+ <p>The base URL for this image is calculated directly based on
+ the value specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> or <code>page</code>,
+ or indirectly by looking up a message resource string based on
+ the <code>srcKey</code> or <code>pageKey</code> attributes.
+ You <strong>must</strong> specify exactly one of these
+ attributes.</p>
+
+ <p>Normally, the <code>src</code>, <code>page</code>, or
+ <code>action</code> that you specify will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the <code>src</code> URL --
+ specify a single parameter with the <code>paramId</code>
+ attribute (at its associated attributes to select the value),
+ or specify the <code>name</code> (and optional
+ <code>property</code>) attributes to select a
+ <code>java.util.Map</code> bean that contains one or more
+ parameter ids and corresponding values.</p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter will be called on the JSP bean identified
+ by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ <code>src</code> URL. The value associated with each key
+ must be either a String or a String array representing the
+ parameter value(s), or an object whose toString() method
+ will be called. If a String array is specified, more than
+ one value for the same query parameter name will be
+ created.</p>
+
+ <p>You can specify the alternate text for this image (which
+ most browsers display as pop-up text block when the user
+ hovers the mouse over this image) either directly, through
+ the <code>alt</code> attribute, or indirectly from a message
+ resources bundle, using the <code>bundle</code> and
+ <code>altKey</code> attributes.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Where the image is aligned to. Can be one of the
+ following attributes:</p>
+ <ul>
+ <li>left - left justify, wrapping text on right</li>
+ <li>right -right justify, wrapping test on left</li>
+ <li>top - aligns the image with the top of the text on
+ the same row</li>
+ <li>middle - aligns the image's vertical center with the
+ text base line</li>
+ <li>bottom - aligns the image with the bottom of the
+ text's base line</li>
+ <li>texttop - aligns the image's top with that of the
+ text font on the same line</li>
+ <li>absmiddle - aligns the image's vertical center with the
+ absolute center of the text</li>
+ <li>absbottom - aligns the image with the absolute bottom
+ of the text font on the same row</li>
+ </ul>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>And alternative text to be displayed in browsers that
+ don't support graphics. Also used often as type of
+ context help over images.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the border surrounding the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>height</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The height of the image being displayed. This parameter
+ is very nice to specify (along with <code>width</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>hspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of horizontal spacing between the icon and
+ the text. The text may be in the same paragraph, or
+ be wrapped around the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>imageName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scriptable name to be defined within this page, so
+ that you can reference it with intra-page scripts. In other
+ words, the value specified here will render a "name" element
+ in the generated image tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ismap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the server-side map that this image belongs
+ to.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request or session Locale attribute used
+ to look up internationalized messages.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated src URL. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path, starting with a slash, of
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>page</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify either the <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the module-relative path for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The action, starting with a slash, that will render
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>action</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify the <code>action</code>,
+ <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this src URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the src URL. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this image will be transferred from
+ This image may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. This value will be used unmodified (other
+ than potential URL rewriting) as the value of the "src"
+ attribute in the rendered tag. You <strong>must</strong>
+ specify either the <code>page</code> attribute or the
+ <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the URL of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>usemap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the map as defined within this page for
+ mapping hot-spot areas of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>vspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of vertical spacing between the icon and
+ the text, above and below.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>width</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the image being displayed. This parameter
+ is very nice to specify (along with <code>height</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>javascript</name>
+ <tag-class>
+ org.apache.struts.taglib.html.JavascriptValidatorTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render JavaScript validation based on the
+ validation rules loaded by the ValidatorPlugIn.
+ </strong></p>
+
+ <p>
+ Render JavaScript validation based on the
+ validation rules loaded by the <code>ValidatorPlugIn</code>.
+ The set of validation rules that should be generated is based
+ on the formName attribute passed in, which should match
+ the name attribute of the form element in the xml file.
+ </p>
+ <p>
+ The dynamicJavascript and staticJavascript attributes
+ default to true, but if dynamicJavascript is set to <code>true</code>
+ and staticJavascript is set to <code>false</code> then only
+ the dynamic JavaScript will be rendered. If dynamicJavascript
+ is set to <code>false</code>
+ and staticJavascript is set to <code>true</code> then only
+ the static JavaScript will be rendered which can then be put in
+ separate JSP page so the browser can cache the static JavaScript.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>cdata</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ If set to "true" and XHTML has been enabled, the JavaScript will
+ be wrapped in a CDATA section to prevent XML parsing. The default is
+ "true" to comply with the W3C's recommendation.
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>dynamicJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the dynamic JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>formName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The key (form name) to retrieve a specific
+ set of validation rules. If "dynamicJavascript" is set
+ to <code>true</code> and formName is missing or is not
+ recognized by the <code>ValidatorPlugIn</code>, a
+ JspException will be thrown.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The alternate JavaScript method name to be used
+ instead of the of the default. The default is
+ 'validate' concatenated in front of
+ the key (form name) passed in (ex: validateRegistrationForm).
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ <description>
+ <![CDATA[
+ <p>
+ The current page of a set of validation rules
+ if the page attribute for the field element
+ in the xml file is in use.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHTML mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The src attribute's value when defining
+ the html script element.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>staticJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the static JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>htmlComment</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to enclose the javascript
+ with HTML comments. This attribute is ignored in XHTML
+ mode because the script would be deleted by the XML parser. See
+ the cdata attribute for details on hiding scripts from XML
+ parsers.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>link</name>
+ <tag-class>org.apache.struts.taglib.html.LinkTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML anchor or hyperlink</strong></p>
+
+
+ <p>Renders an HTML <code><a></code> element as an
+ anchor definition (if "linkName" is specified) or as a
+ hyperlink to the specified URL. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies. The content displayed for this
+ hyperlink will be taken from the body of this tag.</p>
+
+ <p>The base URL for this hyperlink is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there. If the forward is module-relative then
+ it must point to an action and NOT to a page.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ name of a <code>Action</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and module
+ prefix.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then indexed parameter with name from indexId attribute
+ will be added to the query string. Indexed parameter looks like
+ "index[32]". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By this attribute different name for the indexed parameter can be
+ specified. Take a look to the "indexed" attribute for details.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>linkName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The anchor name to be defined within this page, so that
+ you can reference it with intra-page hyperlinks. In other
+ words, the value specified here will render a "name" element
+ in the generated anchor tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element loses input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse double click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse move event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse out event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse over event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute,
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The tab order (ascending positive integers) for
+ this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target in which the resource requested by this
+ hyperlink will be displayed, for example in a framed
+ presentation.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>messages</name>
+ <tag-class>org.apache.struts.taglib.html.MessagesTag</tag-class>
+ <tei-class>org.apache.struts.taglib.html.MessagesTei</tei-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated messages.
+ </strong></p>
+
+ <p>Displays a set of messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, <code>ActionErrors</code> object, a String,
+ or a String array in any scope. If
+ such a bean is not found, nothing will be rendered. The messages are
+ placed into the page scope in the body of this tag where they can be displayed
+ by standard JSP methods. (For example: <code><bean:write></code>,<code><c:out></code>)
+ </p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>id</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ The name of a page scope JSP bean that will contain the current
+ element of the collection of messages on each iteration, if it is not
+ <code>null</code>.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the bean in any scope under which our messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which messages should be
+ displayed. If not specified, all messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of messages begins.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of messages has finished.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>message</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By default the tag will retrieve the bean it will
+ iterate over from the <code>Globals.ERROR_KEY</code> constant string,
+ but if this attribute is set to 'true' the bean
+ will be retrieved from the <code>Globals.MESSAGE_KEY</code>
+ constant string. Also if this is set to 'true', any value
+ assigned to the name attribute will be ignored.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>multibox</name>
+ <tag-class>org.apache.struts.taglib.html.MultiboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, whose "checked" status is
+ initialized based on whether the specified value
+ matches one of the elements of the underlying
+ property's array of current values. This element is
+ useful when you have large numbers of checkboxes, and
+ prefer to combine the values into a single
+ array-valued property instead of multiple boolean
+ properties. This tag is only valid when nested
+ inside a form tag body.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where none of the associated checkboxes
+ are selected, the <code>ActionForm</code> bean
+ associated with this form must include a statement
+ setting the corresponding array to zero length in the
+ <code>reset()</code> method.</p>
+
+ <p>The value to be returned to the server, if this checkbox is
+ selected, must be defined by one of the following methods:</p>
+ <ul>
+ <li>Specify a <code>value</code> attribute, whose contents will
+ be used literally as the value to be returned.</li>
+ <li>Specify no <code>value</code> attribute, and the nested
+ body content of this tag will be used as the value to be
+ returned.</li>
+ </ul>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>option</name>
+ <tag-class>org.apache.struts.taglib.html.OptionTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Option
+ </strong></p>
+
+ <p>Render an HTML <code><option></code> element,
+ representing one of the choices for an enclosing
+ <code><select></code> element. The text displayed to the
+ user comes from either the body of this tag, or from a message
+ string looked up based on the <code>bundle</code>,
+ <code>locale</code>, and <code>key</code> attributes.</p>
+
+ <p>If the value of the corresponding bean property matches the
+ specified value, this option will be marked selected. This tag
+ is only valid when nested inside a
+ <code><html:select></code> tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this option should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>key</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If specified, defines the message key to be looked up in
+ the resource bundle specified by <code>bundle</code> for
+ the text displayed to the user for this option. If not
+ specified, the text to be displayed is taken from the body
+ content of this tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attributes key for the Locale instance to use
+ for looking up the message specified by the
+ <code>key</code> attribute. If not specified, uses the
+ standard Struts session attribute name.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to be submitted for this field if this option is
+ selected by the user.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>options</name>
+ <tag-class>org.apache.struts.taglib.html.OptionsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:optionsCollection></code> elements.</p>
+
+ <p>This tag operates in one of two major modes, depending on
+ whether or not the <code>collection</code> attribute is
+ specified. If the <code>collection</code> attribute is
+ included, the following rules apply:</p>
+ <ul>
+ <li>The <strong>collection</strong> attribute is interpreted
+ as the name of a JSP bean, in some scope, that itself
+ represents a collection of individual beans, one per option
+ value to be rendered.</li>
+ <li>The <strong>property</strong> attribute is interpreted as
+ the name of a property of the individual beans included in
+ the collection, and is used to retrieve the value that will
+ be returned to the server if this option is selected.</li>
+ <li>The <strong>labelProperty</strong> attribute is interpreted
+ as the name of a property of the individual beans included
+ in the collection, and is used to retrieve the label that
+ will be displayed to the user for this option. If the
+ <code>labelProperty</code> attribute is not specified, the
+ property named by the <code>property</code> attribute will
+ be used to select both the value returned to the server and
+ the label displayed to the user for this option.</li>
+ </ul>
+
+ <p>If the <code>collection</code> attribute is not specified,
+ the rules described in the remainder of this section apply.</p>
+
+ <p>The collection of values actually selected depends on the presence or
+ absence of the <code>name</code> and <code>property</code> attributes. The
+ following combinations are allowed:</p>
+ <ul>
+ <li><em>Only <code>name</code> is specified</em> - The value of this attribute
+ is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>property</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>name</code> and <code>property</code> are specified</em> -
+ The value of the <code>name</code> attribute identifies a JSP bean
+ in some scope. The value of the <code>property</code> attribute is the
+ name of some property of that bean which will return the collection.</li>
+ </ul>
+
+ <p>The collection of labels displayed to the user can be the same as the
+ option values themselves, or can be different, depending on the presence or
+ absence of the <code>labelName</code> and <code>labelProperty</code>
+ attributes. If this feature is used, the collection of labels must contain
+ the same number of elements as the corresponding collection of values.
+ The following combinations are allowed:</p>
+ <ul>
+ <li><em>Neither <code>labelName</code> nor <code>labelProperty</code> is
+ specified</em> - The labels will be the same as the option values
+ themselves.</li>
+ <li><em>Only <code>labelName</code> is specified</em> - The value of this
+ attribute is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>labelProperty</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>labelName</code> and <code>labelProperty</code> are
+ specified</em> - The value of the <code>labelName</code> attribute
+ identifies a JSP bean in some scope. The value of the
+ <code>labelProperty</code> attribute is the name of some property of
+ that bean which will return the collection.</li>
+ </ul>
+
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>collection</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) which is itself a
+ Collection of other beans, each of which has properties
+ named by the "property" and "labelProperty" attributes
+ that are used to retrieve the value and label for each
+ option, respectively.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of labels to
+ be displayed to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the labelName
+ attribute, that will return the collection of labels to be displayed
+ to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of
+ values to be returned to the server for these options. If not
+ specified, the form bean associated with our form is assumed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of values to returned
+ to the server for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>optionsCollection</name>
+ <tag-class>
+ org.apache.struts.taglib.html.OptionsCollectionTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:options></code> elements.</p>
+
+ <p>This tag operates on a collection of beans, where each bean
+ has a <strong>label</strong> property and a <strong>value</strong>
+ property. The actual names of these properties can be configured
+ using the <code>label</code> and <code>value</code> attributes
+ of this tag.</p>
+
+ <p>This tag differs from the <code><html:options></code> tag
+ in that it makes more consistent use of the <code>name</code> and
+ <code>property</code> attributes, and allows the collection to be
+ more easily obtained from the enclosing form bean.</p>
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>label</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the label to be rendered for each option. Defaults to "label".
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of objects to be
+ rendered for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the value to be rendered for each option. Defaults to "value".
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>password</name>
+ <tag-class>org.apache.struts.taglib.html.PasswordTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Password Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type password, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>redisplay</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Boolean flag indicating whether or not existing values
+ will be redisplayed if they exist. Even though the
+ redisplayed value will be shown as asterisks on the
+ visible HTML page, the cleartext of the actual password
+ value will be visible though the "Show Page Source"
+ menu option of the client browser. You may wish to
+ set this value to <code>false</code> on login pages.
+ Defaults to <code>true</code> for consistency with
+ all other form tags that redisplay their contents.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any)]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>radio</name>
+ <tag-class>org.apache.struts.taglib.html.RadioTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Radio Button Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type radio, populated from
+ the specified property of the bean associated with our current form.
+ This tag is only valid when nested inside a form tag body.
+ </p>
+ <p>
+ If an iterator is used to render a series of radio tags, the
+ idName attribute may be used to specify the name of the bean
+ exposed by the iterator. In this case, the value attribute is
+ used as the name of a property on the idName bean that returns
+ the value of the radio tag in this iteration.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The corresponding bean property for this radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>idName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the bean (in some scope) that will return the
+ value of the radio tag. Usually exposed
+ by an iterator. When the idName attribute is
+ present, the value attribute is used as the name of the
+ property on the idName bean that will return the
+ value of the radio tag for this iteration.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>reset</name>
+ <tag-class>org.apache.struts.taglib.html.ResetTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Reset Button Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type reset.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the input field that will be generated.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button.
+ [Body of this tag (if any), or "Reset"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>rewrite</name>
+ <tag-class>org.apache.struts.taglib.html.RewriteTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an URI</strong></p>
+
+ <p>Renders a request URI based on exactly the same rules
+ as the <code><a href="#link">link</a></code> tag does,
+ but without creating
+ the <code><a></code> hyperlink. This value is useful
+ when you want to generate a string constant for use by
+ a JavaScript procedure.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.0</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>select</name>
+ <tag-class>org.apache.struts.taglib.html.SelectTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Element
+ </strong></p>
+
+ <p>Renders an HTML <select> element, associated
+ with a bean property specified by our attributes. This
+ tag is only valid when nested inside a form tag body.
+ </p>
+
+ <p>This tag operates in two modes, depending upon the
+ state of the <code>multiple</code> attribute, which
+ affects the data type of the associated property you
+ should use:</p>
+ <ul>
+ <li><em>multiple="true" IS NOT selected</em> -
+ The corresponding property should be a scalar
+ value of any supported data type.</li>
+ <li><em>multiple="true" IS selected</em> -
+ The corresponding property should be an array
+ of any supported data type.</li>
+ </ul>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where no selection at all is made, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement resetting the scalar property
+ to a default value (if <code>multiple</code> is not
+ set), or the array property to zero length (if
+ <code>multiple</code> is set) in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>multiple</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If set to any arbitrary value, the rendered
+ select element will support
+ multiple selections.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ to determine which option should be pre-selected when rendering
+ this input field. If not specified, the bean associated with
+ the enclosing <code><html:form></code> tag is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of available options displayed at one time.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to compare with for marking an option selected.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>submit</name>
+ <tag-class>org.apache.struts.taglib.html.SubmitTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Submit Button
+ </strong></p>
+
+ Renders an HTML <input> element of type <code>submit</code>.
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the button label.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>text</name>
+ <tag-class>org.apache.struts.taglib.html.TextTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render An Input Field of Type text</strong></p>
+
+ <p>Render an input field of type text. This tag is only valid when
+ nested inside a form tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>textarea</name>
+ <tag-class>org.apache.struts.taglib.html.TextareaTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Textarea
+ </strong></p>
+
+ Render a textarea element. This tag is only valid when nested
+ inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>cols</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of columns to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>rows</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of rows to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>xhtml</name>
+ <tag-class>org.apache.struts.taglib.html.XhtmlTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render HTML tags as XHTML</strong></p>
+
+ <p>
+ Using this tag in a page tells all other html taglib tags
+ to render themselves as XHTML 1.0. This is useful
+ when composing pages with JSP includes or Tiles.
+ <html:html xhtml="true"> has a similar effect. This
+ tag has no attributes; you use it like this: <html:xhtml/>.
+ </p>
+ <p>
+ <strong>Note</strong>: Included pages do not inherit the rendering
+ style of the including page. Each JSP fragment or Tile must use this
+ tag to render as XHTML.
+ </p>
+ ]]>
+ </description>
+ </tag>
+</taglib>
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..17c6301
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-2-src/webapp/WEB-INF/web.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+ <display-name>Struts MailReader Application</display-name>
+
+ <!-- Action Servlet Configuration -->
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
+ <init-param>
+ <param-name>config</param-name>
+ <param-value>
+ /WEB-INF/struts-config.xml,
+ /WEB-INF/Register-configure.xml
+ </param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+
+ <!-- Action Servlet Mapping -->
+ <servlet-mapping>
+ <servlet-name>action</servlet-name>
+ <url-pattern>*.do</url-pattern>
+ </servlet-mapping>
+
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/Calculator.java b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/Calculator.java
new file mode 100644
index 0000000..4f63627
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/Calculator.java
@@ -0,0 +1,67 @@
+/*
+ * =================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All
+ * rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software
+ * itself, if and wherever such third-party acknowlegements
+ * normally appear.
+ *
+ * 4. The names "The Jakarta Project", "junitbook", "jia",
+ * "JUnit in Action" and "Apache Software Foundation" must not be
+ * used to endorse or promote products derived from this software
+ * without prior written permission. For written permission,
+ * please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * =================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For
+ * more information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package jumpstart;
+
+public class Calculator
+{
+ public double add(double number1, double number2)
+ {
+ return number1 + number2;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator.java b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator.java
new file mode 100644
index 0000000..aaa4e52
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator.java
@@ -0,0 +1,72 @@
+/*
+ * =================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All
+ * rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software
+ * itself, if and wherever such third-party acknowlegements
+ * normally appear.
+ *
+ * 4. The names "The Jakarta Project", "junitbook", "jia",
+ * "JUnit in Action" and "Apache Software Foundation" must not be
+ * used to endorse or promote products derived from this software
+ * without prior written permission. For written permission,
+ * please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * =================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For
+ * more information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package jumpstart;
+
+public class TestCalculator
+{
+ public static void main(String[] args)
+ {
+ Calculator calculator = new Calculator();
+ double result = calculator.add(10, 50);
+ if (result != 60)
+ {
+ System.out.println("Bad result: " + result);
+ }
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator2.java b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator2.java
new file mode 100644
index 0000000..b08671a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator2.java
@@ -0,0 +1,94 @@
+/*
+ * =================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All
+ * rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software
+ * itself, if and wherever such third-party acknowlegements
+ * normally appear.
+ *
+ * 4. The names "The Jakarta Project", "junitbook", "jia",
+ * "JUnit in Action" and "Apache Software Foundation" must not be
+ * used to endorse or promote products derived from this software
+ * without prior written permission. For written permission,
+ * please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * =================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For
+ * more information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package jumpstart;
+
+public class TestCalculator2
+{
+ private int nbErrors = 0;
+
+ public void testAdd()
+ {
+ Calculator calculator = new Calculator();
+ double result = calculator.add(10, 50);
+ if (result != 60)
+ {
+ throw new RuntimeException("Bad result: " + result);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ TestCalculator2 test = new TestCalculator2();
+ try
+ {
+ test.testAdd();
+ }
+ catch (Throwable e)
+ {
+ test.nbErrors++;
+ e.printStackTrace();
+ }
+
+ if (test.nbErrors > 0)
+ {
+ throw new RuntimeException("There were " + test.nbErrors
+ + " error(s)");
+ }
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator3.java b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator3.java
new file mode 100644
index 0000000..8c70d0f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-3-src/junitbook/jumpstart/TestCalculator3.java
@@ -0,0 +1,71 @@
+/*
+ * =================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All
+ * rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software
+ * itself, if and wherever such third-party acknowlegements
+ * normally appear.
+ *
+ * 4. The names "The Jakarta Project", "junitbook", "jia",
+ * "JUnit in Action" and "Apache Software Foundation" must not be
+ * used to endorse or promote products derived from this software
+ * without prior written permission. For written permission,
+ * please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * =================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For
+ * more information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package jumpstart;
+
+import junit.framework.TestCase;
+
+public class TestCalculator3 extends TestCase
+{
+ public void testAdd()
+ {
+ Calculator calculator = new Calculator();
+ double result = calculator.add(10, 50);
+ assertEquals(60, result, 0);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/commons-logging.properties b/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/commons-logging.properties
new file mode 100644
index 0000000..8e2342f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/commons-logging.properties
@@ -0,0 +1,12 @@
+#
+# commons-logging.properties
+#
+
+#------------------------------------------------------------------------------
+# Select LogFactory:
+#------------------------------------------------------------------------------
+# Dynamically selects logging implementation class according to the following:
+#
+org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
+org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/org/apache/struts/apps/mailreader/dao/BaseTestUserDatabase.java b/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/org/apache/struts/apps/mailreader/dao/BaseTestUserDatabase.java
new file mode 100644
index 0000000..92b9040
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/org/apache/struts/apps/mailreader/dao/BaseTestUserDatabase.java
@@ -0,0 +1,321 @@
+/*
+ * $Id: Subscription.java 149009 2005-01-29 05:33:02Z jmitchell $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.apps.mailreader.dao;
+
+import junit.framework.TestCase;
+
+/**
+ * We have use case tests for:
+ * - [01 ] findUser(existing) [DONE]
+ * - [02 ] findUser(bogus) [DONE]
+ * - [03 ] findUsers() [DONE]
+ * ---------------------------------------------------------------
+ * lab 1-3 - Complete some or all of the remaining use cases
+ * ---------------------------------------------------------------
+ * - [04 ] createUser1, find(new one 1) [DONE]
+ * - [04a] createUser1, find(new one 1) find subscr [DONE]
+ * - [05 ] createUser2, find(existing) [DONE]
+ * - [05a] createUser2, find(existing) find subscr [DONE]
+ * - [06 ] createUser3, findUsers(all) [DONE]
+ * - [06a] createUser4 (duplicate) [DONE]
+ * - [07 ] findUsers(all) [DONE]
+ * - [08 ] create, save, close, open find(new one) [DONE]
+ * - [09 ] create, save, close, open findUsers(all) [DONE]
+ * - [10 ] find(bogus) [DONE]
+ * - [11 ] create, remove, find(valid), find(invalid) [DONE]
+ *
+ */
+
+public abstract class BaseTestUserDatabase extends TestCase {
+
+ protected UserDatabase userDatabase;
+ private int userCt = 10;
+ private int subscriptionCt = 20;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ userDatabase = getNewUserDatabase();
+ generateUsers(userCt, subscriptionCt, "");
+ }
+
+
+ /**
+ *
+ */
+ private void generateUsers(int users, int subs, String prefix) {
+ for (int i = 0; i < users; i++) {
+ User user = getNewUser(userDatabase, prefix + "user" + i);
+ user.setFromAddress(prefix + "fromAddress" + i);
+ user.setFullName(prefix + "fullName" + i);
+ user.setPassword(prefix + "password" + i);
+
+ for (int j = 0; j < subs; j++) {
+ Subscription subscription = getNewSubscription(user, prefix + "host" + j);
+ subscription.setAutoConnect(j % 1 == 0);
+ subscription.setUsername(prefix + "subscriptionUserName" + j);
+ subscription.setPassword(prefix + "subscriptionPassword" + j);
+ subscription.setType(prefix + "type" + j);
+ }
+ }
+ }
+
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ userDatabase.close();
+ }
+
+
+ // findUser(existing)
+ public void testCase01() throws Exception{
+ User user = userDatabase.findUser("user5");
+ assertTrue("Check username", "user5".equals(user.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress5".equals(user.getFromAddress()));
+ assertTrue("Check fullName", "fullName5".equals(user.getFullName()));
+ assertTrue("Check password", "password5".equals(user.getPassword()));
+ assertNull("Check replyToAddress", user.getReplyToAddress());
+
+ }
+
+ // findUser(bogus)
+ public void testCase02() throws Exception{
+ User user = userDatabase.findUser("bogusName");
+ assertNull(user);
+ }
+
+ // findUsers()
+ public void testCase03() throws Exception{
+ User[] users = userDatabase.findUsers();
+ assertTrue("Check users", users.length == userCt);
+ }
+
+ // createUser1, find(new one 1)
+ public void testCase04() throws Exception{
+ String newUserName = "newUser04";
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ User newUser2 = userDatabase.findUser(newUserName);
+ assertTrue("Check username", newUserName.equals(newUser2.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress1".equals(newUser2.getFromAddress()));
+ assertTrue("Check replyToAddress", "replyToAddress1".equals(newUser2.getReplyToAddress()));
+ assertTrue("Check password", "pass1".equals(newUser2.getPassword()));
+ assertNull("Check fullName", newUser2.getFullName());
+ }
+
+ // createUser1, find(new one 1) find subscr
+ public void testCase04a() throws Exception{
+ String newUserName = "newUser04a";
+ int subs = 5;
+
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ User newUser2 = userDatabase.findUser(newUserName);
+ assertTrue("Check username", newUserName.equals(newUser2.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress1".equals(newUser2.getFromAddress()));
+ assertTrue("Check replyToAddress", "replyToAddress1".equals(newUser2.getReplyToAddress()));
+ assertTrue("Check password", "pass1".equals(newUser2.getPassword()));
+ assertNull("Check fullName", newUser2.getFullName());
+
+ generateUsers(3, subs, "04a");
+
+ User newUser3 = userDatabase.findUser("04auser1");
+ Subscription[] subscriptions = newUser3.getSubscriptions();
+ assertTrue ("Testing subscriptions length", subscriptions.length == subs);
+ newUser3.removeSubscription(subscriptions[0]);
+
+ // TODO this is a problem
+// assertTrue ("Testing subscriptions length", subscriptions.length < subs);
+
+ }
+
+ // createUser2, find(existing)
+ public void testCase05() throws Exception{
+ String newUserName = "anotherNewUser05";
+
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ User newUser5 = userDatabase.findUser("user5");
+ assertTrue("Check username", "user5".equals(newUser5.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress5".equals(newUser5.getFromAddress()));
+ assertTrue("Check fullName", "fullName5".equals(newUser5.getFullName()));
+ assertTrue("Check password", "password5".equals(newUser5.getPassword()));
+ assertNull("Check replyToAddress", newUser5.getReplyToAddress());
+
+ }
+
+ // createUser2, find(existing) find subscr
+ public void testCase05a() throws Exception{
+ String newUserName = "anotherNewUser05a";
+
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ User newUser5a = userDatabase.findUser("user5");
+ assertTrue("Check username", "user5".equals(newUser5a.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress5".equals(newUser5a.getFromAddress()));
+ assertTrue("Check fullName", "fullName5".equals(newUser5a.getFullName()));
+ assertTrue("Check password", "password5".equals(newUser5a.getPassword()));
+ assertNull("Check replyToAddress", newUser5a.getReplyToAddress());
+
+ Subscription[] subscriptions = newUser5a.getSubscriptions();
+ assertTrue ("Testing subscriptions length", subscriptions.length == subscriptionCt);
+
+ }
+
+ // createUser3, findUsers(all)
+ public void testCase06() throws Exception{
+ String newUserName = "anotherNewUser06";
+
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ User user6 = userDatabase.findUser("user6");
+ assertTrue("Check username", "user6".equals(user6.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress6".equals(user6.getFromAddress()));
+ assertTrue("Check fullName", "fullName6".equals(user6.getFullName()));
+ assertTrue("Check password", "password6".equals(user6.getPassword()));
+ assertNull("Check replyToAddress", user6.getReplyToAddress());
+
+ }
+
+ // createUser4 (duplicate)
+ // public void testCase06a() throws Exception{
+
+ // findUsers(all)
+ public void testCase07() throws Exception{
+ String newUserName = "anotherNewUser07";
+
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ User user7 = userDatabase.findUser("user7");
+ assertTrue("Check username", "user7".equals(user7.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress7".equals(user7.getFromAddress()));
+ assertTrue("Check fullName", "fullName7".equals(user7.getFullName()));
+ assertTrue("Check password", "password7".equals(user7.getPassword()));
+ assertNull("Check replyToAddress", user7.getReplyToAddress());
+
+ User[] users = userDatabase.findUsers();
+ assertTrue("Check users", users.length == userCt + 1);
+
+ }
+
+ // create, save, close, open find(new one)
+ public void testCase08() throws Exception{
+ String newUserName = "newUser08";
+ int subs = 5;
+
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ // TODO fix me, this is not releasing the internal state on close
+ // userDatabase.save();
+ // userDatabase.close();
+ // userDatabase.open();
+
+ User newUser2 = userDatabase.findUser(newUserName);
+ assertTrue("Check username", newUserName.equals(newUser2.getUsername()));
+ assertTrue("Check fromAddress", "fromAddress1".equals(newUser2.getFromAddress()));
+ assertTrue("Check replyToAddress", "replyToAddress1".equals(newUser2.getReplyToAddress()));
+ assertTrue("Check password", "pass1".equals(newUser2.getPassword()));
+ assertNull("Check fullName", newUser2.getFullName());
+
+ generateUsers(3, subs, "08");
+
+ User newUser3 = userDatabase.findUser("08user1");
+ Subscription[] subscriptions = newUser3.getSubscriptions();
+ assertTrue ("Testing subscriptions length", subscriptions.length == subs);
+
+ // userDatabase.save();
+ // userDatabase.close();
+ // userDatabase.open();
+
+ User newUser4 = userDatabase.findUser("08user1");
+ Subscription[] subscriptions2 = newUser4.getSubscriptions();
+ assertTrue ("Testing subscriptions length", subscriptions2.length == subs);
+
+ }
+
+ // create, save, close, open findUsers(all)
+ public void testCase09() throws Exception{
+
+ // TODO fix me, this is not releasing the internal state on close
+// userDatabase.save();
+// userDatabase.close();
+// userDatabase.open();
+
+ User[] users = userDatabase.findUsers();
+ assertTrue("Testing users count", users.length == userCt);
+
+ }
+
+ // find(bogus)
+ public void testCase010() throws Exception{
+
+ // TODO fix me, this is not releasing the internal state on close
+// userDatabase.save();
+// userDatabase.close();
+// userDatabase.open();
+
+ User user = userDatabase.findUser("bogus user");
+ assertNull("Find non-existing user", user);
+
+ }
+
+ // create, remove, find(valid), find(invalid)
+ public void testCase011() throws Exception{
+
+ String newUserName = "newUser11";
+
+ User newUser = userDatabase.createUser(newUserName);
+ newUser.setPassword("pass1");
+ newUser.setFromAddress("fromAddress1");
+ newUser.setReplyToAddress("replyToAddress1");
+
+ User user = userDatabase.findUser(newUserName);
+ assertNotNull("Find new user", user);
+
+ userDatabase.removeUser(user);
+ User user2 = userDatabase.findUser(newUserName);
+ assertNull("Remove new user", user2);
+
+ }
+
+ protected abstract UserDatabase getNewUserDatabase();
+ protected abstract User getNewUser(UserDatabase db, String userName);
+ protected abstract Subscription getNewSubscription(User user, String host);
+
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/org/apache/struts/apps/mailreader/dao/impl/memory/MemoryUserDatabaseTest.java b/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/org/apache/struts/apps/mailreader/dao/impl/memory/MemoryUserDatabaseTest.java
new file mode 100644
index 0000000..7a0bab5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-3-src/test/org/apache/struts/apps/mailreader/dao/impl/memory/MemoryUserDatabaseTest.java
@@ -0,0 +1,53 @@
+/*
+ * $Id: Subscription.java 149009 2005-01-29 05:33:02Z jmitchell $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.apps.mailreader.dao.impl.memory;
+
+import org.apache.struts.apps.mailreader.dao.BaseTestUserDatabase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+
+
+
+public class MemoryUserDatabaseTest extends BaseTestUserDatabase {
+
+ protected String defaultPathName = "test-database.xml";
+
+ protected UserDatabase getNewUserDatabase(){
+ // using default impl
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(defaultPathName);
+ userDatabase = memoryUserDatabase;
+ return memoryUserDatabase;
+
+ }
+ protected User getNewUser(UserDatabase db, String userName){
+ // using default impl
+ return db.createUser(userName);
+ }
+ protected Subscription getNewSubscription(User user, String host) {
+ return user.createSubscription(host);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ // force write to disk
+ userDatabase.close();
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/META-INF/context.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/Constants.java b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/Constants.java
new file mode 100644
index 0000000..227dcd1
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/Constants.java
@@ -0,0 +1,208 @@
+package org.apache.struts.apps.mailreader.course;
+
+/**
+ * <p>
+ * Manifest constants for the MailReader application.
+ * </p>
+ *
+ */
+public class Constants {
+
+ // --- Tokens ----
+
+ /**
+ * <p>
+ * The token representing a "create" task.
+ * </p>
+ */
+ public static final String CREATE = "Create";
+
+ /**
+ * <p>
+ * The application scope attribute under which our user database
+ * is stored.
+ * </p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ * <p>
+ * The token representing a "edit" task.
+ * </p>
+ */
+ public static final String DELETE = "Delete";
+
+ /**
+ * <p>
+ * The token representing a "edit" task.
+ * </p>
+ */
+ public static final String EDIT = "Edit";
+
+ /**
+ * <p>
+ * The request attributes key under the WelcomeAction stores an ArrayList
+ * of error messages, if required resources are missing.
+ * </p>
+ */
+ public static final String ERROR_KEY = "ERROR";
+
+ /**
+ * <p>
+ * The token representing a "failure" result for this application.
+ * </p>
+ */
+ public static final String FAILURE = "Failure";
+
+ /**
+ * <p>
+ * The token representing a "logon" result for this application.
+ * </p>
+ */
+ public static final String LOGON = "Logon";
+
+ /**
+ * <p>
+ * The package name for this application.
+ * </p>
+ */
+ public static final String PACKAGE = "org.apache.struts.apps.mailreader";
+
+ /**
+ * <p>
+ * The token representing a "save" task.
+ * </p>
+ */
+ public static final String SAVE = "Save";
+
+ /**
+ * <p>
+ * The session scope attribute under which the Subscription object
+ * currently selected by our logged-in User is stored.
+ * </p>
+ */
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ /**
+ * <p>
+ * The token representing a "success" result for this application.
+ * </p>
+ */
+ public static final String SUCCESS = "Success";
+
+ /**
+ * <p>
+ * The session scope attribute under which the User object
+ * for the currently logged in user is stored.
+ * </p>
+ */
+ public static final String USER_KEY = "user";
+
+ // ---- Error Messages ----
+
+ /**
+ * <p>
+ * A static message in case database resource is not loaded.
+ * <p>
+ */
+ public static final String ERROR_DATABASE_NOT_LOADED =
+ "ERROR: User database not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p>
+ * A static message in case message resource is not loaded.
+ * </p>
+ */
+ public static final String ERROR_MESSAGES_NOT_LOADED =
+ "ERROR: Message resources not loaded -- check servlet container logs for error messages.";
+
+ // ---- Error Tokens ----
+
+ /**
+ * <p>
+ * The resource key for an error with the transactional token.
+ * </p>
+ */
+ public static final String MSG_TRANSACTION_TOKEN = "error.transaction.token";
+
+ // ---- Log Messages ----
+
+ /**
+ * <p>
+ * The message to log when cancelling a transaction.
+ * </p>
+ */
+ public static final String LOG_CANCEL = " Transaction cancelled: ";
+
+ /**
+ * <p>
+ * The message to log when forwarding to a result.
+ * </p>
+ */
+ public static final String LOG_RESULT = " Forwarding to result: ";
+
+ /**
+ * <p>
+ * The message to log when forwarding to a 'failure' result.
+ * <p>
+ */
+ public static final String LOG_FAILURE = LOG_RESULT + FAILURE;
+
+ /**
+ * <p>
+ * The message to log when forwarding to a 'logon' result.
+ * </p>
+ */
+ public static final String LOG_LOGON = LOG_RESULT + LOGON;
+
+ /**
+ * <p>
+ * The message to log when populating a form.
+ * </p>
+ */
+ public static final String LOG_POPULATE_FORM = " Populating form from: ";
+
+ /**
+ * <p>
+ * The message to log when populating a subscription.
+ * </p>
+ */
+ public static final String LOG_POPULATE_SUBSCRIPTION = " Populating subscription: ";
+
+ /**
+ * <p>
+ * The message to log when populating a user.
+ * </p>
+ */
+ public static final String LOG_POPULATE_USER = " Populating user: ";
+
+ /**
+ * <p>
+ * The message to log when forwarding to a 'success' result.
+ * </p>
+ */
+ public static final String LOG_PROCESSING = " Processing: ";
+
+ /**
+ * <p>
+ * The message to log when forwarding to a 'success' result.
+ * </p>
+ */
+ public static final String LOG_SUCCESS = LOG_RESULT + SUCCESS;
+
+ /**
+ * <p>
+ * The message to log when setting a transactional token.
+ * </p>
+ */
+ public static final String LOG_TOKEN = " Setting transactional control token";
+
+ /**
+ * <p>
+ * The message to log when checking a transactional token.
+ * </p>
+ */
+ public static final String LOG_TOKEN_CHECK = " Checking transactional control token";
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/LogonAction.java b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/LogonAction.java
new file mode 100644
index 0000000..4f3a6c5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/LogonAction.java
@@ -0,0 +1,95 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.apps.mailreader.course;
+
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMessages;
+import org.apache.struts.action.ActionMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * <p/>
+ * Validate a user logon.
+ * </p>
+ *
+ * @version $Rev: 360442 $ $Date: 2005-12-31 15:10:04 -0500 (Sat, 31 Dec 2005) $
+ */
+public final class LogonAction extends RegisterAction {
+
+
+ /**
+ * <p/>
+ * Store User object in client session.
+ * If user object is null, any existing user object is removed.
+ * </p>
+ *
+ * @param request The request we are processing
+ * @param user The user object returned from the database
+ */
+ protected void doCacheUser(HttpServletRequest request, User user) {
+
+ HttpSession session = request.getSession();
+ session.setAttribute(USER_KEY, user);
+ }
+
+ /**
+ * <p/>
+ * Use "username" and "password" fields from ActionForm to retrieve a User
+ * object from the database. If credentials are not valid, or database
+ * has disappeared, post error messages and forward to input.
+ * </p>
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @throws Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Retrieve user
+ String username = doGet(form, USERNAME);
+ String password = doGet(form, PASSWORD);
+ ActionMessages errors = new ActionMessages();
+ User user = doGetUser(username, password, errors);
+
+ // Report back any errors, and exit if any
+ if (!errors.isEmpty()) {
+ return doInputForward(mapping, request, errors);
+ }
+
+ // Cache user object in session to signify logon
+ doCacheUser(request, user);
+
+ // Done
+ return doFindSuccess(mapping);
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/MemoryDatabasePlugIn.java b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/MemoryDatabasePlugIn.java
new file mode 100644
index 0000000..89996d7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/MemoryDatabasePlugIn.java
@@ -0,0 +1,175 @@
+package org.apache.struts.apps.mailreader.course;
+
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+import org.apache.struts.action.ActionServlet;
+import org.apache.struts.action.PlugIn;
+import org.apache.struts.config.ModuleConfig;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.servlet.ServletException;
+import java.io.*;
+
+/**
+ * <p><strong>MemoryDatabasePlugIn</strong> initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an
+ * XML file.</p>
+ *
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ *
+ * @version $Rev: 360442 $ $Date: 2005-12-31 15:10:04 -0500 (Sat, 31 Dec 2005) $
+ */
+public class MemoryDatabasePlugIn implements PlugIn {
+
+
+ // ---- Instance Variables ----
+
+ /**
+ * The {@link org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * Logging output for this plug in instance.
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+
+ /**
+ * The {@link org.apache.struts.action.ActionServlet} owning this application.
+ */
+ private ActionServlet servlet = null;
+
+ // ---- Properties ----
+
+ /**
+ * The web application resource path of our persistent database
+ * storage file.
+ */
+ private String pathname = "/WEB-INF/database.xml";
+
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ---- PlugIn Methods ----
+
+
+ /**
+ * Gracefully shut down this database, releasing any resources
+ * that were allocated at initialization.
+ */
+ public void destroy() {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY);
+ database = null;
+ servlet = null;
+ database = null;
+ }
+
+
+ /**
+ * Initialize and load our initial database from persistent storage.
+ *
+ * @param servlet The ActionServlet for this web application
+ * @param config The ApplicationConfig for our owning module
+ * @throws ServletException if we cannot configure ourselves correctly
+ */
+ public void init(ActionServlet servlet, ModuleConfig config)
+ throws ServletException {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated configuration and servlet
+ this.servlet = servlet;
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new ServletException("Cannot load database from '" +
+ pathname + "'", e);
+ }
+
+ // Make the initialized database available
+ servlet.getServletContext().setAttribute(Constants.DATABASE_KEY,
+ database);
+
+ }
+
+ // ---- Private Methods ----
+
+ /**
+ * Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.
+ *
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = servlet.getServletContext().getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ servlet.getServletContext().getAttribute
+ ("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ servlet.getServletContext().getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+ }
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/RegisterAction.java b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/RegisterAction.java
new file mode 100644
index 0000000..32a3eca
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/java/org/apache/struts/apps/mailreader/course/RegisterAction.java
@@ -0,0 +1,508 @@
+package org.apache.struts.apps.mailreader.course;
+
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.action.*;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletException;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * <p/>
+ * Provide an Edit method for retrieving an existing user,
+ * and a Save method for updating or inserting a user.
+ * </p><p>
+ * Both methods utilize a RegistrationForm to obtain or expose User details.
+ * If Save is used to create a user,
+ * additional validations ensure input is nominal.
+ * When a user is created,
+ * Save also handles the initial logon.
+ * </p>
+ */
+public class RegisterAction extends Action {
+
+ // ---- Constants ----
+
+ /**
+ * <p/>
+ * The application scope attribute under which our user database
+ * is stored.
+ * </p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ * <p/>
+ * Name of fromAddress field ["fromAddress"].
+ * </p>
+ */
+ public final static String FROM_ADDRESS = "fromAddress";
+
+ /**
+ * <p/>
+ * Name of fullName field ["fullName"].
+ * </p>
+ */
+ public final static String FULL_NAME = "fullName";
+
+ /**
+ * <p/>
+ * Name of password field ["password"].
+ * </p>
+ */
+ public static String PASSWORD = "password";
+
+ /**
+ * <p/>
+ * Name of password confirmation field ["password2"].
+ * </p>
+ */
+ public final static String PASSWORD2 = "password2";
+
+ /**
+ * <p/>
+ * Name of replyToAddress field ["replyToAddress"].
+ * </p>
+ */
+ public final static String REPLY_TO_ADDRESS = "replyToAddress";
+
+ /**
+ * <p/>
+ * The token representing a "success" result for this application.
+ * </p>
+ */
+ public static final String SUCCESS = "Success";
+
+ /**
+ * <p/>
+ * The session scope attribute under which the User object
+ * for the currently logged in user is stored.
+ * </p>
+ */
+ public static final String USER_KEY = "user";
+
+ /**
+ * <p/>
+ * Name of username field ["username"].
+ * </p>
+ */
+ public static String USERNAME = "username";
+
+ // ---- Private Methods ----
+
+ /**
+ * <p/>
+ * The <code>Log</code> instance for this application.
+ * </p>
+ */
+ private Log log = LogFactory.getLog(Constants.PACKAGE);
+
+ /**
+ * <p/>
+ * The message prefix to use when populating a Registration Form.
+ * </p>
+ */
+ final String LOG_REGISTRATION_POPULATE = "RegistrationForm.populate";
+
+ /**
+ * <p/>
+ * Helper method to post error message when user already exists.
+ * </p>
+ *
+ * @param username Existing username
+ * @param errors Our ActionMessages collection
+ */
+ private void errorUsernameUnique(String username,
+ ActionMessages errors) {
+ errors.add(
+ USERNAME,
+ new org.apache.struts.action.ActionMessage(
+ "error.username.unique", username));
+ }
+
+
+ /**
+ * <p/>
+ * Helper method to log event and cancel transaction.
+ * </p>
+ *
+ * @param session Our HttpSession
+ * @param method Method being processed
+ * @param key Attrkibute to remove from session, if any
+ */
+ private void doCancel(HttpSession session, String method, String key) {
+ if (log.isTraceEnabled()) {
+ StringBuffer sb = new StringBuffer(128);
+ sb.append(Constants.LOG_CANCEL);
+ sb.append(method);
+ log.trace(sb.toString());
+ }
+ if (key != null) {
+ session.removeAttribute(key);
+ }
+ }
+
+ /**
+ * <p/>
+ * Verify input for creating a new user,
+ * create the user, and process the login.
+ * </p>
+ *
+ * @param form The input form
+ * @param request The HttpRequest being served
+ * @param errors The ActionMessages collection for any errors
+ * @return A new User and empty Errors if create succeeds,
+ * or null and Errors if create fails
+ */
+ private User doCreateUser(
+ ActionForm form,
+ HttpServletRequest request,
+ ActionMessages errors) {
+
+ if (log.isTraceEnabled()) {
+ log.trace(" Perform additional validations on Create");
+ }
+
+ UserDatabase database = doGetUserDatabase();
+ String username = doGet(form, USERNAME);
+ try {
+ if (database.findUser(username) != null) {
+ errorUsernameUnique(username, errors);
+ }
+ }
+ catch (ExpiredPasswordException e) {
+ errorUsernameUnique(username, errors);
+ errors.add("errors.literal", new ActionMessage(e.getMessage()));
+ }
+
+ String password = doGet(form, PASSWORD);
+ if ((password == null) || (password.length() < 1)) {
+ errors.add(PASSWORD, new ActionMessage("error.password.required"));
+
+ String password2 = doGet(form, PASSWORD2);
+ if ((password2 == null) || (password2.length() < 1)) {
+ errors.add(
+ PASSWORD2,
+ new ActionMessage("error.password2.required"));
+ }
+ }
+
+ if (!errors.isEmpty()) {
+ return null;
+ }
+
+ User user = database.createUser(username);
+
+ // Log the user in
+ HttpSession session = request.getSession();
+ session.setAttribute(Constants.USER_KEY, user);
+ if (log.isTraceEnabled()) {
+ log.trace(
+ " User: '"
+ + user.getUsername()
+ + "' logged on in session: "
+ + session.getId());
+ }
+
+ return user;
+ }
+
+ /**
+ * <p/>
+ * Helper method to obtain User form session (if any).
+ * </p>
+ *
+ * @param session Our HttpSession
+ * @return User object, or null if there is no user.
+ */
+ private User doGetUser(HttpSession session) {
+ return (User) session.getAttribute(Constants.USER_KEY);
+ }
+
+ /**
+ * <p/>
+ * Confirm user credentials. Post any errors and return User object
+ * (or null).
+ * </p>
+ *
+ * @param database Database in which to look up the user
+ * @param username Username specified on the logon form
+ * @param password Password specified on the logon form
+ * @param errors ActionMessages queue to passback errors
+ * @return Validated User object or null
+ * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
+ * to be handled by Struts exception
+ * processor via the action-mapping
+ */
+ private User doGetUser(UserDatabase database, String username,
+ String password, ActionMessages errors)
+ throws ExpiredPasswordException {
+
+ User user = null;
+ if (database == null) {
+ errors.add(
+ ActionMessages.GLOBAL_MESSAGE,
+ new ActionMessage("error.database.missing"));
+ } else {
+
+ if (username.equals("Hermes")) {
+ throw new ExpiredPasswordException("Hermes");
+ }
+
+ user = database.findUser(username);
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ errors.add(
+ ActionMessages.GLOBAL_MESSAGE,
+ new ActionMessage("error.password.mismatch"));
+ }
+ }
+
+ return user;
+ }
+
+ /**
+ * <p/>
+ * Return a reference to the UserDatabase
+ * or null if the database is not available.
+ * </p>
+ *
+ * @return a reference to the UserDatabase or null if the database is not
+ * available
+ */
+ private UserDatabase doGetUserDatabase() {
+ return (UserDatabase) servlet.getServletContext().getAttribute(
+ DATABASE_KEY);
+ }
+
+ /**
+ * <p/>
+ * Log a "processing" message for an Action.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @param method Name of method being processed
+ */
+ private void doLogProcess(ActionMapping mapping, String method) {
+ if (log.isDebugEnabled()) {
+ StringBuffer sb = new StringBuffer(128);
+ sb.append(" ");
+ sb.append(mapping.getPath());
+ sb.append(":");
+ sb.append(Constants.LOG_PROCESSING);
+ sb.append(method);
+ log.debug(sb.toString());
+ }
+ }
+
+ /**
+ * <p/>
+ * Helper method to populate the User object from the input form.
+ * </p>
+ *
+ * @param user User object to populate
+ * @param form Form with incoming values
+ * @throws ServletException On any error
+ */
+ private void doPopulate(User user, ActionForm form)
+ throws ServletException {
+
+ if (log.isTraceEnabled()) {
+ log.trace(Constants.LOG_POPULATE_USER + user);
+ }
+
+ try {
+ String oldPassword = user.getPassword();
+ PropertyUtils.copyProperties(user, form);
+ String password = doGet(form, PASSWORD);
+ if ((password == null)
+ || (password.length() < 1)) {
+
+ user.setPassword(oldPassword);
+ }
+
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if (t == null) {
+ t = e;
+ }
+
+ log.error(LOG_REGISTRATION_POPULATE, t);
+ throw new ServletException(LOG_REGISTRATION_POPULATE, t);
+
+ } catch (Throwable t) {
+ log.error(LOG_REGISTRATION_POPULATE, t);
+ throw new ServletException(LOG_REGISTRATION_POPULATE, t);
+ }
+ }
+
+ /**
+ * <p/>
+ * Persist the User object, including subscriptions, to the database.
+ * </p>
+ *
+ * @param user Our User object
+ * @throws javax.servlet.ServletException On any error
+ */
+ private void doSaveUser(User user) throws ServletException {
+
+ final String LOG_DATABASE_SAVE_ERROR =
+ " Unexpected error when saving User: ";
+
+ try {
+ UserDatabase database = doGetUserDatabase();
+ database.save();
+ } catch (Exception e) {
+ String message = LOG_DATABASE_SAVE_ERROR + user.getUsername();
+ log.error(message, e);
+ throw new ServletException(message, e);
+ }
+ }
+
+ // ---- Protected methods ----
+
+ /**
+ * <p/>
+ * Return the mapping labeled "success"
+ * or null if there is no such mapping.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @return Return the mapping named "success" or null if there is no such
+ * mapping.
+ */
+ protected ActionForward doFindSuccess(ActionMapping mapping) {
+ return mapping.findForward(SUCCESS);
+ }
+
+
+ /**
+ * <p/>
+ * Helper method to fetch a String property from a DynaActionForm.
+ * </p>
+ * <p/>
+ * Values are returned trimmed of leading and trailing whitespace.
+ * Zero-length strings are returned as null.
+ * </p>
+ *
+ * @param form Our DynaActionForm
+ * @param property The name of the property
+ * @return The value or null if an error occurs
+ */
+ protected String doGet(ActionForm form, String property) {
+ String initial;
+ try {
+ initial = (String) PropertyUtils.getSimpleProperty(form, property);
+ } catch (Throwable t) {
+ initial = null;
+ }
+ String value = null;
+ if ((initial != null) && (initial.length() > 0)) {
+ value = initial.trim();
+ if (value.length() == 0) {
+ value = null;
+ }
+ }
+ return value;
+ }
+
+ /**
+ * <p/>
+ * Confirm user credentials. Post any errors and return User object
+ * (or null).
+ * </p>
+ *
+ * @param username Username specified on the logon form
+ * @param password Password specified on the logon form
+ * @param errors ActionMessages queue to passback errors
+ * @return Validated User object or null
+ * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
+ * to be handled by Struts exception
+ * processor via the action-mapping
+ */
+ protected User doGetUser(String username,
+ String password, ActionMessages errors)
+ throws ExpiredPasswordException {
+
+ return doGetUser(doGetUserDatabase(), username, password, errors);
+ }
+
+ /**
+ * <p/>
+ * Save any errors and forward to the Input result.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @param request Our HttpServletRequest
+ * @param errors Our ActionMessages collectoin
+ * @return The InputForward for this mappintg
+ */
+ protected ActionForward doInputForward(ActionMapping mapping,
+ HttpServletRequest request,
+ ActionMessages errors) {
+ this.saveErrors(request, errors);
+ return (mapping.getInputForward());
+ }
+
+ // ----- Public Methods ----
+
+ /**
+ * <p/>
+ * Insert or update a User object to the persistent store.
+ * </p><p>
+ * If a User is not logged in,
+ * then a new User is created and automatically logged in.
+ * Otherwise, the existing User is updated.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @param form Our ActionForm
+ * @param request Our HttpServletRequest
+ * @param response Our HttpServletResponse
+ * @return The "Success" result for this mapping
+ * @throws Exception on any error
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ final String method = Constants.SAVE;
+ doLogProcess(mapping, method);
+
+ HttpSession session = request.getSession();
+ if (isCancelled(request)) {
+ doCancel(session, method, Constants.SUBSCRIPTION_KEY);
+ return doFindSuccess(mapping);
+ }
+
+ ActionMessages errors = new ActionMessages();
+ if (!errors.isEmpty()) {
+ return doInputForward(mapping, request, errors);
+ }
+
+ User user = doGetUser(session);
+ if (user == null) {
+ user = doCreateUser(form, request, errors);
+ if (!errors.isEmpty()) {
+ return doInputForward(mapping, request, errors);
+ }
+ }
+
+ doPopulate(user, form);
+ doSaveUser(user);
+
+ return doFindSuccess(mapping);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/LogonForm.jsp b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/LogonForm.jsp
new file mode 100644
index 0000000..11371a6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/LogonForm.jsp
@@ -0,0 +1,54 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<html:xhtml/>
+<html>
+<head>
+ <title><bean:message key="Logon.title"/></title>
+</head>
+
+<body>
+<html:errors/>
+
+<html:form action="/LogonPost">
+ <table border="0" width="100%">
+
+ <tr>
+ <th align="right">
+ <bean:message key="username.label"/>:
+ </th>
+ <td align="left">
+ <html:text property="username" size="16" maxlength="18"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ <bean:message key="password.label"/>:
+ </th>
+ <td align="left">
+ <html:password property="password" size="16" maxlength="18"
+ redisplay="false"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">
+ <html:submit property="DO_SUBMIT">
+ <bean:message key="button.submit"/>
+ </html:submit>
+ </td>
+ <td align="left">
+ <html:reset property="DO_RESET">
+ <bean:message key="button.reset"/>
+ </html:reset>
+ </td>
+ </tr>
+
+ </table>
+
+</html:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/MainMenu.jsp b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/MainMenu.jsp
new file mode 100644
index 0000000..a0d6ec6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/MainMenu.jsp
@@ -0,0 +1,16 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<html>
+<head>
+ <title><bean:message key="MainMenu.title"/></title>
+</head>
+
+<body>
+<h3>Main Menu Options for <bean:write name="user"
+ property="fullName"/></h3>
+<ul>
+ <li>[TODO] Edit Profile</li>
+ <li>[TODO] Logout</li>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/RegisterForm.jsp b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/RegisterForm.jsp
new file mode 100644
index 0000000..f5ffd21
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/RegisterForm.jsp
@@ -0,0 +1,94 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<html:html>
+ <head>
+ <title><bean:message key="Register.title"/></title>
+ </head>
+
+ <body>
+
+ <html:errors/>
+
+ <html:form action="/RegisterSave">
+ <table border="0" width="100%">
+
+ <tr>
+ <th align="right">
+ Username:
+ </th>
+ <td align="left">
+ <html:text property="username" size="16" maxlength="16"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Password:
+ </th>
+ <td align="left">
+ <html:password property="password" size="16"
+ maxlength="16"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Confirm Password:
+ </th>
+ <td align="left">
+ <html:password property="password2" size="16"
+ maxlength="16"/>
+ </td>
+ </tr>
+
+ <!-- Lab 1-2: Insert remaining fields from use case -->
+
+ <tr>
+ <th align="right">
+ Fullname:
+ </th>
+ <td align="left">
+ <html:text property="fullName" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ From Address:
+ </th>
+ <td align="left">
+ <html:text property="fromAddress" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Reply To Address:
+ </th>
+ <td align="left">
+ <html:text property="replyToAddress" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">
+ <html:submit property="DO_SUBMIT">
+ <bean:message key="button.submit"/>
+ </html:submit>
+ </td>
+ <td align="left">
+ <html:reset property="DO_RESET">
+ <bean:message key="button.reset"/>
+ </html:reset>
+
+ <html:cancel/>
+ </td>
+ </tr>
+
+ </table>
+ </html:form>
+
+ </body>
+</html:html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Logon-configure.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Logon-configure.xml
new file mode 100644
index 0000000..a0eb8ac
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Logon-configure.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="LogonForm"
+ extends="BaseForm"/>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="/Logon"
+ name="LogonForm"
+ forward="/LogonForm.jsp"
+ validate="false"/>
+
+ <action
+ path="/LogonPost"
+ type="org.apache.struts.apps.mailreader.course.LogonAction"
+ name="LogonForm"
+ scope="request"
+ validate="true"
+ input="Input">
+ <forward
+ name="Input"
+ path="/Logon.do"/>
+ <forward
+ name="Success"
+ redirect="true"
+ path="/MainMenu.do"/>
+ </action>
+
+ </action-mappings>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Logon-validate.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Logon-validate.xml
new file mode 100644
index 0000000..7797d1b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Logon-validate.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">
+
+<form-validation>
+ <formset>
+ <form name="LogonForm">
+
+ <field property="username"
+ depends="required">
+ <arg key="username.label"/>
+ </field>
+
+ <field property="password"
+ depends="required, minlength,maxlength">
+ <arg key="password.label"/>
+ <arg key="${var:minlength}"
+ name="minlength"
+ resource="false"/>
+ <arg key="${var:maxlength}"
+ name="maxlength"
+ resource="false"/>
+
+ <var>
+ <var-name>
+ maxlength
+ </var-name>
+ <var-value>
+ 16
+ </var-value>
+ </var>
+ <var>
+ <var-name>
+ minlength
+ </var-name>
+ <var-value>
+ 3
+ </var-value>
+ </var>
+ </field>
+ </form>
+ </formset>
+</form-validation>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Register-configure.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Register-configure.xml
new file mode 100644
index 0000000..a6072ee
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Register-configure.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="RegisterForm"
+ extends="BaseForm">
+ <form-property
+ name="password2"
+ type="java.lang.String"/>
+ <form-property
+ name="fullName"
+ type="java.lang.String"/>
+ <form-property
+ name="fromAddress"
+ type="java.lang.String"/>
+ <form-property
+ name="replyToAddress"
+ type="java.lang.String"/>
+ </form-bean>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="/Register"
+ name="RegisterForm"
+ forward="/RegisterForm.jsp"
+ validate="false"/>
+
+ <action path="/RegisterSave"
+ name="RegisterForm"
+ type="org.apache.struts.apps.mailreader.course.RegisterAction"
+ validate="true"
+ input="Input">
+ <forward
+ name="Input"
+ path="/Register.do"/>
+ <forward
+ name="Success"
+ redirect="true"
+ path="/MainMenu.do"/>
+ </action>
+
+ </action-mappings>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Register-validate.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Register-validate.xml
new file mode 100644
index 0000000..4d06c11
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/Register-validate.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">
+
+<form-validation>
+
+ <formset>
+ <form name="RegisterForm">
+
+ <field property="username" depends="required">
+ <arg position="0" key="username.label"/>
+ </field>
+
+ <field property="password" depends="required">
+ <arg position="0" key="password.label"/>
+ </field>
+
+ <field property="password2" depends="required,validwhen">
+ <arg position="0" key="password2.label"/>
+ <var>
+ <var-name>test</var-name>
+ <var-value>(*this* == password)</var-value>
+ </var>
+ </field>
+
+ <!-- Lab 1-2: Insert remaining fields from use case -->
+
+ <field property="fullName"
+ depends="required">
+ <arg key="fullName.label"/>
+ </field>
+
+ <field property="fromAddress"
+ depends="required,email">
+ <arg key="fromAddress.label"/>
+ </field>
+
+ <field property="replyToAddress"
+ depends="email">
+ <arg key="replyToAddress.label"/>
+ </field>
+
+ </form>
+ </formset>
+</form-validation>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/classes/MessageResources.properties b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/classes/MessageResources.properties
new file mode 100644
index 0000000..9f8a92a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/classes/MessageResources.properties
@@ -0,0 +1,107 @@
+# Standard error messages for validator framework checks
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+errors.required={0} is required.
+errors.email={0} is not a valid email address.
+username.label=Username
+password.label=Password
+password2.label=Confirm Password
+# Lab 1-2: Insert remaining fields from use case
+fullName.label=Full Name
+fromAddress.label=From Address
+replyToAddress.label=Reply To Address
+# Lab 1-4: Resources for Logon use case
+button.cancel=Cancel
+button.confirm=Confirm
+button.submit=Submit
+button.reset=Reset
+button.submit.id=DO_SUBMIT
+button.reset.id=DO_RESET
+
+MainMenu.title=Main Menu
+Register.title=Register Form
+Logon.title=Logon Form
+
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+button.save=Save
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+error.database.missing=User database is missing, cannot validate logon credentials
+error.fromAddress.format=Invalid format for From Address
+error.fromAddress.required=From Address is required
+error.fullName.required=Full Name is required
+error.host.required=Mail Server is required
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+error.password.mismatch=Invalid username and/or password, please try again
+error.replyToAddress.format=Invalid format for Reply To Address
+error.transaction.token=Cannot submit this form out of order
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+error.username.required=Username is required
+error.username.unique=That username is already in use - please select another
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.logon=Log on to the MailReader Demonstration Application
+index.registration=Register with the MailReader Demonstration Application
+index.title=MailReader Demonstration Application
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+mainMenu.heading=Main Menu Options for
+mainMenu.logoff=Log off MailReader Demonstration Application
+mainMenu.registration=Edit your user registration profile
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+prompt.autoConnect=Auto Connect
+prompt.fromAddress=From Address
+prompt.fullName=Full Name
+prompt.mailHostname=Mail Server
+prompt.mailPassword=Mail Password
+prompt.mailServerType=Server Type
+prompt.mailUsername=Mail Username
+prompt.password=Password
+prompt.password2=(Repeat) Password
+prompt.replyToAddress=Reply To Address
+prompt.username=Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+registration.title.create=Register for the MailReader Demonstration Application
+registration.title.edit=Edit Registration for the MailReader Demonstration Application
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.minlength={0} cannot be less than {1} characters.
+errors.maxlength={0} cannot be greater than {1} characters.
+errors.invalid={0} is invalid.
+errors.byte={0} must be an byte.
+errors.short={0} must be an short.
+errors.integer={0} must be an integer.
+errors.long={0} must be an long.
+errors.float={0} must be an float.
+errors.double={0} must be an double.
+errors.date={0} is not a date.
+errors.range={0} is not in the range {1} through {2}.
+errors.creditcard={0} is not a valid credit card number.
+errors.literal={0}
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/database.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/database.xml
new file mode 100644
index 0000000..c199a5e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/database.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user"
+ password="pass"
+ fullName="John Q. User"
+ fromAddress="John.User@somewhere.com">
+ <subscription
+ host="mail.hotmail.com"
+ type="pop3"
+ autoConnect="false"
+ username="user1234"
+ password="bar">
+ </subscription>
+ <subscription
+ host="mail.yahoo.com"
+ type="imap"
+ autoConnect="false"
+ username="jquser"
+ password="foo">
+ </subscription>
+ </user>
+</database>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config-debug.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config-debug.xml
new file mode 100644
index 0000000..47b4033
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config-debug.xml
@@ -0,0 +1,10 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"
+ summary="true"
+ saveresponse="true"
+ resultpath="results"
+ resultfile="result.txt"
+ showhtmlparseroutput="true"/>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config-tidy.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config-tidy.xml
new file mode 100644
index 0000000..789af67
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config-tidy.xml
@@ -0,0 +1,10 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"
+ summary="false"
+ saveresponse="false"
+ resultpath="results"
+ resultfile="result.txt"
+ showhtmlparseroutput="true"/>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/form-submit.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/form-submit.xml
new file mode 100644
index 0000000..435cdc7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/form-submit.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Click Submit"
+ name="${button.submit.id}"/>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-fail.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-fail.xml
new file mode 100644
index 0000000..03ffdef
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-fail.xml
@@ -0,0 +1,2 @@
+ &form-submit;
+ &logon-page;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-hermes.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-hermes.xml
new file mode 100644
index 0000000..4b9e2c9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-hermes.xml
@@ -0,0 +1,11 @@
+&logon-open;
+<setInputField
+ description="Registered username"
+ name="username"
+ value="hermes"/>
+<setInputField
+ description="Correct password"
+ name="password"
+ value="m3dus4"/>
+ &form-submit;
+ &menu-page;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-open.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-open.xml
new file mode 100644
index 0000000..7c14500
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-open.xml
@@ -0,0 +1,4 @@
+<invoke
+ description="Pass logon"
+ url="Logon.do"/>
+ &logon-page;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-page.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-page.xml
new file mode 100644
index 0000000..9bab591
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/logon-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Logon page title"
+ text="${Logon.title}"/>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/menu-page.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/menu-page.xml
new file mode 100644
index 0000000..a583c17
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/menu-page.xml
@@ -0,0 +1,3 @@
+<verifytitle
+ description="Menu page title"
+ text="${MainMenu.title}"/>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-hermes.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-hermes.xml
new file mode 100644
index 0000000..e919b7d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-hermes.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="hermes"/>
+<setInputField
+ description="password"
+ name="password"
+ value="m3dus4"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="m3dus4"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Hermes Katsopolis"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="hermes@somewhere.com"/>
+ &form-submit;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..49017f7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,4 @@
+<invoke
+ description="Open Register screen"
+ url="Register.do"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..e267249
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration screen title"
+ text="${Register.title}"/>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/struts-config.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/struts-config.xml
new file mode 100644
index 0000000..49ee5c0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/struts-config.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="BaseForm"
+ type="org.apache.struts.validator.DynaValidatorForm">
+ <form-property
+ name="username"
+ type="java.lang.String"/>
+ <form-property
+ name="password"
+ type="java.lang.String"/>
+ </form-bean>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="/MainMenu"
+ forward="/MainMenu.jsp"
+ validate="false"/>
+
+ </action-mappings>
+
+ <controller
+ inputForward="true"/>
+
+ <message-resources
+ parameter="MessageResources"/>
+
+ <plug-in
+ className="org.apache.struts.apps.mailreader.course.MemoryDatabasePlugIn">
+ <set-property
+ property="pathname"
+ value="/WEB-INF/database.xml"/>
+ </plug-in>
+
+ <plug-in
+ className="org.apache.struts.validator.ValidatorPlugIn">
+ <set-property
+ property="pathnames"
+ value="/org/apache/struts/validator/validator-rules.xml,
+ /WEB-INF/Logon-validate.xml,/WEB-INF/Register-validate.xml"
+ />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/struts-html.tld b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/struts-html.tld
new file mode 100644
index 0000000..c44843b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/struts-html.tld
@@ -0,0 +1,8752 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
+ "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+<taglib>
+ <tlib-version>1.3</tlib-version>
+ <jsp-version>1.2</jsp-version>
+ <short-name>html</short-name>
+ <uri>http://struts.apache.org/tags-html</uri>
+ <description>
+ <![CDATA[
+ <p>
+ This taglib contains tags used to create struts
+ input forms, as well as other tags generally useful
+ in the creation of HTML-based user interfaces.
+ </p>
+
+ <p>Many of the tags in this tag library will throw a
+ <code>JspException</code> at runtime when they are utilized incorrectly
+ (such as when you specify an invalid combination of tag attributes). JSP
+ allows you to declare an "error page" in the <code><%@ page %></code>
+ directive. If you wish to process the actual exception that caused the
+ problem, it is passed to the error page as a request attribute under key
+ <code>org.apache.struts.action.EXCEPTION</code>.</p>
+ ]]>
+ </description>
+ <tag>
+ <name>base</name>
+ <tag-class>org.apache.struts.taglib.html.BaseTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><base></code> Element</strong></p>
+
+ <p>Renders an HTML <code><base></code> element with an
+ <code>href</code> attribute pointing to the absolute location of
+ the enclosing JSP page. This tag is valid only when nested inside
+ an HTML <code><head></code> element.</p>
+
+ <p>This tag is useful because it allows you to use relative URL
+ references in the page that are calculated based on the URL of the
+ page itself, rather than the URL to which the most recent submit
+ took place (which is where the browser would normally resolve
+ relative references against).</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target for this base reference.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>server</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The server name to use instead of request.getServerName().</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ref</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The reference from which the base uri will created. Possible values are:
+ </p>
+ <ul>
+ <li><code>page</code> - The base uri will be the jsp page location. (default)</li>
+ <li><code>site</code> - The base uri will be the application context path.</li>
+ </ul>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.3</dd></dl>
+
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>button</name>
+ <tag-class>org.apache.struts.taglib.html.ButtonTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render A Button Input Field</strong></p>
+
+ <p>
+ Renders an HTML <input> element of type
+ <code>button</code>, populated from the specified value or the
+ content of this tag body. This tag is only valid when nested
+ inside a form tag body.
+ </p>
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> if this input field should be
+ disabled.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Click"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>cancel</name>
+ <tag-class>org.apache.struts.taglib.html.CancelTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Cancel Button
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type submit. This tag is only
+ valid when nested inside a form tag body. Pressing of this submit
+ button causes the action servlet to bypass calling the associated
+ form bean validate() method. The action is called normally.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ <strong>WARNING</strong> - If you set this attribute to a
+ value other than the default, this will <em>NOT</em> be
+ recognized as the cancel key by the Struts controller servlet
+ or the <code>Action.isCancelled()</code> method. You will
+ need to do your own cancel detection.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Cancel"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>checkbox</name>
+ <tag-class>org.apache.struts.taglib.html.CheckboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, populated from the specified
+ value or the specified property of the bean associated
+ with our current form. This tag is only valid when
+ nested inside a form tag body.</p>
+
+ <p><strong>NOTE</strong>: The underlying property value
+ associated with this field should be of type <code>boolean</code>,
+ and any <code>value</code> you specify should correspond to one
+ of the Strings that indicate a true value ("true", "yes", or
+ "on"). If you wish to utilize a set of related String values,
+ consider using the <code>multibox</code> tag.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize unchecked checkboxes, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement setting the corresponding
+ boolean property to <code>false</code> in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted. If not specified,
+ the value "on" will be returned.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>errors</name>
+ <tag-class>org.apache.struts.taglib.html.ErrorsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated error messages.
+ </strong></p>
+
+ <p>Displays a set of error messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, an <code>ActionErrors</code>
+ object, a String, or a String array in request scope. If
+ such a bean is not found, nothing will be rendered.</p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name, with optional
+ definitions of message keys specified in the following
+ attributes:</p>
+ <ul>
+ <li><strong>header</strong> - Text that will be rendered
+ before the error messages list. Typically, this message text
+ will end with <code><ul></code> to start the
+ error messages list (default "errors.header").</li>
+ <li><strong>footer</strong> - Text that will be rendered
+ after the error messages list. Typically, this message text
+ will begin with <code></ul></code> to end the error
+ messages list (default "errors.footer").</li>
+ <li><strong>prefix</strong> - Text that will be rendered
+ before each individual error in the list (default "errors.prefix").</li>
+ <li><strong>suffix</strong> - Text that will be rendered
+ after each individual error in the list (default "errors.suffix").</li>
+ </ul>
+
+ <p>See the <code>messages</code> tag for an alternative to this tag that
+ does not rely on HTML in your <code>MessageResources</code>.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of error messages has finished.
+ Defaults to "errors.footer" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of error messages begins.
+ Defaults to "errors.header" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>prefix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before an error message.
+ Defaults to "errors.prefix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which error messages should be
+ displayed. If not specified, all error messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>suffix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after an error message.
+ Defaults to "errors.suffix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>file</name>
+ <tag-class>org.apache.struts.taglib.html.FileTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A File Select Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type file, defaulting to
+ the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ <p>
+ As with the corresponding HTML <input> element, the
+ enclosing form element must specify "POST" for the <code>method</code>
+ attribute, and "multipart/form-data" for the <code>enctype</code>
+ attribute. For example:
+ </p>
+ <pre>
+ <html:form method="POST" enctype="multipart/form-data">
+ <html:file property="theFile" />
+ </html:form></pre>
+
+ <p>
+ WARNING: In order to correctly recognize uploaded files, the ActionForm bean
+ associated with this form must include a statement setting the corresponding
+ org.apache.struts.upload.FormFile property to null in the reset() method.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>accept</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Comma-delimited set of content types that the server you submit to
+ knows how to process. This list can be used by the client browser
+ to limit the set of file options that is made available for selection.
+ If not specified, no content type list will be sent.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. This is ignored
+ by most browsers. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Size of the file selection box to be displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ <strong>NOTE</strong>: When setting this to some value, whether
+ intentional or as the result (for example) of validation errors
+ forcing the user back to the original jsp, this value is ignored
+ by most browsers (for security reasons).
+ This means that your users will have to re-select any previously
+ selected files when submitting the form. Opera web browser will
+ prompt the user so they have a chance to abort the submit.
+ </p>
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value or body content (if any) if
+ property is not specified]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>form</name>
+ <tag-class>org.apache.struts.taglib.html.FormTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Define An Input Form
+ </strong></p>
+
+ <p>
+ Renders an HTML <form> element whose contents are described
+ by the body content of this tag. The form implicitly interacts
+ with the specified request scope or session scope bean to populate
+ the input fields with the current property values from the bean.
+ </p>
+ <p>
+ The form bean is located, and created if necessary, based on the
+ form bean specification for the associated <code>ActionMapping</code>.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this form will be submitted. This
+ value is also used to select the ActionMapping we are
+ assumed to be processing, from which we can identify
+ the appropriate form bean and scope. If a value is not
+ provided, the original URI (servletPath) for the request is
+ used. </p>
+
+ <p>If you are using extension mapping for selecting the
+ controller servlet, this value should be equal to the
+ <code>path</code> attribute of the corresponding
+ <code><action></code> element, optionally
+ followed by the correct extension suffix.</p>
+
+ <p>If you are using path mapping to select the
+ controller servlet, this value should be exactly equal
+ to the <code>path</code> attribute of the corresponding
+ <code><action></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>acceptCharset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The list of character encodings for input data that the server should
+ accept.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ disabled.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>enctype</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The content encoding to be used to submit this form, if the method
+ is POST. This must be set to "multipart/form-data" if you are using
+ the file tag to enable file upload. If not specified, the browser
+ default (normally "application/x-www-form-urlencoded") is used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The field name (among the fields on this form) to which initial
+ focus will be assigned with a JavaScript function. If not specified,
+ no special JavaScript for this purpose will be rendered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focusIndex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If the focus field is a field array, such as a radio button group, you can
+ specify the index in the array to receive focus.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The HTTP method that will be used to submit this request
+ (GET, POST). [POST]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onreset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is reset.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onsubmit</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ read only.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The form's focus <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHMTL mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Window target to which this form is submitted, such as
+ for use in framed presentations.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>frame</name>
+ <tag-class>org.apache.struts.taglib.html.FrameTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML frame element</strong></p>
+
+
+ <p>Renders an HTML <code><frame></code> element
+ with processing for the <code>src</code> attribute that is
+ identical to that performed by the <code><html:link></code>
+ tag for the <code>href</code> attribute. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies.</p>
+
+ <p>The base URL for this frame is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and application
+ prefix.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ logical name of a global Action that contains the actual
+ content-relative URI of the destination of this transfer.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameborder</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should a frame border be generated around this frame (1)
+ or not (0)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Value for the <code>name</code> attribute of the rendered
+ <code><frame></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>longdesc</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>URI of a long description of the frame. This description
+ should supplement the short description provided by the
+ <code>title</code> attribute, and may be particularly useful
+ for non-visual user agents.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginheight</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its top and bottom margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginwidth</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its left and right margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>noresize</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Should users be disallowed from resizing the frame?
+ (true, false).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scrolling</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should scroll bars be created unconditionally (yes),
+ never (no), or only when needed (auto)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>hidden</name>
+ <tag-class>org.apache.struts.taglib.html.HiddenTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Hidden Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type hidden, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>write</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Should the value of this field also be rendered to the
+ response page to make it visible, in addition to creating
+ an HTML type="hidden" element? By default, only the
+ hidden element is created.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>html</name>
+ <tag-class>org.apache.struts.taglib.html.HtmlTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><html></code> Element</strong></p>
+
+ <p>Renders an HTML <code><html></code> element with
+ language attributes extracted from the user's current Locale
+ object, if there is one.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>lang</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Renders a lang attribute with the locale stored in the user's session. If not
+ found in the session, the language from the <code>Accept-Language</code>
+ HTTP header is used. If still not found, the default language for the server
+ is used.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>xhtml</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> in order to render
+ <code>xml:lang</code> and <code>xmlns</code> attributes
+ on the generated <code>html</code> element. This also
+ causes all other html tags to render as XHTML 1.0 (the
+ <html:xhtml/> tag has a similar purpose).
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>image</name>
+ <tag-class>org.apache.struts.taglib.html.ImageTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render an input tag of type "image"
+ </strong></p>
+
+
+ <p>Renders an HTML <code><input></code> tag of type
+ "image". The base URL for this image is calculated directly
+ based on the value specified in the <code>src</code> or
+ <code>page</code> attributes, or indirectly by looking up a
+ message resource string based on the <code>srcKey</code> or
+ <code>pageKey</code> attributes. You <strong>must</strong>
+ specify exactly one of these attributes.</p>
+
+ <p>If you would like to obtain the coordinates of the mouse
+ click that submitted this request, see the information below
+ on the <code>property</code> attribute.</p>
+
+ <p>This tag is only valid when nested inside a form tag body.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alignment option for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width (in pixels) of the border around this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The session attribute key for the Locale used to select
+ internationalized messages. If not specified, defaults to the
+ Struts standard value.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under
+ the mouse pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under
+ the mouse pointer but the pointer was moved outside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not
+ under the mouse pointer but the pointer is moved inside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path of the image for this
+ input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ module-relative path of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The property name of this image tag. The parameter names
+ for the request will appear as "property.x" and "property.y",
+ the x and y representing the coordinates of the mouse click
+ for the image. A way of retrieving these values through a
+ form bean is to define getX(), getY(), setX(), and setY()
+ methods, and specify your property as a blank string
+ (property="").</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The value that will be submitted if this image button
+ is pressed.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>img</name>
+ <tag-class>org.apache.struts.taglib.html.ImgTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML img tag</strong></p>
+
+
+ <p>Renders an HTML <code><img></code> element with
+ the image at the specified URL. Like the link tag, URL
+ rewriting will be applied automatically to the value
+ specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> to maintain session state
+ in the absence of cookies. This will allow dynamic
+ generation of an image where the content displayed for this
+ image will be taken from the attributes of this tag.</p>
+
+ <p>The base URL for this image is calculated directly based on
+ the value specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> or <code>page</code>,
+ or indirectly by looking up a message resource string based on
+ the <code>srcKey</code> or <code>pageKey</code> attributes.
+ You <strong>must</strong> specify exactly one of these
+ attributes.</p>
+
+ <p>Normally, the <code>src</code>, <code>page</code>, or
+ <code>action</code> that you specify will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the <code>src</code> URL --
+ specify a single parameter with the <code>paramId</code>
+ attribute (at its associated attributes to select the value),
+ or specify the <code>name</code> (and optional
+ <code>property</code>) attributes to select a
+ <code>java.util.Map</code> bean that contains one or more
+ parameter ids and corresponding values.</p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter will be called on the JSP bean identified
+ by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ <code>src</code> URL. The value associated with each key
+ must be either a String or a String array representing the
+ parameter value(s), or an object whose toString() method
+ will be called. If a String array is specified, more than
+ one value for the same query parameter name will be
+ created.</p>
+
+ <p>You can specify the alternate text for this image (which
+ most browsers display as pop-up text block when the user
+ hovers the mouse over this image) either directly, through
+ the <code>alt</code> attribute, or indirectly from a message
+ resources bundle, using the <code>bundle</code> and
+ <code>altKey</code> attributes.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Where the image is aligned to. Can be one of the
+ following attributes:</p>
+ <ul>
+ <li>left - left justify, wrapping text on right</li>
+ <li>right -right justify, wrapping test on left</li>
+ <li>top - aligns the image with the top of the text on
+ the same row</li>
+ <li>middle - aligns the image's vertical center with the
+ text base line</li>
+ <li>bottom - aligns the image with the bottom of the
+ text's base line</li>
+ <li>texttop - aligns the image's top with that of the
+ text font on the same line</li>
+ <li>absmiddle - aligns the image's vertical center with the
+ absolute center of the text</li>
+ <li>absbottom - aligns the image with the absolute bottom
+ of the text font on the same row</li>
+ </ul>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>And alternative text to be displayed in browsers that
+ don't support graphics. Also used often as type of
+ context help over images.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the border surrounding the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>height</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The height of the image being displayed. This parameter
+ is very nice to specify (along with <code>width</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>hspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of horizontal spacing between the icon and
+ the text. The text may be in the same paragraph, or
+ be wrapped around the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>imageName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scriptable name to be defined within this page, so
+ that you can reference it with intra-page scripts. In other
+ words, the value specified here will render a "name" element
+ in the generated image tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ismap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the server-side map that this image belongs
+ to.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request or session Locale attribute used
+ to look up internationalized messages.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated src URL. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path, starting with a slash, of
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>page</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify either the <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the module-relative path for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The action, starting with a slash, that will render
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>action</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify the <code>action</code>,
+ <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this src URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the src URL. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this image will be transferred from
+ This image may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. This value will be used unmodified (other
+ than potential URL rewriting) as the value of the "src"
+ attribute in the rendered tag. You <strong>must</strong>
+ specify either the <code>page</code> attribute or the
+ <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the URL of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>usemap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the map as defined within this page for
+ mapping hot-spot areas of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>vspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of vertical spacing between the icon and
+ the text, above and below.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>width</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the image being displayed. This parameter
+ is very nice to specify (along with <code>height</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>javascript</name>
+ <tag-class>
+ org.apache.struts.taglib.html.JavascriptValidatorTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render JavaScript validation based on the
+ validation rules loaded by the ValidatorPlugIn.
+ </strong></p>
+
+ <p>
+ Render JavaScript validation based on the
+ validation rules loaded by the <code>ValidatorPlugIn</code>.
+ The set of validation rules that should be generated is based
+ on the formName attribute passed in, which should match
+ the name attribute of the form element in the xml file.
+ </p>
+ <p>
+ The dynamicJavascript and staticJavascript attributes
+ default to true, but if dynamicJavascript is set to <code>true</code>
+ and staticJavascript is set to <code>false</code> then only
+ the dynamic JavaScript will be rendered. If dynamicJavascript
+ is set to <code>false</code>
+ and staticJavascript is set to <code>true</code> then only
+ the static JavaScript will be rendered which can then be put in
+ separate JSP page so the browser can cache the static JavaScript.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>cdata</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ If set to "true" and XHTML has been enabled, the JavaScript will
+ be wrapped in a CDATA section to prevent XML parsing. The default is
+ "true" to comply with the W3C's recommendation.
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>dynamicJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the dynamic JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>formName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The key (form name) to retrieve a specific
+ set of validation rules. If "dynamicJavascript" is set
+ to <code>true</code> and formName is missing or is not
+ recognized by the <code>ValidatorPlugIn</code>, a
+ JspException will be thrown.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The alternate JavaScript method name to be used
+ instead of the of the default. The default is
+ 'validate' concatenated in front of
+ the key (form name) passed in (ex: validateRegistrationForm).
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ <description>
+ <![CDATA[
+ <p>
+ The current page of a set of validation rules
+ if the page attribute for the field element
+ in the xml file is in use.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHTML mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The src attribute's value when defining
+ the html script element.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>staticJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the static JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>htmlComment</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to enclose the javascript
+ with HTML comments. This attribute is ignored in XHTML
+ mode because the script would be deleted by the XML parser. See
+ the cdata attribute for details on hiding scripts from XML
+ parsers.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>link</name>
+ <tag-class>org.apache.struts.taglib.html.LinkTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML anchor or hyperlink</strong></p>
+
+
+ <p>Renders an HTML <code><a></code> element as an
+ anchor definition (if "linkName" is specified) or as a
+ hyperlink to the specified URL. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies. The content displayed for this
+ hyperlink will be taken from the body of this tag.</p>
+
+ <p>The base URL for this hyperlink is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there. If the forward is module-relative then
+ it must point to an action and NOT to a page.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ name of a <code>Action</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and module
+ prefix.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then indexed parameter with name from indexId attribute
+ will be added to the query string. Indexed parameter looks like
+ "index[32]". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By this attribute different name for the indexed parameter can be
+ specified. Take a look to the "indexed" attribute for details.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>linkName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The anchor name to be defined within this page, so that
+ you can reference it with intra-page hyperlinks. In other
+ words, the value specified here will render a "name" element
+ in the generated anchor tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element loses input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse double click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse move event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse out event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse over event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute,
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The tab order (ascending positive integers) for
+ this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target in which the resource requested by this
+ hyperlink will be displayed, for example in a framed
+ presentation.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>messages</name>
+ <tag-class>org.apache.struts.taglib.html.MessagesTag</tag-class>
+ <tei-class>org.apache.struts.taglib.html.MessagesTei</tei-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated messages.
+ </strong></p>
+
+ <p>Displays a set of messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, <code>ActionErrors</code> object, a String,
+ or a String array in any scope. If
+ such a bean is not found, nothing will be rendered. The messages are
+ placed into the page scope in the body of this tag where they can be displayed
+ by standard JSP methods. (For example: <code><bean:write></code>,<code><c:out></code>)
+ </p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>id</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ The name of a page scope JSP bean that will contain the current
+ element of the collection of messages on each iteration, if it is not
+ <code>null</code>.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the bean in any scope under which our messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which messages should be
+ displayed. If not specified, all messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of messages begins.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of messages has finished.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>message</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By default the tag will retrieve the bean it will
+ iterate over from the <code>Globals.ERROR_KEY</code> constant string,
+ but if this attribute is set to 'true' the bean
+ will be retrieved from the <code>Globals.MESSAGE_KEY</code>
+ constant string. Also if this is set to 'true', any value
+ assigned to the name attribute will be ignored.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>multibox</name>
+ <tag-class>org.apache.struts.taglib.html.MultiboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, whose "checked" status is
+ initialized based on whether the specified value
+ matches one of the elements of the underlying
+ property's array of current values. This element is
+ useful when you have large numbers of checkboxes, and
+ prefer to combine the values into a single
+ array-valued property instead of multiple boolean
+ properties. This tag is only valid when nested
+ inside a form tag body.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where none of the associated checkboxes
+ are selected, the <code>ActionForm</code> bean
+ associated with this form must include a statement
+ setting the corresponding array to zero length in the
+ <code>reset()</code> method.</p>
+
+ <p>The value to be returned to the server, if this checkbox is
+ selected, must be defined by one of the following methods:</p>
+ <ul>
+ <li>Specify a <code>value</code> attribute, whose contents will
+ be used literally as the value to be returned.</li>
+ <li>Specify no <code>value</code> attribute, and the nested
+ body content of this tag will be used as the value to be
+ returned.</li>
+ </ul>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>option</name>
+ <tag-class>org.apache.struts.taglib.html.OptionTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Option
+ </strong></p>
+
+ <p>Render an HTML <code><option></code> element,
+ representing one of the choices for an enclosing
+ <code><select></code> element. The text displayed to the
+ user comes from either the body of this tag, or from a message
+ string looked up based on the <code>bundle</code>,
+ <code>locale</code>, and <code>key</code> attributes.</p>
+
+ <p>If the value of the corresponding bean property matches the
+ specified value, this option will be marked selected. This tag
+ is only valid when nested inside a
+ <code><html:select></code> tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this option should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>key</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If specified, defines the message key to be looked up in
+ the resource bundle specified by <code>bundle</code> for
+ the text displayed to the user for this option. If not
+ specified, the text to be displayed is taken from the body
+ content of this tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attributes key for the Locale instance to use
+ for looking up the message specified by the
+ <code>key</code> attribute. If not specified, uses the
+ standard Struts session attribute name.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to be submitted for this field if this option is
+ selected by the user.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>options</name>
+ <tag-class>org.apache.struts.taglib.html.OptionsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:optionsCollection></code> elements.</p>
+
+ <p>This tag operates in one of two major modes, depending on
+ whether or not the <code>collection</code> attribute is
+ specified. If the <code>collection</code> attribute is
+ included, the following rules apply:</p>
+ <ul>
+ <li>The <strong>collection</strong> attribute is interpreted
+ as the name of a JSP bean, in some scope, that itself
+ represents a collection of individual beans, one per option
+ value to be rendered.</li>
+ <li>The <strong>property</strong> attribute is interpreted as
+ the name of a property of the individual beans included in
+ the collection, and is used to retrieve the value that will
+ be returned to the server if this option is selected.</li>
+ <li>The <strong>labelProperty</strong> attribute is interpreted
+ as the name of a property of the individual beans included
+ in the collection, and is used to retrieve the label that
+ will be displayed to the user for this option. If the
+ <code>labelProperty</code> attribute is not specified, the
+ property named by the <code>property</code> attribute will
+ be used to select both the value returned to the server and
+ the label displayed to the user for this option.</li>
+ </ul>
+
+ <p>If the <code>collection</code> attribute is not specified,
+ the rules described in the remainder of this section apply.</p>
+
+ <p>The collection of values actually selected depends on the presence or
+ absence of the <code>name</code> and <code>property</code> attributes. The
+ following combinations are allowed:</p>
+ <ul>
+ <li><em>Only <code>name</code> is specified</em> - The value of this attribute
+ is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>property</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>name</code> and <code>property</code> are specified</em> -
+ The value of the <code>name</code> attribute identifies a JSP bean
+ in some scope. The value of the <code>property</code> attribute is the
+ name of some property of that bean which will return the collection.</li>
+ </ul>
+
+ <p>The collection of labels displayed to the user can be the same as the
+ option values themselves, or can be different, depending on the presence or
+ absence of the <code>labelName</code> and <code>labelProperty</code>
+ attributes. If this feature is used, the collection of labels must contain
+ the same number of elements as the corresponding collection of values.
+ The following combinations are allowed:</p>
+ <ul>
+ <li><em>Neither <code>labelName</code> nor <code>labelProperty</code> is
+ specified</em> - The labels will be the same as the option values
+ themselves.</li>
+ <li><em>Only <code>labelName</code> is specified</em> - The value of this
+ attribute is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>labelProperty</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>labelName</code> and <code>labelProperty</code> are
+ specified</em> - The value of the <code>labelName</code> attribute
+ identifies a JSP bean in some scope. The value of the
+ <code>labelProperty</code> attribute is the name of some property of
+ that bean which will return the collection.</li>
+ </ul>
+
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>collection</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) which is itself a
+ Collection of other beans, each of which has properties
+ named by the "property" and "labelProperty" attributes
+ that are used to retrieve the value and label for each
+ option, respectively.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of labels to
+ be displayed to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the labelName
+ attribute, that will return the collection of labels to be displayed
+ to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of
+ values to be returned to the server for these options. If not
+ specified, the form bean associated with our form is assumed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of values to returned
+ to the server for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>optionsCollection</name>
+ <tag-class>
+ org.apache.struts.taglib.html.OptionsCollectionTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:options></code> elements.</p>
+
+ <p>This tag operates on a collection of beans, where each bean
+ has a <strong>label</strong> property and a <strong>value</strong>
+ property. The actual names of these properties can be configured
+ using the <code>label</code> and <code>value</code> attributes
+ of this tag.</p>
+
+ <p>This tag differs from the <code><html:options></code> tag
+ in that it makes more consistent use of the <code>name</code> and
+ <code>property</code> attributes, and allows the collection to be
+ more easily obtained from the enclosing form bean.</p>
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>label</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the label to be rendered for each option. Defaults to "label".
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of objects to be
+ rendered for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the value to be rendered for each option. Defaults to "value".
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>password</name>
+ <tag-class>org.apache.struts.taglib.html.PasswordTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Password Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type password, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>redisplay</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Boolean flag indicating whether or not existing values
+ will be redisplayed if they exist. Even though the
+ redisplayed value will be shown as asterisks on the
+ visible HTML page, the cleartext of the actual password
+ value will be visible though the "Show Page Source"
+ menu option of the client browser. You may wish to
+ set this value to <code>false</code> on login pages.
+ Defaults to <code>true</code> for consistency with
+ all other form tags that redisplay their contents.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any)]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>radio</name>
+ <tag-class>org.apache.struts.taglib.html.RadioTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Radio Button Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type radio, populated from
+ the specified property of the bean associated with our current form.
+ This tag is only valid when nested inside a form tag body.
+ </p>
+ <p>
+ If an iterator is used to render a series of radio tags, the
+ idName attribute may be used to specify the name of the bean
+ exposed by the iterator. In this case, the value attribute is
+ used as the name of a property on the idName bean that returns
+ the value of the radio tag in this iteration.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The corresponding bean property for this radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>idName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the bean (in some scope) that will return the
+ value of the radio tag. Usually exposed
+ by an iterator. When the idName attribute is
+ present, the value attribute is used as the name of the
+ property on the idName bean that will return the
+ value of the radio tag for this iteration.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>reset</name>
+ <tag-class>org.apache.struts.taglib.html.ResetTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Reset Button Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type reset.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the input field that will be generated.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button.
+ [Body of this tag (if any), or "Reset"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>rewrite</name>
+ <tag-class>org.apache.struts.taglib.html.RewriteTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an URI</strong></p>
+
+ <p>Renders a request URI based on exactly the same rules
+ as the <code><a href="#link">link</a></code> tag does,
+ but without creating
+ the <code><a></code> hyperlink. This value is useful
+ when you want to generate a string constant for use by
+ a JavaScript procedure.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.0</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>select</name>
+ <tag-class>org.apache.struts.taglib.html.SelectTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Element
+ </strong></p>
+
+ <p>Renders an HTML <select> element, associated
+ with a bean property specified by our attributes. This
+ tag is only valid when nested inside a form tag body.
+ </p>
+
+ <p>This tag operates in two modes, depending upon the
+ state of the <code>multiple</code> attribute, which
+ affects the data type of the associated property you
+ should use:</p>
+ <ul>
+ <li><em>multiple="true" IS NOT selected</em> -
+ The corresponding property should be a scalar
+ value of any supported data type.</li>
+ <li><em>multiple="true" IS selected</em> -
+ The corresponding property should be an array
+ of any supported data type.</li>
+ </ul>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where no selection at all is made, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement resetting the scalar property
+ to a default value (if <code>multiple</code> is not
+ set), or the array property to zero length (if
+ <code>multiple</code> is set) in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>multiple</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If set to any arbitrary value, the rendered
+ select element will support
+ multiple selections.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ to determine which option should be pre-selected when rendering
+ this input field. If not specified, the bean associated with
+ the enclosing <code><html:form></code> tag is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of available options displayed at one time.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to compare with for marking an option selected.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>submit</name>
+ <tag-class>org.apache.struts.taglib.html.SubmitTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Submit Button
+ </strong></p>
+
+ Renders an HTML <input> element of type <code>submit</code>.
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the button label.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>text</name>
+ <tag-class>org.apache.struts.taglib.html.TextTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render An Input Field of Type text</strong></p>
+
+ <p>Render an input field of type text. This tag is only valid when
+ nested inside a form tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>textarea</name>
+ <tag-class>org.apache.struts.taglib.html.TextareaTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Textarea
+ </strong></p>
+
+ Render a textarea element. This tag is only valid when nested
+ inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>cols</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of columns to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>rows</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of rows to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>xhtml</name>
+ <tag-class>org.apache.struts.taglib.html.XhtmlTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render HTML tags as XHTML</strong></p>
+
+ <p>
+ Using this tag in a page tells all other html taglib tags
+ to render themselves as XHTML 1.0. This is useful
+ when composing pages with JSP includes or Tiles.
+ <html:html xhtml="true"> has a similar effect. This
+ tag has no attributes; you use it like this: <html:xhtml/>.
+ </p>
+ <p>
+ <strong>Note</strong>: Included pages do not inherit the rendering
+ style of the including page. Each JSP fragment or Tile must use this
+ tag to render as XHTML.
+ </p>
+ ]]>
+ </description>
+ </tag>
+</taglib>
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..9f04cd7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+ <display-name>Struts MailReader Application</display-name>
+
+ <!-- Action Servlet Configuration -->
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
+ <init-param>
+ <param-name>config</param-name>
+ <param-value>
+ /WEB-INF/struts-config.xml,
+ /WEB-INF/Register-configure.xml,
+ /WEB-INF/Logon-configure.xml
+ </param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+
+ <!-- Action Servlet Mapping -->
+ <servlet-mapping>
+ <servlet-name>action</servlet-name>
+ <url-pattern>*.do</url-pattern>
+ </servlet-mapping>
+
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.properties b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.properties
new file mode 100644
index 0000000..c0a4c4b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.properties
@@ -0,0 +1,12 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+#
+# $Id: webtest.properties.sample 125286 2005-01-15 19:03:34Z jmitchell $
+# -----------------------------------------------------------------------------
+webtest.home = C:/opt/Canoo/webtest-1.7
+webapps.home = C:/opt/Apache/Tomcat-5.5/webapps/
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..4f2508a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,17 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+#
+# $Id: webtest.properties.sample 351877 2005-12-03 02:48:33Z husted $
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = struts-mailreader
+mailreader.home = ../../../
+resource.home = ${mailreader.home}/src/java/org/apache/struts/apps/mailreader/resources/ApplicationResources.properties
+webapps.home = /Program Files/Apache Software Foundation/Tomcat 5.5/webapps/
diff --git a/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..3fc4902
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-1-4-src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+ <!ENTITY logon-fail SYSTEM "file:./entities/logon-fail.xml">
+ <!ENTITY logon-hermes SYSTEM "file:./entities/logon-hermes.xml">
+ <!ENTITY logon-open SYSTEM "file:./entities/logon-open.xml">
+ <!ENTITY logon-page SYSTEM "file:./entities/logon-page.xml">
+ <!ENTITY menu-page SYSTEM "file:./entities/menu-page.xml">
+ <!ENTITY register-hermes SYSTEM "file:./entities/register-hermes.xml">
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY form-submit SYSTEM "file:./entities/form-submit.xml">
+ ]>
+
+<project name="MailReader Storyboard - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="lab-1-4-src"/>
+
+ <property name="mailreader.home"
+ location="../../"/>
+
+ <property name="resource.home"
+ location="classes/MessageResources.properties"/>
+
+ <property name="webapps.home"
+ location="/Program Files/Apache Software Foundation/Tomcat 5.5/webapps/"/>
+
+ <!-- Load application resources -->
+ <property file="${resource.home}"/>
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register,Logon"/>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/webapp/WEB-INF/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Hermes (MSS)">
+ &config;
+ <steps>
+ ®ister-open;
+ ®ister-hermes;
+ <verifyTitle
+ description="Menu page title"
+ text="${MainMenu.title}"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+ <target name="Logon"
+ description="Subscribers can present their registration credentials to
+ use an account again.">
+
+ <webtest name="Open logon action (MSS)">
+ &config;
+ <steps>
+ &logon-open;
+ <setInputField
+ description="Default username"
+ name="username"
+ value="user"/>
+ <setInputField
+ description="Correct default password"
+ name="password"
+ value="pass"/>
+ &form-submit;
+ &menu-page;
+ </steps>
+ </webtest>
+
+ <webtest name="Open logon action (MSS)">
+ &config;
+ <steps>
+ &logon-hermes;
+ </steps>
+ </webtest>
+
+ <webtest name="Logon - Wrong password (1c)">
+ &config;
+ <steps>
+ &logon-open;
+ <setInputField
+ description="Registered username"
+ name="username"
+ value="hermes"/>
+ <setInputField
+ description="Wrong password"
+ name="password"
+ value="medusa"/>
+ &logon-fail;
+ </steps>
+ </webtest>
+
+ <webtest name="Logon - No Account (1a)">
+ &config;
+ <steps>
+ &logon-open;
+ <setInputField
+ description="Not a username"
+ name="username"
+ value="zeus"/>
+ <setInputField
+ description="Not a password"
+ name="password"
+ value="joltBolt"/>
+ &logon-fail;
+ </steps>
+ </webtest>
+
+ </target>
+
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/META-INF/context.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/WEB-INF/web.xml
new file mode 100644
index 0000000..3afc996
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/WEB-INF/web.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+</web-app>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/Constants.java b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/Constants.java
new file mode 100644
index 0000000..364bf28
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/Constants.java
@@ -0,0 +1,207 @@
+package org.apache.struts.apps.mailreader.course;
+
+/**
+ * <p/>
+ * Manifest constants for the MailReader application.
+ * </p>
+ */
+public class Constants {
+
+ // --- Tokens ----
+
+ /**
+ * <p/>
+ * The token representing a "create" task.
+ * </p>
+ */
+ public static final String CREATE = "Create";
+
+ /**
+ * <p/>
+ * The application scope attribute under which our user database
+ * is stored.
+ * </p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ * <p/>
+ * The token representing a "edit" task.
+ * </p>
+ */
+ public static final String DELETE = "Delete";
+
+ /**
+ * <p/>
+ * The token representing a "edit" task.
+ * </p>
+ */
+ public static final String EDIT = "Edit";
+
+ /**
+ * <p/>
+ * The request attributes key under the WelcomeAction stores an ArrayList
+ * of error messages, if required resources are missing.
+ * </p>
+ */
+ public static final String ERROR_KEY = "ERROR";
+
+ /**
+ * <p/>
+ * The token representing a "failure" result for this application.
+ * </p>
+ */
+ public static final String FAILURE = "Failure";
+
+ /**
+ * <p/>
+ * The token representing a "logon" result for this application.
+ * </p>
+ */
+ public static final String LOGON = "Logon";
+
+ /**
+ * <p/>
+ * The package name for this application.
+ * </p>
+ */
+ public static final String PACKAGE = "org.apache.struts.apps.mailreader";
+
+ /**
+ * <p/>
+ * The token representing a "save" task.
+ * </p>
+ */
+ public static final String SAVE = "Save";
+
+ /**
+ * <p/>
+ * The session scope attribute under which the Subscription object
+ * currently selected by our logged-in User is stored.
+ * </p>
+ */
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ /**
+ * <p/>
+ * The token representing a "success" result for this application.
+ * </p>
+ */
+ public static final String SUCCESS = "Success";
+
+ /**
+ * <p/>
+ * The session scope attribute under which the User object
+ * for the currently logged in user is stored.
+ * </p>
+ */
+ public static final String USER_KEY = "user";
+
+ // ---- Error Messages ----
+
+ /**
+ * <p/>
+ * A static message in case database resource is not loaded.
+ * <p/>
+ */
+ public static final String ERROR_DATABASE_NOT_LOADED =
+ "ERROR: User database not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p/>
+ * A static message in case message resource is not loaded.
+ * </p>
+ */
+ public static final String ERROR_MESSAGES_NOT_LOADED =
+ "ERROR: Message resources not loaded -- check servlet container logs for error messages.";
+
+ // ---- Error Tokens ----
+
+ /**
+ * <p/>
+ * The resource key for an error with the transactional token.
+ * </p>
+ */
+ public static final String MSG_TRANSACTION_TOKEN = "error.transaction.token";
+
+ // ---- Log Messages ----
+
+ /**
+ * <p/>
+ * The message to log when cancelling a transaction.
+ * </p>
+ */
+ public static final String LOG_CANCEL = " Transaction cancelled: ";
+
+ /**
+ * <p/>
+ * The message to log when forwarding to a result.
+ * </p>
+ */
+ public static final String LOG_RESULT = " Forwarding to result: ";
+
+ /**
+ * <p/>
+ * The message to log when forwarding to a 'failure' result.
+ * <p/>
+ */
+ public static final String LOG_FAILURE = LOG_RESULT + FAILURE;
+
+ /**
+ * <p/>
+ * The message to log when forwarding to a 'logon' result.
+ * </p>
+ */
+ public static final String LOG_LOGON = LOG_RESULT + LOGON;
+
+ /**
+ * <p/>
+ * The message to log when populating a form.
+ * </p>
+ */
+ public static final String LOG_POPULATE_FORM = " Populating form from: ";
+
+ /**
+ * <p/>
+ * The message to log when populating a subscription.
+ * </p>
+ */
+ public static final String LOG_POPULATE_SUBSCRIPTION = " Populating subscription: ";
+
+ /**
+ * <p/>
+ * The message to log when populating a user.
+ * </p>
+ */
+ public static final String LOG_POPULATE_USER = " Populating user: ";
+
+ /**
+ * <p/>
+ * The message to log when forwarding to a 'success' result.
+ * </p>
+ */
+ public static final String LOG_PROCESSING = " Processing: ";
+
+ /**
+ * <p/>
+ * The message to log when forwarding to a 'success' result.
+ * </p>
+ */
+ public static final String LOG_SUCCESS = LOG_RESULT + SUCCESS;
+
+ /**
+ * <p/>
+ * The message to log when setting a transactional token.
+ * </p>
+ */
+ public static final String LOG_TOKEN = " Setting transactional control token";
+
+ /**
+ * <p/>
+ * The message to log when checking a transactional token.
+ * </p>
+ */
+ public static final String LOG_TOKEN_CHECK = " Checking transactional control token";
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/LogonAction.java b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/LogonAction.java
new file mode 100644
index 0000000..1fff4e4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/LogonAction.java
@@ -0,0 +1,95 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.apps.mailreader.course;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionMessages;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * <p/>
+ * Validate a user logon.
+ * </p>
+ *
+ * @version $Rev: 360442 $ $Date: 2005-12-31 15:10:04 -0500 (Sat, 31 Dec 2005) $
+ */
+public final class LogonAction extends RegisterAction {
+
+
+ /**
+ * <p/>
+ * Store User object in client session.
+ * If user object is null, any existing user object is removed.
+ * </p>
+ *
+ * @param request The request we are processing
+ * @param user The user object returned from the database
+ */
+ protected void doCacheUser(HttpServletRequest request, User user) {
+
+ HttpSession session = request.getSession();
+ session.setAttribute(USER_KEY, user);
+ }
+
+ /**
+ * <p/>
+ * Use "username" and "password" fields from ActionForm to retrieve a User
+ * object from the database. If credentials are not valid, or database
+ * has disappeared, post error messages and forward to input.
+ * </p>
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @throws Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Retrieve user
+ String username = doGet(form, USERNAME);
+ String password = doGet(form, PASSWORD);
+ ActionMessages errors = new ActionMessages();
+ User user = doGetUser(username, password, errors);
+
+ // Report back any errors, and exit if any
+ if (!errors.isEmpty()) {
+ return doInputForward(mapping, request, errors);
+ }
+
+ // Cache user object in session to signify logon
+ doCacheUser(request, user);
+
+ // Done
+ return doFindSuccess(mapping);
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/MemoryDatabasePlugIn.java b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/MemoryDatabasePlugIn.java
new file mode 100644
index 0000000..cc04c5d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/MemoryDatabasePlugIn.java
@@ -0,0 +1,174 @@
+package org.apache.struts.apps.mailreader.course;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.ActionServlet;
+import org.apache.struts.action.PlugIn;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+import org.apache.struts.config.ModuleConfig;
+
+import javax.servlet.ServletException;
+import java.io.*;
+
+/**
+ * <p><strong>MemoryDatabasePlugIn</strong> initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an
+ * XML file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ *
+ * @version $Rev: 360442 $ $Date: 2005-12-31 15:10:04 -0500 (Sat, 31 Dec 2005) $
+ */
+public class MemoryDatabasePlugIn implements PlugIn {
+
+ // ---- Instance Variables ----
+
+ /**
+ * The {@link org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * Logging output for this plug in instance.
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+
+ /**
+ * The {@link org.apache.struts.action.ActionServlet} owning this application.
+ */
+ private ActionServlet servlet = null;
+
+ // ---- Properties ----
+
+ /**
+ * The web application resource path of our persistent database
+ * storage file.
+ */
+ private String pathname = "/WEB-INF/database.xml";
+
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ---- PlugIn Methods ----
+
+
+ /**
+ * Gracefully shut down this database, releasing any resources
+ * that were allocated at initialization.
+ */
+ public void destroy() {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY);
+ database = null;
+ servlet = null;
+ database = null;
+ }
+
+
+ /**
+ * Initialize and load our initial database from persistent storage.
+ *
+ * @param servlet The ActionServlet for this web application
+ * @param config The ApplicationConfig for our owning module
+ * @throws ServletException if we cannot configure ourselves correctly
+ */
+ public void init(ActionServlet servlet, ModuleConfig config)
+ throws ServletException {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated configuration and servlet
+ this.servlet = servlet;
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new ServletException("Cannot load database from '" +
+ pathname + "'", e);
+ }
+
+ // Make the initialized database available
+ servlet.getServletContext().setAttribute(Constants.DATABASE_KEY,
+ database);
+
+ }
+
+ // ---- Private Methods ----
+
+ /**
+ * Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.
+ *
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = servlet.getServletContext().getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ servlet.getServletContext().getAttribute
+ ("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ servlet.getServletContext().getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/RegisterAction.java b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/RegisterAction.java
new file mode 100644
index 0000000..2a844c3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/java/org/apache/struts/apps/mailreader/course/RegisterAction.java
@@ -0,0 +1,628 @@
+package org.apache.struts.apps.mailreader.course;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.*;
+import org.apache.struts.actions.MappingDispatchAction;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * <p/>
+ * Provide an Edit method for retrieving an existing user,
+ * and a Save method for updating or inserting a user.
+ * </p><p>
+ * Both methods utilize a RegistrationForm to obtain or expose User details.
+ * If Save is used to create a user,
+ * additional validations ensure input is nominal.
+ * When a user is created,
+ * Save also handles the initial logon.
+ * </p>
+ */
+public class RegisterAction extends MappingDispatchAction {
+
+ // ---- Constants ----
+
+ /**
+ * <p/>
+ * The application scope attribute under which our user database
+ * is stored.
+ * </p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ * <p/>
+ * Name of fromAddress field ["fromAddress"].
+ * </p>
+ */
+ public final static String FROM_ADDRESS = "fromAddress";
+
+ /**
+ * <p/>
+ * Name of fullName field ["fullName"].
+ * </p>
+ */
+ public final static String FULL_NAME = "fullName";
+
+ /**
+ * <p/>
+ * Name of password field ["password"].
+ * </p>
+ */
+ public static String PASSWORD = "password";
+
+ /**
+ * <p/>
+ * Name of password confirmation field ["password2"].
+ * </p>
+ */
+ public final static String PASSWORD2 = "password2";
+
+ /**
+ * <p/>
+ * Name of replyToAddress field ["replyToAddress"].
+ * </p>
+ */
+ public final static String REPLY_TO_ADDRESS = "replyToAddress";
+
+ /**
+ * <p/>
+ * The token representing a "success" result for this application.
+ * </p>
+ */
+ public static final String SUCCESS = "Success";
+
+ /**
+ * <p/>
+ * The session scope attribute under which the User object
+ * for the currently logged in user is stored.
+ * </p>
+ */
+ public static final String USER_KEY = "user";
+
+ /**
+ * <p/>
+ * Name of username field ["username"].
+ * </p>
+ */
+ public static String USERNAME = "username";
+
+ /**
+ * <p/>
+ * Name of task field ["task"].
+ * </p>
+ */
+ public final static String TASK = "task";
+
+ // ---- Private Methods ----
+
+ /**
+ * <p/>
+ * The <code>Log</code> instance for this application.
+ * </p>
+ */
+ private Log log = LogFactory.getLog(Constants.PACKAGE);
+
+ /**
+ * <p/>
+ * The message prefix to use when populating a Registration Form.
+ * </p>
+ */
+ final String LOG_REGISTRATION_POPULATE = "RegistrationForm.populate";
+
+ /**
+ * <p/>
+ * Helper method to post error message when user already exists.
+ * </p>
+ *
+ * @param username Existing username
+ * @param errors Our ActionMessages collection
+ */
+ private void errorUsernameUnique(String username,
+ ActionMessages errors) {
+ errors.add(
+ USERNAME,
+ new org.apache.struts.action.ActionMessage(
+ "error.username.unique", username));
+ }
+
+
+ /**
+ * <p/>
+ * Helper method to log event and cancel transaction.
+ * </p>
+ *
+ * @param session Our HttpSession
+ * @param method Method being processed
+ * @param key Attrkibute to remove from session, if any
+ */
+ private void doCancel(HttpSession session, String method, String key) {
+ if (log.isTraceEnabled()) {
+ StringBuffer sb = new StringBuffer(128);
+ sb.append(Constants.LOG_CANCEL);
+ sb.append(method);
+ log.trace(sb.toString());
+ }
+ if (key != null) {
+ session.removeAttribute(key);
+ }
+ }
+
+ /**
+ * <p/>
+ * Verify input for creating a new user,
+ * create the user, and process the login.
+ * </p>
+ *
+ * @param form The input form
+ * @param request The HttpRequest being served
+ * @param errors The ActionMessages collection for any errors
+ * @return A new User and empty Errors if create succeeds,
+ * or null and Errors if create fails
+ */
+ private User doCreateUser(
+ ActionForm form,
+ HttpServletRequest request,
+ ActionMessages errors) {
+
+ if (log.isTraceEnabled()) {
+ log.trace(" Perform additional validations on Create");
+ }
+
+ UserDatabase database = doGetUserDatabase();
+ String username = doGet(form, USERNAME);
+ try {
+ if (database.findUser(username) != null) {
+ errorUsernameUnique(username, errors);
+ }
+ }
+ catch (ExpiredPasswordException e) {
+ errorUsernameUnique(username, errors);
+ errors.add("errors.literal", new ActionMessage(e.getMessage()));
+ }
+
+ String password = doGet(form, PASSWORD);
+ if ((password == null) || (password.length() < 1)) {
+ errors.add(PASSWORD, new ActionMessage("error.password.required"));
+
+ String password2 = doGet(form, PASSWORD2);
+ if ((password2 == null) || (password2.length() < 1)) {
+ errors.add(
+ PASSWORD2,
+ new ActionMessage("error.password2.required"));
+ }
+ }
+
+ if (!errors.isEmpty()) {
+ return null;
+ }
+
+ User user = database.createUser(username);
+
+ // Log the user in
+ HttpSession session = request.getSession();
+ session.setAttribute(Constants.USER_KEY, user);
+ if (log.isTraceEnabled()) {
+ log.trace(
+ " User: '"
+ + user.getUsername()
+ + "' logged on in session: "
+ + session.getId());
+ }
+
+ return user;
+ }
+
+ /**
+ * <p/>
+ * Helper method to obtain User form session (if any).
+ * </p>
+ *
+ * @param session Our HttpSession
+ * @return User object, or null if there is no user.
+ */
+ private User doGetUser(HttpSession session) {
+ return (User) session.getAttribute(Constants.USER_KEY);
+ }
+
+ /**
+ * <p/>
+ * Confirm user credentials. Post any errors and return User object
+ * (or null).
+ * </p>
+ *
+ * @param database Database in which to look up the user
+ * @param username Username specified on the logon form
+ * @param password Password specified on the logon form
+ * @param errors ActionMessages queue to passback errors
+ * @return Validated User object or null
+ * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
+ * to be handled by Struts exception
+ * processor via the action-mapping
+ */
+ private User doGetUser(UserDatabase database, String username,
+ String password, ActionMessages errors)
+ throws ExpiredPasswordException {
+
+ User user = null;
+ if (database == null) {
+ errors.add(
+ ActionMessages.GLOBAL_MESSAGE,
+ new ActionMessage("error.database.missing"));
+ } else {
+
+ if (username.equals("Hermes")) {
+ throw new ExpiredPasswordException("Hermes");
+ }
+
+ user = database.findUser(username);
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ errors.add(
+ ActionMessages.GLOBAL_MESSAGE,
+ new ActionMessage("error.password.mismatch"));
+ }
+ }
+
+ return user;
+ }
+
+ /**
+ * <p/>
+ * Return a reference to the UserDatabase
+ * or null if the database is not available.
+ * </p>
+ *
+ * @return a reference to the UserDatabase or null if the database is not
+ * available
+ */
+ private UserDatabase doGetUserDatabase() {
+ return (UserDatabase) servlet.getServletContext().getAttribute(
+ DATABASE_KEY);
+ }
+
+ /**
+ * <p/>
+ * Log a "processing" message for an Action.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @param method Name of method being processed
+ */
+ private void doLogProcess(ActionMapping mapping, String method) {
+ if (log.isDebugEnabled()) {
+ StringBuffer sb = new StringBuffer(128);
+ sb.append(" ");
+ sb.append(mapping.getPath());
+ sb.append(":");
+ sb.append(Constants.LOG_PROCESSING);
+ sb.append(method);
+ log.debug(sb.toString());
+ }
+ }
+
+ /**
+ * <p/>
+ * Helper method to populate the input form from the User object.
+ * </p>
+ *
+ * @param form Form with incoming values
+ * @param user User object to populate
+ * @throws ServletException On any error
+ */
+ private void doPopulate(ActionForm form, User user)
+ throws ServletException {
+
+ final String title = Constants.EDIT;
+
+ if (log.isTraceEnabled()) {
+ log.trace(Constants.LOG_POPULATE_FORM + user);
+ }
+
+ try {
+ PropertyUtils.copyProperties(form, user);
+ DynaActionForm dyna = (DynaActionForm) form;
+ dyna.set(TASK, title);
+ dyna.set(PASSWORD, null);
+ dyna.set(PASSWORD2, null);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if (t == null) {
+ t = e;
+ }
+ log.error(LOG_REGISTRATION_POPULATE, t);
+ throw new ServletException(LOG_REGISTRATION_POPULATE, t);
+ } catch (Throwable t) {
+ log.error(LOG_REGISTRATION_POPULATE, t);
+ throw new ServletException(LOG_REGISTRATION_POPULATE, t);
+ }
+ }
+
+ /**
+ * <p/>
+ * Helper method to populate the User object from the input form.
+ * </p>
+ *
+ * @param user User object to populate
+ * @param form Form with incoming values
+ * @throws ServletException On any error
+ */
+ private void doPopulate(User user, ActionForm form)
+ throws ServletException {
+
+ if (log.isTraceEnabled()) {
+ log.trace(Constants.LOG_POPULATE_USER + user);
+ }
+
+ try {
+ String oldPassword = user.getPassword();
+ PropertyUtils.copyProperties(user, form);
+ String password = doGet(form, PASSWORD);
+ if ((password == null)
+ || (password.length() < 1)) {
+
+ user.setPassword(oldPassword);
+ }
+
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if (t == null) {
+ t = e;
+ }
+
+ log.error(LOG_REGISTRATION_POPULATE, t);
+ throw new ServletException(LOG_REGISTRATION_POPULATE, t);
+
+ } catch (Throwable t) {
+ log.error(LOG_REGISTRATION_POPULATE, t);
+ throw new ServletException(LOG_REGISTRATION_POPULATE, t);
+ }
+ }
+
+ /**
+ * <p/>
+ * Helper method to log event and save token.
+ * </p>
+ *
+ * @param request Our HttpServletRequest
+ */
+ private void doSaveToken(HttpServletRequest request) {
+ if (log.isTraceEnabled()) {
+ log.trace(Constants.LOG_TOKEN);
+ }
+ saveToken(request);
+ }
+
+ /**
+ * <p/>
+ * Persist the User object, including subscriptions, to the database.
+ * </p>
+ *
+ * @param user Our User object
+ * @throws javax.servlet.ServletException On any error
+ */
+ private void doSaveUser(User user) throws ServletException {
+
+ final String LOG_DATABASE_SAVE_ERROR =
+ " Unexpected error when saving User: ";
+
+ try {
+ UserDatabase database = doGetUserDatabase();
+ database.save();
+ } catch (Exception e) {
+ String message = LOG_DATABASE_SAVE_ERROR + user.getUsername();
+ log.error(message, e);
+ throw new ServletException(message, e);
+ }
+ }
+
+ /**
+ * <p/>
+ * Validate and clear the transactional token,
+ * creating logging statements as needed.
+ * </p>
+ *
+ * @param request Our HttpServletRequest
+ * @param errors ActionErrors to transfer any messages
+ */
+ private void doValidateToken(HttpServletRequest request,
+ ActionMessages errors) {
+
+ if (log.isTraceEnabled()) {
+ log.trace(Constants.LOG_TOKEN_CHECK);
+ }
+
+ if (!isTokenValid(request)) {
+ errors.add(
+ ActionMessages.GLOBAL_MESSAGE,
+ new ActionMessage(Constants.MSG_TRANSACTION_TOKEN));
+ }
+
+ resetToken(request);
+ }
+
+ // ---- Protected methods ----
+
+ /**
+ * <p/>
+ * Return the mapping labeled "success"
+ * or null if there is no such mapping.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @return Return the mapping named "success" or null if there is no such
+ * mapping.
+ */
+ protected ActionForward doFindSuccess(ActionMapping mapping) {
+ return mapping.findForward(SUCCESS);
+ }
+
+
+ /**
+ * <p/>
+ * Helper method to fetch a String property from a DynaActionForm.
+ * </p>
+ * <p/>
+ * Values are returned trimmed of leading and trailing whitespace.
+ * Zero-length strings are returned as null.
+ * </p>
+ *
+ * @param form Our DynaActionForm
+ * @param property The name of the property
+ * @return The value or null if an error occurs
+ */
+ protected String doGet(ActionForm form, String property) {
+ String initial;
+ try {
+ initial = (String) PropertyUtils.getSimpleProperty(form, property);
+ } catch (Throwable t) {
+ initial = null;
+ }
+ String value = null;
+ if ((initial != null) && (initial.length() > 0)) {
+ value = initial.trim();
+ if (value.length() == 0) {
+ value = null;
+ }
+ }
+ return value;
+ }
+
+ /**
+ * <p/>
+ * Confirm user credentials. Post any errors and return User object
+ * (or null).
+ * </p>
+ *
+ * @param username Username specified on the logon form
+ * @param password Password specified on the logon form
+ * @param errors ActionMessages queue to passback errors
+ * @return Validated User object or null
+ * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
+ * to be handled by Struts exception
+ * processor via the action-mapping
+ */
+ protected User doGetUser(String username,
+ String password, ActionMessages errors)
+ throws ExpiredPasswordException {
+
+ return doGetUser(doGetUserDatabase(), username, password, errors);
+ }
+
+ /**
+ * <p/>
+ * Save any errors and forward to the Input result.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @param request Our HttpServletRequest
+ * @param errors Our ActionMessages collectoin
+ * @return The InputForward for this mappintg
+ */
+ protected ActionForward doInputForward(ActionMapping mapping,
+ HttpServletRequest request,
+ ActionMessages errors) {
+ this.saveErrors(request, errors);
+ return (mapping.getInputForward());
+ }
+
+ // ----- Public Methods ----
+
+ /**
+ * <p/>
+ * Retrieve the User object to edit or null if the User does not exist,
+ * and set an transactional token to later detect multiple Save commands.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @param form Our ActionForm
+ * @param request Our HttpServletRequest
+ * @param response Our HttpServletResponse
+ * @return The "Success" result for this mapping
+ * @throws Exception on any error
+ */
+ public ActionForward Edit(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ final String method = Constants.EDIT;
+ doLogProcess(mapping, method);
+
+ HttpSession session = request.getSession();
+ User user = doGetUser(session);
+ boolean updating = (user != null);
+ if (updating) {
+ doPopulate(form, user);
+ }
+
+ doSaveToken(request);
+ return doFindSuccess(mapping);
+ }
+
+ /**
+ * <p/>
+ * Insert or update a User object to the persistent store.
+ * </p><p>
+ * If a User is not logged in,
+ * then a new User is created and automatically logged in.
+ * Otherwise, the existing User is updated.
+ * </p>
+ *
+ * @param mapping Our ActionMapping
+ * @param form Our ActionForm
+ * @param request Our HttpServletRequest
+ * @param response Our HttpServletResponse
+ * @return The "Success" result for this mapping
+ * @throws Exception on any error
+ */
+ public ActionForward Save(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ final String method = Constants.SAVE;
+ doLogProcess(mapping, method);
+
+ HttpSession session = request.getSession();
+ if (isCancelled(request)) {
+ doCancel(session, method, Constants.SUBSCRIPTION_KEY);
+ return doFindSuccess(mapping);
+ }
+
+ ActionMessages errors = new ActionMessages();
+ doValidateToken(request, errors);
+
+ if (!errors.isEmpty()) {
+ return doInputForward(mapping, request, errors);
+ }
+
+ User user = doGetUser(session);
+ if (user == null) {
+ user = doCreateUser(form, request, errors);
+ if (!errors.isEmpty()) {
+ return doInputForward(mapping, request, errors);
+ }
+ }
+
+ doPopulate(user, form);
+ doSaveUser(user);
+
+ return doFindSuccess(mapping);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/LogonForm.jsp b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/LogonForm.jsp
new file mode 100644
index 0000000..11371a6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/LogonForm.jsp
@@ -0,0 +1,54 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<html:xhtml/>
+<html>
+<head>
+ <title><bean:message key="Logon.title"/></title>
+</head>
+
+<body>
+<html:errors/>
+
+<html:form action="/LogonPost">
+ <table border="0" width="100%">
+
+ <tr>
+ <th align="right">
+ <bean:message key="username.label"/>:
+ </th>
+ <td align="left">
+ <html:text property="username" size="16" maxlength="18"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ <bean:message key="password.label"/>:
+ </th>
+ <td align="left">
+ <html:password property="password" size="16" maxlength="18"
+ redisplay="false"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">
+ <html:submit property="DO_SUBMIT">
+ <bean:message key="button.submit"/>
+ </html:submit>
+ </td>
+ <td align="left">
+ <html:reset property="DO_RESET">
+ <bean:message key="button.reset"/>
+ </html:reset>
+ </td>
+ </tr>
+
+ </table>
+
+</html:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/MainMenu.jsp b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/MainMenu.jsp
new file mode 100644
index 0000000..e0bf471
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/MainMenu.jsp
@@ -0,0 +1,16 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
+<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
+<html>
+<head>
+ <title><bean:message key="MainMenu.title"/></title>
+</head>
+
+<body>
+<h3>Main Menu Options for <c:out value="${user.map.fullName}"/></h3>
+<ul>
+ <li><html:link action="/RegisterEdit">Edit Profile</html:link></li>
+ <li>[TODO] Logout</li>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/RegisterForm.jsp b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/RegisterForm.jsp
new file mode 100644
index 0000000..0e9a80c
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/RegisterForm.jsp
@@ -0,0 +1,164 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
+<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
+<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
+
+<html:html>
+<head>
+ <!-- Lab 2-1: When task is Edit, change title -->
+ <title>
+ <c:if test="${RegisterForm.map.task == 'Create'}">
+ <bean:message key="registration.title.create"/>
+ </c:if>
+ <c:if test="${RegisterForm.map.task == 'Edit'}">
+ <bean:message key="registration.title.edit"/>
+ </c:if>
+ </title>
+</head>
+
+<body>
+
+<html:errors/>
+
+<html:form action="/RegisterSave">
+ <html:hidden property="task"/>
+ <table border="0" width="100%">
+
+ <tr>
+ <th align="right">
+ Username:
+ </th>
+ <td align="left">
+ <!-- Lab 2-1: When task is Edit, change username to readonly -->
+ <c:if test="${RegisterForm.map.task == 'Create'}">
+ <html:text property="username" size="16" maxlength="16"/>
+ </c:if>
+ <c:if test="${RegisterForm.map.task == 'Edit'}">
+ <c:out value="${RegisterForm.map.username}"/>
+ <html:hidden property="username"/>
+ </c:if>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Password:
+ </th>
+ <td align="left">
+ <html:password property="password" size="16"
+ maxlength="16"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Confirm Password:
+ </th>
+ <td align="left">
+ <html:password property="password2" size="16"
+ maxlength="16"/>
+ </td>
+ </tr>
+ <tr>
+ <th align="right">
+ Fullname:
+ </th>
+ <td align="left">
+ <html:text property="fullName" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ From Address:
+ </th>
+ <td align="left">
+ <html:text property="fromAddress" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Reply To Address:
+ </th>
+ <td align="left">
+ <html:text property="replyToAddress" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">
+ <html:submit property="DO_SUBMIT">
+ <bean:message key="button.submit"/>
+ </html:submit>
+ </td>
+ <td align="left">
+ <html:reset property="DO_RESET">
+ <bean:message key="button.reset"/>
+ </html:reset>
+
+ <html:cancel/>
+ </td>
+ </tr>
+
+ </table>
+</html:form>
+
+<!-- Lab 2-1: When task is Edit, display Subscriptions -->
+<c:if test="${RegisterForm.map.task == 'Edit'}">
+<div align="center">
+ <h3><bean:message key="heading.subscriptions"/></h3>
+</div>
+
+<table border="1" width="100%">
+
+ <tr>
+ <th align="center" width="30%">
+ <bean:message key="heading.host"/>
+ </th>
+ <th align="center" width="25%">
+ <bean:message key="heading.user"/>
+ </th>
+ <th align="center" width="10%">
+ <bean:message key="heading.type"/>
+ </th>
+ <th align="center" width="10%">
+ <bean:message key="heading.autoConnect"/>
+ </th>
+ <th align="center" width="15%">
+ <bean:message key="heading.action"/>
+ </th>
+ </tr>
+
+ <c:forEach var="subscription" items="${user.subscriptions}">
+ <tr>
+ <td align="left">
+ <bean:write name="subscription" property="host"/>
+ </td>
+ <td align="left">
+ <bean:write name="subscription" property="username"/>
+ </td>
+ <td align="center">
+ <bean:write name="subscription" property="type"/>
+ </td>
+ <td align="center">
+ <bean:write name="subscription" property="autoConnect"/>
+ </td>
+ <td align="center">
+ <html:link action="/DeleteSubscription"
+ paramName="subscription" paramId="host"
+ paramProperty="host">
+ <bean:message key="registration.deleteSubscription"/>
+ </html:link>
+
+ <html:link action="/EditSubscription"
+ paramName="subscription" paramId="host"
+ paramProperty="host">
+ <bean:message key="registration.editSubscription"/>
+ </html:link>
+ </td>
+ </tr>
+ </c:forEach>
+ </c:if>
+</body>
+</html:html>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Logon-configure.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Logon-configure.xml
new file mode 100644
index 0000000..74223e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Logon-configure.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="LogonForm"
+ extends="BaseForm"/>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="/Logon"
+ name="LogonForm"
+ forward="/LogonForm.jsp"
+ validate="false"/>
+
+ <action
+ path="/LogonPost"
+ type="org.apache.struts.apps.mailreader.course.LogonAction"
+ name="LogonForm"
+ scope="request"
+ validate="true"
+ input="Input">
+ <forward
+ name="Input"
+ path="/Logon.do"/>
+ <forward
+ name="Success"
+ redirect="true"
+ path="/MainMenu.do"/>
+ </action>
+
+ </action-mappings>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Logon-validate.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Logon-validate.xml
new file mode 100644
index 0000000..ccc050b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Logon-validate.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">
+
+<form-validation>
+ <formset>
+ <form name="LogonForm">
+
+ <field property="username"
+ depends="required">
+ <arg key="username.label"/>
+ </field>
+
+ <field property="password"
+ depends="required, minlength,maxlength">
+ <arg key="password.label"/>
+ <arg key="${var:minlength}"
+ name="minlength"
+ resource="false"/>
+ <arg key="${var:maxlength}"
+ name="maxlength"
+ resource="false"/>
+
+ <var>
+ <var-name>
+ maxlength
+ </var-name>
+ <var-value>
+ 16
+ </var-value>
+ </var>
+ <var>
+ <var-name>
+ minlength
+ </var-name>
+ <var-value>
+ 3
+ </var-value>
+ </var>
+ </field>
+ </form>
+ </formset>
+</form-validation>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Register-configure.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Register-configure.xml
new file mode 100644
index 0000000..90ddf0d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Register-configure.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="RegisterForm"
+ extends="BaseForm">
+ <form-property
+ name="password2"
+ type="java.lang.String"/>
+ <form-property
+ name="fullName"
+ type="java.lang.String"/>
+ <form-property
+ name="fromAddress"
+ type="java.lang.String"/>
+ <form-property
+ name="replyToAddress"
+ type="java.lang.String"/>
+ </form-bean>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="RegisterAction"
+ input="Input"
+ type="org.apache.struts.apps.mailreader.course.RegisterAction"
+ name="RegisterForm"
+ scope="request">
+ <forward
+ name="Input"
+ path="/RegisterForm.jsp"/>
+ <forward
+ name="Success"
+ redirect="true"
+ path="/MainMenu.do"/>
+ </action>
+
+ <action path="/Register"
+ extends="RegisterAction"
+ forward="/RegisterForm.jsp"
+ validate="false"/>
+
+ <action path="/RegisterEdit"
+ extends="RegisterAction"
+ parameter="Edit"
+ validate="false">
+ <forward
+ name="Success"
+ path="/RegisterForm.jsp"/>
+ </action>
+
+
+ <action path="/RegisterSave"
+ extends="RegisterAction"
+ parameter="Save">
+ </action>
+
+ </action-mappings>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Register-validate.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Register-validate.xml
new file mode 100644
index 0000000..4d06c11
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/Register-validate.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">
+
+<form-validation>
+
+ <formset>
+ <form name="RegisterForm">
+
+ <field property="username" depends="required">
+ <arg position="0" key="username.label"/>
+ </field>
+
+ <field property="password" depends="required">
+ <arg position="0" key="password.label"/>
+ </field>
+
+ <field property="password2" depends="required,validwhen">
+ <arg position="0" key="password2.label"/>
+ <var>
+ <var-name>test</var-name>
+ <var-value>(*this* == password)</var-value>
+ </var>
+ </field>
+
+ <!-- Lab 1-2: Insert remaining fields from use case -->
+
+ <field property="fullName"
+ depends="required">
+ <arg key="fullName.label"/>
+ </field>
+
+ <field property="fromAddress"
+ depends="required,email">
+ <arg key="fromAddress.label"/>
+ </field>
+
+ <field property="replyToAddress"
+ depends="email">
+ <arg key="replyToAddress.label"/>
+ </field>
+
+ </form>
+ </formset>
+</form-validation>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/database.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/database.xml
new file mode 100644
index 0000000..c199a5e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/database.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user"
+ password="pass"
+ fullName="John Q. User"
+ fromAddress="John.User@somewhere.com">
+ <subscription
+ host="mail.hotmail.com"
+ type="pop3"
+ autoConnect="false"
+ username="user1234"
+ password="bar">
+ </subscription>
+ <subscription
+ host="mail.yahoo.com"
+ type="imap"
+ autoConnect="false"
+ username="jquser"
+ password="foo">
+ </subscription>
+ </user>
+</database>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/struts-config.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/struts-config.xml
new file mode 100644
index 0000000..a27fc6b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/struts-config.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+
+ <form-beans>
+ <form-bean
+ name="BaseForm"
+ type="org.apache.struts.validator.DynaValidatorForm">
+ <form-property
+ name="username"
+ type="java.lang.String"/>
+ <form-property
+ name="password"
+ type="java.lang.String"/>
+ <!-- Lab 2-1: Add task property -->
+ <form-property
+ name="task"
+ type="java.lang.String"
+ initial="Create"/>
+ </form-bean>
+ </form-beans>
+
+ <action-mappings
+ type="org.apache.struts.action.RequestActionMapping">
+
+ <action path="/MainMenu"
+ forward="/MainMenu.jsp"
+ validate="false"/>
+
+ </action-mappings>
+
+ <controller
+ inputForward="true"/>
+
+ <message-resources
+ parameter="MessageResources"/>
+
+ <plug-in
+ className="org.apache.struts.apps.mailreader.course.MemoryDatabasePlugIn">
+ <set-property
+ property="pathname"
+ value="/WEB-INF/database.xml"/>
+ </plug-in>
+
+ <plug-in
+ className="org.apache.struts.validator.ValidatorPlugIn">
+ <set-property
+ property="pathnames"
+ value="/org/apache/struts/validator/validator-rules.xml,
+ /WEB-INF/Logon-validate.xml,/WEB-INF/Register-validate.xml"
+ />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/struts-html.tld b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/struts-html.tld
new file mode 100644
index 0000000..c44843b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/struts-html.tld
@@ -0,0 +1,8752 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE taglib
+ PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
+ "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+<taglib>
+ <tlib-version>1.3</tlib-version>
+ <jsp-version>1.2</jsp-version>
+ <short-name>html</short-name>
+ <uri>http://struts.apache.org/tags-html</uri>
+ <description>
+ <![CDATA[
+ <p>
+ This taglib contains tags used to create struts
+ input forms, as well as other tags generally useful
+ in the creation of HTML-based user interfaces.
+ </p>
+
+ <p>Many of the tags in this tag library will throw a
+ <code>JspException</code> at runtime when they are utilized incorrectly
+ (such as when you specify an invalid combination of tag attributes). JSP
+ allows you to declare an "error page" in the <code><%@ page %></code>
+ directive. If you wish to process the actual exception that caused the
+ problem, it is passed to the error page as a request attribute under key
+ <code>org.apache.struts.action.EXCEPTION</code>.</p>
+ ]]>
+ </description>
+ <tag>
+ <name>base</name>
+ <tag-class>org.apache.struts.taglib.html.BaseTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><base></code> Element</strong></p>
+
+ <p>Renders an HTML <code><base></code> element with an
+ <code>href</code> attribute pointing to the absolute location of
+ the enclosing JSP page. This tag is valid only when nested inside
+ an HTML <code><head></code> element.</p>
+
+ <p>This tag is useful because it allows you to use relative URL
+ references in the page that are calculated based on the URL of the
+ page itself, rather than the URL to which the most recent submit
+ took place (which is where the browser would normally resolve
+ relative references against).</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target for this base reference.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>server</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The server name to use instead of request.getServerName().</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ref</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The reference from which the base uri will created. Possible values are:
+ </p>
+ <ul>
+ <li><code>page</code> - The base uri will be the jsp page location. (default)</li>
+ <li><code>site</code> - The base uri will be the application context path.</li>
+ </ul>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.3</dd></dl>
+
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>button</name>
+ <tag-class>org.apache.struts.taglib.html.ButtonTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render A Button Input Field</strong></p>
+
+ <p>
+ Renders an HTML <input> element of type
+ <code>button</code>, populated from the specified value or the
+ content of this tag body. This tag is only valid when nested
+ inside a form tag body.
+ </p>
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> if this input field should be
+ disabled.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Click"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>cancel</name>
+ <tag-class>org.apache.struts.taglib.html.CancelTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Cancel Button
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type submit. This tag is only
+ valid when nested inside a form tag body. Pressing of this submit
+ button causes the action servlet to bypass calling the associated
+ form bean validate() method. The action is called normally.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ <strong>WARNING</strong> - If you set this attribute to a
+ value other than the default, this will <em>NOT</em> be
+ recognized as the cancel key by the Struts controller servlet
+ or the <code>Action.isCancelled()</code> method. You will
+ need to do your own cancel detection.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any), or "Cancel"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>checkbox</name>
+ <tag-class>org.apache.struts.taglib.html.CheckboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, populated from the specified
+ value or the specified property of the bean associated
+ with our current form. This tag is only valid when
+ nested inside a form tag body.</p>
+
+ <p><strong>NOTE</strong>: The underlying property value
+ associated with this field should be of type <code>boolean</code>,
+ and any <code>value</code> you specify should correspond to one
+ of the Strings that indicate a true value ("true", "yes", or
+ "on"). If you wish to utilize a set of related String values,
+ consider using the <code>multibox</code> tag.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize unchecked checkboxes, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement setting the corresponding
+ boolean property to <code>false</code> in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted. If not specified,
+ the value "on" will be returned.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>errors</name>
+ <tag-class>org.apache.struts.taglib.html.ErrorsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated error messages.
+ </strong></p>
+
+ <p>Displays a set of error messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, an <code>ActionErrors</code>
+ object, a String, or a String array in request scope. If
+ such a bean is not found, nothing will be rendered.</p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name, with optional
+ definitions of message keys specified in the following
+ attributes:</p>
+ <ul>
+ <li><strong>header</strong> - Text that will be rendered
+ before the error messages list. Typically, this message text
+ will end with <code><ul></code> to start the
+ error messages list (default "errors.header").</li>
+ <li><strong>footer</strong> - Text that will be rendered
+ after the error messages list. Typically, this message text
+ will begin with <code></ul></code> to end the error
+ messages list (default "errors.footer").</li>
+ <li><strong>prefix</strong> - Text that will be rendered
+ before each individual error in the list (default "errors.prefix").</li>
+ <li><strong>suffix</strong> - Text that will be rendered
+ after each individual error in the list (default "errors.suffix").</li>
+ </ul>
+
+ <p>See the <code>messages</code> tag for an alternative to this tag that
+ does not rely on HTML in your <code>MessageResources</code>.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of error messages has finished.
+ Defaults to "errors.footer" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of error messages begins.
+ Defaults to "errors.header" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>prefix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before an error message.
+ Defaults to "errors.prefix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which error messages should be
+ displayed. If not specified, all error messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>suffix</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after an error message.
+ Defaults to "errors.suffix" if not specified.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>file</name>
+ <tag-class>org.apache.struts.taglib.html.FileTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A File Select Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type file, defaulting to
+ the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ <p>
+ As with the corresponding HTML <input> element, the
+ enclosing form element must specify "POST" for the <code>method</code>
+ attribute, and "multipart/form-data" for the <code>enctype</code>
+ attribute. For example:
+ </p>
+ <pre>
+ <html:form method="POST" enctype="multipart/form-data">
+ <html:file property="theFile" />
+ </html:form></pre>
+
+ <p>
+ WARNING: In order to correctly recognize uploaded files, the ActionForm bean
+ associated with this form must include a statement setting the corresponding
+ org.apache.struts.upload.FormFile property to null in the reset() method.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>accept</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Comma-delimited set of content types that the server you submit to
+ knows how to process. This list can be used by the client browser
+ to limit the set of file options that is made available for selection.
+ If not specified, no content type list will be sent.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. This is ignored
+ by most browsers. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Size of the file selection box to be displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ <strong>NOTE</strong>: When setting this to some value, whether
+ intentional or as the result (for example) of validation errors
+ forcing the user back to the original jsp, this value is ignored
+ by most browsers (for security reasons).
+ This means that your users will have to re-select any previously
+ selected files when submitting the form. Opera web browser will
+ prompt the user so they have a chance to abort the submit.
+ </p>
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value or body content (if any) if
+ property is not specified]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>form</name>
+ <tag-class>org.apache.struts.taglib.html.FormTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Define An Input Form
+ </strong></p>
+
+ <p>
+ Renders an HTML <form> element whose contents are described
+ by the body content of this tag. The form implicitly interacts
+ with the specified request scope or session scope bean to populate
+ the input fields with the current property values from the bean.
+ </p>
+ <p>
+ The form bean is located, and created if necessary, based on the
+ form bean specification for the associated <code>ActionMapping</code>.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this form will be submitted. This
+ value is also used to select the ActionMapping we are
+ assumed to be processing, from which we can identify
+ the appropriate form bean and scope. If a value is not
+ provided, the original URI (servletPath) for the request is
+ used. </p>
+
+ <p>If you are using extension mapping for selecting the
+ controller servlet, this value should be equal to the
+ <code>path</code> attribute of the corresponding
+ <code><action></code> element, optionally
+ followed by the correct extension suffix.</p>
+
+ <p>If you are using path mapping to select the
+ controller servlet, this value should be exactly equal
+ to the <code>path</code> attribute of the corresponding
+ <code><action></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>acceptCharset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The list of character encodings for input data that the server should
+ accept.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ disabled.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>enctype</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The content encoding to be used to submit this form, if the method
+ is POST. This must be set to "multipart/form-data" if you are using
+ the file tag to enable file upload. If not specified, the browser
+ default (normally "application/x-www-form-urlencoded") is used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The field name (among the fields on this form) to which initial
+ focus will be assigned with a JavaScript function. If not specified,
+ no special JavaScript for this purpose will be rendered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>focusIndex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If the focus field is a field array, such as a radio button group, you can
+ specify the index in the array to receive focus.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The HTTP method that will be used to submit this request
+ (GET, POST). [POST]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onreset</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is reset.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onsubmit</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed if the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if the Form's input fields should be
+ read only.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The form's focus <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHMTL mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Window target to which this form is submitted, such as
+ for use in framed presentations.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>frame</name>
+ <tag-class>org.apache.struts.taglib.html.FrameTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML frame element</strong></p>
+
+
+ <p>Renders an HTML <code><frame></code> element
+ with processing for the <code>src</code> attribute that is
+ identical to that performed by the <code><html:link></code>
+ tag for the <code>href</code> attribute. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies.</p>
+
+ <p>The base URL for this frame is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and application
+ prefix.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ logical name of a global Action that contains the actual
+ content-relative URI of the destination of this transfer.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameborder</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should a frame border be generated around this frame (1)
+ or not (0)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>frameName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Value for the <code>name</code> attribute of the rendered
+ <code><frame></code> element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>longdesc</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>URI of a long description of the frame. This description
+ should supplement the short description provided by the
+ <code>title</code> attribute, and may be particularly useful
+ for non-visual user agents.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginheight</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its top and bottom margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>marginwidth</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Integer</type>
+ <description>
+ <![CDATA[
+ <p>The amount of space (in pixels) to be left between the
+ frame's contents and its left and right margins.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>noresize</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Should users be disallowed from resizing the frame?
+ (true, false).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute,
+ or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scrolling</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Should scroll bars be created unconditionally (yes),
+ never (no), or only when needed (auto)?</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>hidden</name>
+ <tag-class>org.apache.struts.taglib.html.HiddenTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Hidden Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type hidden, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of <code>logic:iterate</code> tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>write</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Should the value of this field also be rendered to the
+ response page to make it visible, in addition to creating
+ an HTML type="hidden" element? By default, only the
+ hidden element is created.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>html</name>
+ <tag-class>org.apache.struts.taglib.html.HtmlTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML <code><html></code> Element</strong></p>
+
+ <p>Renders an HTML <code><html></code> element with
+ language attributes extracted from the user's current Locale
+ object, if there is one.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>lang</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Renders a lang attribute with the locale stored in the user's session. If not
+ found in the session, the language from the <code>Accept-Language</code>
+ HTTP header is used. If still not found, the default language for the server
+ is used.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>xhtml</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>Set to <code>true</code> in order to render
+ <code>xml:lang</code> and <code>xmlns</code> attributes
+ on the generated <code>html</code> element. This also
+ causes all other html tags to render as XHTML 1.0 (the
+ <html:xhtml/> tag has a similar purpose).
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>image</name>
+ <tag-class>org.apache.struts.taglib.html.ImageTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render an input tag of type "image"
+ </strong></p>
+
+
+ <p>Renders an HTML <code><input></code> tag of type
+ "image". The base URL for this image is calculated directly
+ based on the value specified in the <code>src</code> or
+ <code>page</code> attributes, or indirectly by looking up a
+ message resource string based on the <code>srcKey</code> or
+ <code>pageKey</code> attributes. You <strong>must</strong>
+ specify exactly one of these attributes.</p>
+
+ <p>If you would like to obtain the coordinates of the mouse
+ click that submitted this request, see the information below
+ on the <code>property</code> attribute.</p>
+
+ <p>This tag is only valid when nested inside a form tag body.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alignment option for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width (in pixels) of the border around this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The session attribute key for the Locale used to select
+ internationalized messages. If not specified, defaults to the
+ Struts standard value.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus
+ and a key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under
+ the mouse pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under
+ the mouse pointer but the pointer was moved outside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not
+ under the mouse pointer but the pointer is moved inside the
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path of the image for this
+ input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ module-relative path of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The property name of this image tag. The parameter names
+ for the request will appear as "property.x" and "property.y",
+ the x and y representing the coordinates of the mouse click
+ for the image. A way of retrieving these values through a
+ form bean is to define getX(), getY(), setX(), and setY()
+ methods, and specify your property as a blank string
+ (property="").</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The key of the message resources string specifying the
+ source URL of the image for this input tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The value that will be submitted if this image button
+ is pressed.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>img</name>
+ <tag-class>org.apache.struts.taglib.html.ImgTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML img tag</strong></p>
+
+
+ <p>Renders an HTML <code><img></code> element with
+ the image at the specified URL. Like the link tag, URL
+ rewriting will be applied automatically to the value
+ specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> to maintain session state
+ in the absence of cookies. This will allow dynamic
+ generation of an image where the content displayed for this
+ image will be taken from the attributes of this tag.</p>
+
+ <p>The base URL for this image is calculated directly based on
+ the value specified in <code>src</code>, <code>page</code>, or
+ <code>action</code> or <code>page</code>,
+ or indirectly by looking up a message resource string based on
+ the <code>srcKey</code> or <code>pageKey</code> attributes.
+ You <strong>must</strong> specify exactly one of these
+ attributes.</p>
+
+ <p>Normally, the <code>src</code>, <code>page</code>, or
+ <code>action</code> that you specify will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the <code>src</code> URL --
+ specify a single parameter with the <code>paramId</code>
+ attribute (at its associated attributes to select the value),
+ or specify the <code>name</code> (and optional
+ <code>property</code>) attributes to select a
+ <code>java.util.Map</code> bean that contains one or more
+ parameter ids and corresponding values.</p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter will be called on the JSP bean identified
+ by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ <code>src</code> URL. The value associated with each key
+ must be either a String or a String array representing the
+ parameter value(s), or an object whose toString() method
+ will be called. If a String array is specified, more than
+ one value for the same query parameter name will be
+ created.</p>
+
+ <p>You can specify the alternate text for this image (which
+ most browsers display as pop-up text block when the user
+ hovers the mouse over this image) either directly, through
+ the <code>alt</code> attribute, or indirectly from a message
+ resources bundle, using the <code>bundle</code> and
+ <code>altKey</code> attributes.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>align</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Where the image is aligned to. Can be one of the
+ following attributes:</p>
+ <ul>
+ <li>left - left justify, wrapping text on right</li>
+ <li>right -right justify, wrapping test on left</li>
+ <li>top - aligns the image with the top of the text on
+ the same row</li>
+ <li>middle - aligns the image's vertical center with the
+ text base line</li>
+ <li>bottom - aligns the image with the bottom of the
+ text's base line</li>
+ <li>texttop - aligns the image's top with that of the
+ text font on the same line</li>
+ <li>absmiddle - aligns the image's vertical center with the
+ absolute center of the text</li>
+ <li>absbottom - aligns the image with the absolute bottom
+ of the text font on the same row</li>
+ </ul>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>And alternative text to be displayed in browsers that
+ don't support graphics. Also used often as type of
+ context help over images.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>border</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the border surrounding the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>height</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The height of the image being displayed. This parameter
+ is very nice to specify (along with <code>width</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>hspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of horizontal spacing between the icon and
+ the text. The text may be in the same paragraph, or
+ be wrapped around the image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>imageName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scriptable name to be defined within this page, so
+ that you can reference it with intra-page scripts. In other
+ words, the value specified here will render a "name" element
+ in the generated image tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ismap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the server-side map that this image belongs
+ to.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request or session Locale attribute used
+ to look up internationalized messages.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated src URL. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path, starting with a slash, of
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>page</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify either the <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>pageKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the module-relative path for this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The action, starting with a slash, that will render
+ the image to be displayed by this tag. The rendered
+ URL for this image will automatically prepend the context
+ path of this web application (in the same manner as the
+ <code>action</code> attribute on the link tag works),
+ in addition to any necessary URL rewriting. You
+ <strong>must</strong> specify the <code>action</code>,
+ <code>page</code>
+ attribute or the <code>src</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this src URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the src URL. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this image will be transferred from
+ This image may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. This value will be used unmodified (other
+ than potential URL rewriting) as the value of the "src"
+ attribute in the rendered tag. You <strong>must</strong>
+ specify either the <code>page</code> attribute or the
+ <code>src</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>srcKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message key, in the message resources bundle named by
+ the <code>bundle</code> attribute, of the String to be
+ used as the URL of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>usemap</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the map as defined within this page for
+ mapping hot-spot areas of this image.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>vspace</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The amount of vertical spacing between the icon and
+ the text, above and below.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>width</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The width of the image being displayed. This parameter
+ is very nice to specify (along with <code>height</code>)
+ to help the browser render the page faster.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>javascript</name>
+ <tag-class>
+ org.apache.struts.taglib.html.JavascriptValidatorTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render JavaScript validation based on the
+ validation rules loaded by the ValidatorPlugIn.
+ </strong></p>
+
+ <p>
+ Render JavaScript validation based on the
+ validation rules loaded by the <code>ValidatorPlugIn</code>.
+ The set of validation rules that should be generated is based
+ on the formName attribute passed in, which should match
+ the name attribute of the form element in the xml file.
+ </p>
+ <p>
+ The dynamicJavascript and staticJavascript attributes
+ default to true, but if dynamicJavascript is set to <code>true</code>
+ and staticJavascript is set to <code>false</code> then only
+ the dynamic JavaScript will be rendered. If dynamicJavascript
+ is set to <code>false</code>
+ and staticJavascript is set to <code>true</code> then only
+ the static JavaScript will be rendered which can then be put in
+ separate JSP page so the browser can cache the static JavaScript.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>cdata</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ If set to "true" and XHTML has been enabled, the JavaScript will
+ be wrapped in a CDATA section to prevent XML parsing. The default is
+ "true" to comply with the W3C's recommendation.
+ </p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>dynamicJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the dynamic JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>formName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The key (form name) to retrieve a specific
+ set of validation rules. If "dynamicJavascript" is set
+ to <code>true</code> and formName is missing or is not
+ recognized by the <code>ValidatorPlugIn</code>, a
+ JspException will be thrown.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>method</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The alternate JavaScript method name to be used
+ instead of the of the default. The default is
+ 'validate' concatenated in front of
+ the key (form name) passed in (ex: validateRegistrationForm).
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ <description>
+ <![CDATA[
+ <p>
+ The current page of a set of validation rules
+ if the page attribute for the field element
+ in the xml file is in use.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scriptLanguage</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ The <script> element will not contain a language attribute
+ when this is set to false. The default is true but this property is ignored
+ in XHTML mode.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>src</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ The src attribute's value when defining
+ the html script element.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>staticJavascript</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to render the static JavaScript.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>htmlComment</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>
+ Whether or not to enclose the javascript
+ with HTML comments. This attribute is ignored in XHTML
+ mode because the script would be deleted by the XML parser. See
+ the cdata attribute for details on hiding scripts from XML
+ parsers.
+ Defaults to <code>true</code>.
+ </p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.7</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>link</name>
+ <tag-class>org.apache.struts.taglib.html.LinkTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render an HTML anchor or hyperlink</strong></p>
+
+
+ <p>Renders an HTML <code><a></code> element as an
+ anchor definition (if "linkName" is specified) or as a
+ hyperlink to the specified URL. URL rewriting will be
+ applied automatically, to maintain session state in the
+ absence of cookies. The content displayed for this
+ hyperlink will be taken from the body of this tag.</p>
+
+ <p>The base URL for this hyperlink is calculated based on
+ which of the following attributes you specify (you must
+ specify exactly one of them):</p>
+ <ul>
+ <li><em>forward</em> - Use the value of this attribute as the
+ name of a global <code>ActionForward</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there. If the forward is module-relative then
+ it must point to an action and NOT to a page.</li>
+ <li><em>action</em> - Use the value of this attribute as the
+ name of a <code>Action</code> to be looked
+ up, and use the module-relative or context-relative
+ URI found there.</li>
+ <li><em>href</em> - Use the value of this attribute unchanged.
+ </li>
+ <li><em>page</em> - Use the value of this attribute as a
+ module-relative URI, and generate a server-relative
+ URI by including the context path and module
+ prefix.</li>
+ </ul>
+
+ <p>Normally, the hyperlink you specify with one of the
+ attributes described in the previous paragraph will be left
+ unchanged (other than URL rewriting if necessary). However,
+ there are two ways you can append one or more dynamically
+ defined query parameters to the hyperlink -- specify a single
+ parameter with the <code>paramId</code> attribute (and its
+ associated attributes to select the value), or specify the
+ <code>name</code> (and optional <code>property</code>)
+ attributes to select a <code>java.util.Map</code> bean that
+ contains one or more parameter ids and corresponding values.
+ </p>
+
+ <p>To specify a single parameter, use the <code>paramId</code>
+ attribute to define the name of the request parameter to be
+ submitted. To specify the corresponding value, use one of the
+ following approaches:</p>
+ <ul>
+ <li><em>Specify only the <code>paramName</code> attribute</em>
+ - The named JSP bean (optionally scoped by the value of the
+ <code>paramScope</code> attribute) must identify a value
+ that can be converted to a String.</li>
+ <li><em>Specify both the <code>paramName</code> and
+ <code>paramProperty</code> attributes</em> - The specified
+ property getter method will be called on the JSP bean
+ identified by the <code>paramName</code> (and optional
+ <code>paramScope</code>) attributes, in order to select
+ a value that can be converted to a String.</li>
+ </ul>
+
+ <p>If you prefer to specify a <code>java.util.Map</code> that
+ contains all of the request parameters to be added to the
+ hyperlink, use one of the following techniques:</p>
+ <ul>
+ <li><em>Specify only the <code>name</code> attribute</em> -
+ The named JSP bean (optionally scoped by the value of
+ the <code>scope</code> attribute) must identify a
+ <code>java.util.Map</code> containing the parameters.</li>
+ <li><em>Specify both <code>name</code> and
+ <code>property</code> attributes</em> - The specified
+ property getter method will be called on the bean
+ identified by the <code>name</code> (and optional
+ <code>scope</code>) attributes, in order to return the
+ <code>java.util.Map</code> containing the parameters.</li>
+ </ul>
+
+ <p>As the <code>Map</code> is processed, the keys are assumed
+ to be the names of query parameters to be appended to the
+ hyperlink. The value associated with each key must be either
+ a String or a String array representing the parameter value(s),
+ or an object whose toString() method will be called.
+ If a String array is specified, more than one value for the
+ same query parameter name will be created.</p>
+
+ <p>Additionally, you can request that the current transaction
+ control token, if any, be included in the generated hyperlink
+ by setting the <code>transaction</code> attribute to
+ <code>true</code>.
+ You can also request that an anchor ("#xxx") be added to the
+ end of the URL that is created by any of the above mechanisms,
+ by using the <code>anchor</code> attribute.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately
+ to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then indexed parameter with name from indexId attribute
+ will be added to the query string. Indexed parameter looks like
+ "index[32]". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By this attribute different name for the indexed parameter can be
+ specified. Take a look to the "indexed" attribute for details.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>linkName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The anchor name to be defined within this page, so that
+ you can reference it with intra-page hyperlinks. In other
+ words, the value specified here will render a "name" element
+ in the generated anchor tag.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element loses input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse double click.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives input focus.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key press event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a key up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse down event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse move event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse out event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse over event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>JavaScript event handler that is executed when
+ this element receives a mouse up event.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute,
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, the <code>linkName</code>
+ attribute, or the <code>page</code> attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The tab order (ascending positive integers) for
+ this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The window target in which the resource requested by this
+ hyperlink will be displayed, for example in a framed
+ presentation.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>messages</name>
+ <tag-class>org.apache.struts.taglib.html.MessagesTag</tag-class>
+ <tei-class>org.apache.struts.taglib.html.MessagesTei</tei-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Conditionally display a set of accumulated messages.
+ </strong></p>
+
+ <p>Displays a set of messages prepared by a business
+ logic component and stored as an <code>ActionMessages</code>
+ object, <code>ActionErrors</code> object, a String,
+ or a String array in any scope. If
+ such a bean is not found, nothing will be rendered. The messages are
+ placed into the page scope in the body of this tag where they can be displayed
+ by standard JSP methods. (For example: <code><bean:write></code>,<code><c:out></code>)
+ </p>
+
+ <p>In order to use this tag successfully, you must have
+ defined an application scope <code>MessageResources</code>
+ bean under the default attribute name.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>id</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ <description>
+ <![CDATA[
+ The name of a page scope JSP bean that will contain the current
+ element of the collection of messages on each iteration, if it is not
+ <code>null</code>.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attribute key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attribute key for the Locale used to select
+ messages to be displayed. If not specified, defaults to
+ the Struts standard value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the bean in any scope under which our messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the property for which messages should be
+ displayed. If not specified, all messages (regardless
+ of property) are displayed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>header</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed before the iteration of messages begins.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>footer</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ This value is an optional message resource key that will
+ be printed after the iteration of messages has finished.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>message</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ By default the tag will retrieve the bean it will
+ iterate over from the <code>Globals.ERROR_KEY</code> constant string,
+ but if this attribute is set to 'true' the bean
+ will be retrieved from the <code>Globals.MESSAGE_KEY</code>
+ constant string. Also if this is set to 'true', any value
+ assigned to the name attribute will be ignored.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>multibox</name>
+ <tag-class>org.apache.struts.taglib.html.MultiboxTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Checkbox Input Field
+ </strong></p>
+
+ <p>Renders an HTML <input> element of type
+ <code>checkbox</code>, whose "checked" status is
+ initialized based on whether the specified value
+ matches one of the elements of the underlying
+ property's array of current values. This element is
+ useful when you have large numbers of checkboxes, and
+ prefer to combine the values into a single
+ array-valued property instead of multiple boolean
+ properties. This tag is only valid when nested
+ inside a form tag body.</p>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where none of the associated checkboxes
+ are selected, the <code>ActionForm</code> bean
+ associated with this form must include a statement
+ setting the corresponding array to zero length in the
+ <code>reset()</code> method.</p>
+
+ <p>The value to be returned to the server, if this checkbox is
+ selected, must be defined by one of the following methods:</p>
+ <ul>
+ <li>Specify a <code>value</code> attribute, whose contents will
+ be used literally as the value to be returned.</li>
+ <li>Specify no <code>value</code> attribute, and the nested
+ body content of this tag will be used as the value to be
+ returned.</li>
+ </ul>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to be transmitted if this checkbox is
+ checked when the form is submitted.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>option</name>
+ <tag-class>org.apache.struts.taglib.html.OptionTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Option
+ </strong></p>
+
+ <p>Render an HTML <code><option></code> element,
+ representing one of the choices for an enclosing
+ <code><select></code> element. The text displayed to the
+ user comes from either the body of this tag, or from a message
+ string looked up based on the <code>bundle</code>,
+ <code>locale</code>, and <code>key</code> attributes.</p>
+
+ <p>If the value of the corresponding bean property matches the
+ specified value, this option will be marked selected. This tag
+ is only valid when nested inside a
+ <code><html:select></code> tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this option should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>key</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If specified, defines the message key to be looked up in
+ the resource bundle specified by <code>bundle</code> for
+ the text displayed to the user for this option. If not
+ specified, the text to be displayed is taken from the body
+ content of this tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>locale</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The session attributes key for the Locale instance to use
+ for looking up the message specified by the
+ <code>key</code> attribute. If not specified, uses the
+ standard Struts session attribute name.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to be submitted for this field if this option is
+ selected by the user.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>options</name>
+ <tag-class>org.apache.struts.taglib.html.OptionsTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:optionsCollection></code> elements.</p>
+
+ <p>This tag operates in one of two major modes, depending on
+ whether or not the <code>collection</code> attribute is
+ specified. If the <code>collection</code> attribute is
+ included, the following rules apply:</p>
+ <ul>
+ <li>The <strong>collection</strong> attribute is interpreted
+ as the name of a JSP bean, in some scope, that itself
+ represents a collection of individual beans, one per option
+ value to be rendered.</li>
+ <li>The <strong>property</strong> attribute is interpreted as
+ the name of a property of the individual beans included in
+ the collection, and is used to retrieve the value that will
+ be returned to the server if this option is selected.</li>
+ <li>The <strong>labelProperty</strong> attribute is interpreted
+ as the name of a property of the individual beans included
+ in the collection, and is used to retrieve the label that
+ will be displayed to the user for this option. If the
+ <code>labelProperty</code> attribute is not specified, the
+ property named by the <code>property</code> attribute will
+ be used to select both the value returned to the server and
+ the label displayed to the user for this option.</li>
+ </ul>
+
+ <p>If the <code>collection</code> attribute is not specified,
+ the rules described in the remainder of this section apply.</p>
+
+ <p>The collection of values actually selected depends on the presence or
+ absence of the <code>name</code> and <code>property</code> attributes. The
+ following combinations are allowed:</p>
+ <ul>
+ <li><em>Only <code>name</code> is specified</em> - The value of this attribute
+ is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>property</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>name</code> and <code>property</code> are specified</em> -
+ The value of the <code>name</code> attribute identifies a JSP bean
+ in some scope. The value of the <code>property</code> attribute is the
+ name of some property of that bean which will return the collection.</li>
+ </ul>
+
+ <p>The collection of labels displayed to the user can be the same as the
+ option values themselves, or can be different, depending on the presence or
+ absence of the <code>labelName</code> and <code>labelProperty</code>
+ attributes. If this feature is used, the collection of labels must contain
+ the same number of elements as the corresponding collection of values.
+ The following combinations are allowed:</p>
+ <ul>
+ <li><em>Neither <code>labelName</code> nor <code>labelProperty</code> is
+ specified</em> - The labels will be the same as the option values
+ themselves.</li>
+ <li><em>Only <code>labelName</code> is specified</em> - The value of this
+ attribute is the name of a JSP bean in some scope that is the
+ collection.</li>
+ <li><em>Only <code>labelProperty</code> is specified</em> - The value of this
+ attribute is the name of a property of the ActionForm bean associated
+ with our form, which will return the collection.</li>
+ <li><em>Both <code>labelName</code> and <code>labelProperty</code> are
+ specified</em> - The value of the <code>labelName</code> attribute
+ identifies a JSP bean in some scope. The value of the
+ <code>labelProperty</code> attribute is the name of some property of
+ that bean which will return the collection.</li>
+ </ul>
+
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+
+ ]]>
+ </description>
+ <attribute>
+ <name>collection</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) which is itself a
+ Collection of other beans, each of which has properties
+ named by the "property" and "labelProperty" attributes
+ that are used to retrieve the value and label for each
+ option, respectively.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of labels to
+ be displayed to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>labelProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the labelName
+ attribute, that will return the collection of labels to be displayed
+ to the user for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the JSP bean (in some scope) containing the collection of
+ values to be returned to the server for these options. If not
+ specified, the form bean associated with our form is assumed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of values to returned
+ to the server for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>optionsCollection</name>
+ <tag-class>
+ org.apache.struts.taglib.html.OptionsCollectionTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render a Collection of Select Options
+ </strong></p>
+
+ <p>Renders a set of HTML <code><option></code> elements,
+ representing possible choices for a <code><select></code>
+ element. This tag can be used multiple times within a single
+ <code><html:select></code> element, either in conjunction
+ with or instead of one or more <code><html:option></code>
+ or <code><html:options></code> elements.</p>
+
+ <p>This tag operates on a collection of beans, where each bean
+ has a <strong>label</strong> property and a <strong>value</strong>
+ property. The actual names of these properties can be configured
+ using the <code>label</code> and <code>value</code> attributes
+ of this tag.</p>
+
+ <p>This tag differs from the <code><html:options></code> tag
+ in that it makes more consistent use of the <code>name</code> and
+ <code>property</code> attributes, and allows the collection to be
+ more easily obtained from the enclosing form bean.</p>
+
+ <p>Note that this tag does not support a <code>styleId</code>
+ attribute, as it would have to apply the value to all the
+ <code>option</code> elements created by this element, which would
+ mean that more than one <code>id</code> element might have the same
+ value, which the HTML specification says is illegal.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>filter</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>false</code> if you do NOT want the option labels
+ filtered for sensitive characters in HTML. By default, such
+ values are filtered.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>label</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the label to be rendered for each option. Defaults to "label".
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the form bean, or the bean specified by the name
+ attribute, that will return the collection of objects to be
+ rendered for these options.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The property of the bean within the collection which represents
+ the value to be rendered for each option. Defaults to "value".
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>password</name>
+ <tag-class>org.apache.struts.taglib.html.PasswordTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Password Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type password, populated
+ from the specified value or the specified property of the bean
+ associated with our current form. This tag is only valid when
+ nested inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>redisplay</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Boolean flag indicating whether or not existing values
+ will be redisplayed if they exist. Even though the
+ redisplayed value will be shown as asterisks on the
+ visible HTML page, the cleartext of the actual password
+ value will be visible though the "Show Page Source"
+ menu option of the client browser. You may wish to
+ set this value to <code>false</code> on login pages.
+ Defaults to <code>true</code> for consistency with
+ all other form tags that redisplay their contents.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button. This value will
+ also be submitted as the value of the specified request parameter.
+ [Body of this tag (if any)]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>radio</name>
+ <tag-class>org.apache.struts.taglib.html.RadioTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Radio Button Input Field
+ </strong></p>
+
+ <p>
+ Renders an HTML <input> element of type radio, populated from
+ the specified property of the bean associated with our current form.
+ This tag is only valid when nested inside a form tag body.
+ </p>
+ <p>
+ If an iterator is used to render a series of radio tags, the
+ idName attribute may be used to specify the name of the bean
+ exposed by the iterator. In this case, the value attribute is
+ used as the name of a property on the idName bean that returns
+ the value of the radio tag in this iteration.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted when
+ rendering the current value of this input field. If not specified,
+ the bean associated with the form tag we are nested within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The corresponding bean property for this radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the radio tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>idName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the bean (in some scope) that will return the
+ value of the radio tag. Usually exposed
+ by an iterator. When the idName attribute is
+ present, the value attribute is used as the name of the
+ property on the idName bean that will return the
+ value of the radio tag for this iteration.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.1</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>reset</name>
+ <tag-class>org.apache.struts.taglib.html.ResetTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Reset Button Input Field
+ </strong></p>
+
+ Renders an HTML <input> element of type reset.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the input field that will be generated.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value of the label to be placed on this button.
+ [Body of this tag (if any), or "Reset"]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>rewrite</name>
+ <tag-class>org.apache.struts.taglib.html.RewriteTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render an URI</strong></p>
+
+ <p>Renders a request URI based on exactly the same rules
+ as the <code><a href="#link">link</a></code> tag does,
+ but without creating
+ the <code><a></code> hyperlink. This value is useful
+ when you want to generate a string constant for use by
+ a JavaScript procedure.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>action</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a <code>Action</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+
+ <p>Additionally, you can specify a <code>module</code> prefix
+ for linking to other modules.</p>
+
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.0</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>module</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Prefix name of a <code>Module</code> that
+ contains the action mapping for the <code>Action</code>
+ that is specified by the <code>action</code> attribute.
+ You <strong>must</strong> specify an <code>action</code>
+ attribute for this to have an effect.</p>
+
+ <p><strong>Note: </strong>Use "" to map to the default module.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>anchor</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Optional anchor tag ("#xxx") to be added to the generated
+ hyperlink. Specify this value <strong>without</strong> any
+ "#" character.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>forward</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Logical name of a global <code>ActionForward</code> that
+ contains the actual content-relative URI of the destination
+ of this transfer. This hyperlink may be dynamically
+ modified by the inclusion of query parameters, as described
+ in the tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>href</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The URL to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify
+ exactly one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that contains a <code>Map</code>
+ representing the query parameters (if <code>property</code>
+ is not specified), or a JSP bean whose property getter is
+ called to return a <code>Map</code> (if <code>property</code>
+ is specified).</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The module-relative path (beginning with a "/"
+ character) to which this hyperlink will transfer control
+ if activated. This hyperlink may be dynamically modified
+ by the inclusion of query parameters, as described in the
+ tag description. You <strong>must</strong> specify exactly
+ one of the <code>action</code> attribute, the
+ <code>forward</code> attribute, the
+ <code>href</code> attribute, or the <code>page</code>
+ attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of the request parameter that will be dynamically
+ added to the generated hyperlink. The corresponding value is
+ defined by the <code>paramName</code> and (optional)
+ <code>paramProperty</code> attributes, optionally scoped by
+ the <code>paramScope</code> attribute</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramName</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a JSP bean that is a String containing the
+ value for the request parameter named by <code>paramId</code>
+ (if <code>paramProperty</code> is not specified), or a JSP
+ bean whose property getter is called to return a String
+ (if <code>paramProperty</code> is specified). The JSP bean
+ is constrained to the bean scope specified by the
+ <code>paramScope</code> property, if it is specified.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>paramName</code> attribute, whose return value must
+ be a String containing the value of the request parameter
+ (named by the <code>paramId</code> attribute) that will be
+ dynamically added to this hyperlink.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>paramScope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>paramName</code> attribute. If not specified,
+ all scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The name of a property of the bean specified by the
+ <code>name</code> attribute, whose return value must be
+ a <code>java.util.Map</code> containing the query parameters
+ to be added to the hyperlink. You <strong>must</strong>
+ specify the <code>name</code> attribute if you specify
+ this attribute.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The scope within which to search for the bean specified
+ by the <code>name</code> attribute. If not specified, all
+ scopes are searched.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>transaction</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, any current transaction
+ control token will be included in the generated hyperlink,
+ so that it will pass an <code>isTokenValid()</code> test
+ in the receiving Action.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>useLocalEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ <p>If set to <code>true</code>, LocalCharacterEncoding will be
+ used, that is, the characterEncoding set to the HttpServletResponse,
+ as prefered character encoding rather than UTF-8, when
+ URLEncoding is done on parameters of the URL.</p>
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>select</name>
+ <tag-class>org.apache.struts.taglib.html.SelectTag</tag-class>
+ <body-content>JSP</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Select Element
+ </strong></p>
+
+ <p>Renders an HTML <select> element, associated
+ with a bean property specified by our attributes. This
+ tag is only valid when nested inside a form tag body.
+ </p>
+
+ <p>This tag operates in two modes, depending upon the
+ state of the <code>multiple</code> attribute, which
+ affects the data type of the associated property you
+ should use:</p>
+ <ul>
+ <li><em>multiple="true" IS NOT selected</em> -
+ The corresponding property should be a scalar
+ value of any supported data type.</li>
+ <li><em>multiple="true" IS selected</em> -
+ The corresponding property should be an array
+ of any supported data type.</li>
+ </ul>
+
+ <p><strong>WARNING</strong>: In order to correctly
+ recognize cases where no selection at all is made, the
+ <code>ActionForm</code> bean associated with this form
+ must include a statement resetting the scalar property
+ to a default value (if <code>multiple</code> is not
+ set), or the array property to zero length (if
+ <code>multiple</code> is set) in the
+ <code>reset()</code> method.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>multiple</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ If set to any arbitrary value, the rendered
+ select element will support
+ multiple selections.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ to determine which option should be pre-selected when rendering
+ this input field. If not specified, the bean associated with
+ the enclosing <code><html:form></code> tag is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of available options displayed at one time.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value to compare with for marking an option selected.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>submit</name>
+ <tag-class>org.apache.struts.taglib.html.SubmitTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Submit Button
+ </strong></p>
+
+ Renders an HTML <input> element of type <code>submit</code>.
+ <p>
+ If a graphical button is needed (a button with an image), then the
+ <a href="#image"><code>image</code></a> tag is more appropriate.
+ </p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag. If <code>true</code>
+ then name of the html tag will be rendered as
+ "propertyName[34]". Number in brackets will be generated for
+ every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of the request parameter that will be included with this
+ submission, set to the specified value.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS styles to be applied to this HTML element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Identifier to be assigned to this HTML element (renders
+ an "id" attribute).
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The value of the button label.
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>text</name>
+ <tag-class>org.apache.struts.taglib.html.TextTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>Render An Input Field of Type text</strong></p>
+
+ <p>Render an input field of type text. This tag is only valid when
+ nested inside a form tag body.</p>
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The keyboard character used to move focus immediately to this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>maxlength</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Maximum number of input characters to accept. [No limit]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>size</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Number of character positions to allocate. [Browser default]
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>textarea</name>
+ <tag-class>org.apache.struts.taglib.html.TextareaTag</tag-class>
+ <description>
+ <![CDATA[
+ <p><strong>
+ Render A Textarea
+ </strong></p>
+
+ Render a textarea element. This tag is only valid when nested
+ inside a form tag body.
+ ]]>
+ </description>
+ <attribute>
+ <name>accesskey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The keyboard character used to move focus immediately to this
+ element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>alt</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The alternate text for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>altKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key of the alternate text for this
+ element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>bundle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The servlet context attributes key for the MessageResources
+ instance to use. If not specified, defaults to the
+ application resources configured for our action servlet.
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>cols</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of columns to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>disabled</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ disabled.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Name of the request scope bean under which our error messages
+ have been stored. If not present, the name specified by the
+ <code>Globals.ERROR_KEY</code> constant string will be used.</p>
+
+ <p><strong>N.B.</strong> This is used in conjunction with the
+ <code>errorStyle</code>, <code>errorStyleClass</code> and
+ <code>errorStyleId</code> attributes and should be set to
+ the same value as the <code>name</code> attribute on the
+ <html:errors/> tag.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyle</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element if
+ an error exists for it.</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>style</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element if
+ an error exists for it (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleClass</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>errorStyleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element if
+ an error exists for it (renders an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, this overrides the
+ <code>styleId</code> attribute in the event of an error.</p>
+
+ <dl><dt><b>Since:</b></dt>
+ <dd>Struts 1.2.5</dd></dl>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>indexed</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Valid only inside of logic:iterate tag.
+ If <code>true</code> then name of the html tag will be rendered as
+ "id[34].propertyName". Number in brackets will be generated
+ for every iteration and taken from ancestor logic:iterate tag.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The attribute name of the bean whose properties are consulted
+ when rendering the current value of this input field. If not
+ specified, the bean associated with the form tag we are nested
+ within is utilized.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onblur</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onchange</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element loses input
+ focus and its value has changed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>ondblclick</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives a
+ mouse double click.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onfocus</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element receives input
+ focus.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeydown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeypress</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is depressed and released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onkeyup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element has focus and a
+ key is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousedown</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the mouse
+ pointer and a mouse button is depressed.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmousemove</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and the pointer is moved.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseout</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was under the
+ mouse pointer but the pointer was moved outside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseover</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element was not under
+ the mouse pointer but the pointer is moved inside the element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onmouseup</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when this element is under the
+ mouse pointer and a mouse button is released.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>onselect</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ JavaScript event handler executed when a
+ when a user selects some text in a text field.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Name of this input field, and the name of the corresponding bean
+ property if value is not specified. The corresponding bean property
+ (if any) must be of type String.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>readonly</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ <description>
+ <![CDATA[
+ Set to <code>true</code> if this input field should be
+ read only.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>rows</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The number of rows to display.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>style</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS styles to be applied to this HTML element.</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyle</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleClass</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>CSS stylesheet class to be applied to this HTML element
+ (renders a "class" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleClass</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>styleId</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>Identifier to be assigned to this HTML element (renders
+ an "id" attribute).</p>
+
+ <p><strong>N.B.</strong> If present, the <code>errorStyleId</code>
+ overrides this attribute in the event of an error for the element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>tabindex</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ The tab order (ascending positive integers) for this element.
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The advisory title for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>titleKey</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ <p>The message resources key for the advisory title
+ for this element.</p>
+ ]]>
+ </description>
+ </attribute>
+ <attribute>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <description>
+ <![CDATA[
+ Value to which this field should be initialized. [Use the
+ corresponding bean property value]
+ ]]>
+ </description>
+ </attribute>
+ </tag>
+ <tag>
+ <name>xhtml</name>
+ <tag-class>org.apache.struts.taglib.html.XhtmlTag</tag-class>
+ <body-content>empty</body-content>
+ <description>
+ <![CDATA[
+ <p><strong>Render HTML tags as XHTML</strong></p>
+
+ <p>
+ Using this tag in a page tells all other html taglib tags
+ to render themselves as XHTML 1.0. This is useful
+ when composing pages with JSP includes or Tiles.
+ <html:html xhtml="true"> has a similar effect. This
+ tag has no attributes; you use it like this: <html:xhtml/>.
+ </p>
+ <p>
+ <strong>Note</strong>: Included pages do not inherit the rendering
+ style of the including page. Each JSP fragment or Tile must use this
+ tag to render as XHTML.
+ </p>
+ ]]>
+ </description>
+ </tag>
+</taglib>
+
diff --git a/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..9f04cd7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts/lab-2-1-src/webapp/WEB-INF/web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+ <display-name>Struts MailReader Application</display-name>
+
+ <!-- Action Servlet Configuration -->
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
+ <init-param>
+ <param-name>config</param-name>
+ <param-value>
+ /WEB-INF/struts-config.xml,
+ /WEB-INF/Register-configure.xml,
+ /WEB-INF/Logon-configure.xml
+ </param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+
+ <!-- Action Servlet Mapping -->
+ <servlet-mapping>
+ <servlet-name>action</servlet-name>
+ <url-pattern>*.do</url-pattern>
+ </servlet-mapping>
+
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/browse/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/browse.iml b/struts-sandbox/mailreader-course/struts2/browse/browse.iml
new file mode 100644
index 0000000..2e9f591
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/browse.iml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/browse/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/browse" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/browse" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/AuthenticationInterceptor.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/AuthenticationInterceptor.java
new file mode 100644
index 0000000..bf08889
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/AuthenticationInterceptor.java
@@ -0,0 +1,31 @@
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.Map;
+
+public class AuthenticationInterceptor implements Interceptor {
+
+ public void destroy() {
+ }
+
+ public void init() {
+ }
+
+ public String intercept(ActionInvocation actionInvocation) throws Exception {
+
+ Map session = actionInvocation.getInvocationContext().getSession();
+
+ User user = (User) session.get(MailReaderSupport.USER_KEY);
+
+ boolean isAuthenticated = (null != user) && (null != user.getDatabase());
+
+ if (!isAuthenticated) {
+ return Action.LOGIN;
+ } else {
+ return actionInvocation.invoke();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Login-validation.xml b/struts-sandbox/mailreader-course/struts2/browse/src/java/Login-validation.xml
new file mode 100644
index 0000000..ed9359f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Login-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Login.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/Login.java
new file mode 100644
index 0000000..16deb09
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Login.java
@@ -0,0 +1,22 @@
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Login extends MailReaderSupport {
+
+ public String save() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Logout.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/Logout.java
new file mode 100644
index 0000000..4f17f10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Logout.java
@@ -0,0 +1,9 @@
+public class Logout extends MailReaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..4fa163b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/MailReaderSupport.java
@@ -0,0 +1,325 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport
+ implements ApplicationAware, SessionAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Subscription form properties ----
+
+ private String host;
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String value) {
+ host = value;
+ }
+
+ // ---- Task property (utilized by UI) ----
+
+ private String task = null;
+
+ public String getTask() {
+ return task;
+ }
+
+ public void setTask(String value) {
+ task = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ public static final String USER_KEY = "user";
+
+ public static final String HOST = "host";
+
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ public static final String CANCEL = "cancel";
+
+ public static final String CREATE = "Create";
+
+ public static final String EDIT = "Edit";
+
+ public static final String DELETE = "Delete";
+
+ // ---- Message Keys ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "error.database.missing";
+
+ public static final String ERROR_USERNAME_UNIQUE =
+ "error.username.unique";
+
+ public static final String ERROR_PASSWORD_MISMATCH =
+ "error.password.mismatch";
+
+ public static final String ERROR_PASSWORD_MATCH =
+ "error.password.match";
+
+ public static final String ERROR_HOST_UNIQUE
+ = "That hostname is already defined";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText(ERROR_DATABASE_MISSING));
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- Subscription property ----
+
+ public Subscription getSubscription() {
+ return (Subscription) getSession().get(SUBSCRIPTION_KEY);
+ }
+
+ public void setSubscription(Subscription subscription) {
+ getSession().put(SUBSCRIPTION_KEY, subscription);
+ }
+
+
+ public String getSubscriptionHost() {
+ Subscription sub = getSubscription();
+ if (null == sub) {
+ return null;
+ }
+ return sub.getHost();
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(USER_KEY, user);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+
+ User user = getDatabase().findUser(username);
+
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+
+ if (user == null) {
+ addFieldError(PASSWORD_MISMATCH_FIELD,
+ getText(ERROR_PASSWORD_MISMATCH));
+ }
+
+ return user;
+
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+ /**
+ * <p>Provide a "temporary" User Subscription object
+ * that can be used tocapture input values.</p>
+ */
+ public void createInputSubscription() {
+ Subscription sub = new MemorySubscription(getUser(), null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = getUser().findSubscription(host);
+ return subscription;
+ }
+
+ public Subscription findSubscription() {
+ return findSubscription(getHost());
+ }
+
+ public void removeSubscription() {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(SUBSCRIPTION_KEY);
+ }
+
+ public void copySubscription(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ BeanUtils.setValues(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }
+
+ public Subscription createSubscription(String host) {
+
+ Subscription sub;
+
+ sub = findSubscription(host);
+
+ if (null != sub) {
+ // FIXME - localization - "error.host.unique")
+ addFieldError(HOST, ERROR_HOST_UNIQUE);
+ return null;
+ }
+
+ return getUser().createSubscription(host);
+ }
+
+ // ---- Alias ----
+
+ public String cancel() {
+ return CANCEL;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/NPE.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/NPE.java
new file mode 100644
index 0000000..229ed0f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/NPE.java
@@ -0,0 +1,9 @@
+import com.opensymphony.xwork2.Action;
+
+public class NPE implements Action {
+
+ public String execute() {
+ throw new NullPointerException("Oops!");
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/browse/src/java/Register-validation.xml
new file mode 100644
index 0000000..f8155f6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Register-validation.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/Register.java
new file mode 100644
index 0000000..78f2bde
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Register.java
@@ -0,0 +1,65 @@
+import com.opensymphony.util.BeanUtils;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String input() throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ setTask(EDIT);
+ BeanUtils.setValues(this, user, null);
+ setPassword(null);
+ } else {
+ setTask(CREATE);
+ }
+
+ return INPUT;
+ }
+
+ public String save()
+ throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ // FIXME: Any way to call the RegisterSave validators from here?
+ String newPassword = getPassword();
+ boolean changing = ((null != newPassword) && (newPassword.length() > 0));
+ if (!changing) {
+ setPassword(user.getPassword());
+ } else {
+ String confirmPassword = getPassword2();
+ boolean matches = ((null != confirmPassword)
+ && (confirmPassword.equals(newPassword)));
+ if (matches) {
+ user.setPassword(newPassword);
+ } else {
+ addActionError(getText(ERROR_PASSWORD_MATCH));
+ return INPUT;
+ }
+ }
+ BeanUtils.setValues(user, this, null);
+ }
+
+ if (!editing) {
+ user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return INPUT;
+ }
+
+ user = createUser(getUsername(), getPassword());
+ setUser(user);
+ }
+
+ saveUser();
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/RegisterCreate-validation.xml b/struts-sandbox/mailreader-course/struts2/browse/src/java/RegisterCreate-validation.xml
new file mode 100644
index 0000000..6896407
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/RegisterCreate-validation.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="errors.range"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.match"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/RegisterCreate.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/RegisterCreate.java
new file mode 100644
index 0000000..4895652
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/RegisterCreate.java
@@ -0,0 +1,5 @@
+/**
+ * <p>Stub class to allow extra validation on initial Save.</p>
+ */
+public class RegisterCreate extends Register {
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Subscribe-validation.xml b/struts-sandbox/mailreader-course/struts2/browse/src/java/Subscribe-validation.xml
new file mode 100644
index 0000000..bc422c8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Subscribe-validation.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="host">
+ <field-validator type="requiredstring">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/Subscribe.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/Subscribe.java
new file mode 100644
index 0000000..e5d8164
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/Subscribe.java
@@ -0,0 +1,74 @@
+import com.opensymphony.xwork2.Preparable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class Subscribe extends MailReaderSupport
+ implements Preparable {
+
+ private Map types = null;
+
+ public Map getTypes() {
+ return types;
+ }
+
+ public void prepare() {
+
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+
+ setHost(getSubscriptionHost());
+ }
+
+ public String input() {
+ createInputSubscription();
+ setTask(CREATE);
+ return INPUT;
+ }
+
+ public String find() {
+
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+
+ if (sub == null) {
+ return ERROR;
+ }
+
+ setSubscription(sub);
+
+ return SUCCESS;
+
+ }
+
+ public String delete() {
+
+ setTask(DELETE);
+ return find();
+ }
+
+ public String edit() {
+
+ setTask(EDIT);
+ return find();
+ }
+
+ public String save() throws Exception {
+
+ if (DELETE.equals(getTask())) {
+ removeSubscription();
+ }
+
+ if (CREATE.equals(getTask())) {
+ copySubscription(getHost());
+ }
+
+ if (hasErrors()) return INPUT;
+
+ saveUser();
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/SubscribeSave-validation.xml b/struts-sandbox/mailreader-course/struts2/browse/src/java/SubscribeSave-validation.xml
new file mode 100644
index 0000000..7d28623
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/SubscribeSave-validation.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="subscription.username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.type">
+ <field-validator type="requiredstring">
+ <message key="error.type.invalid"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/SubscribeSave.java b/struts-sandbox/mailreader-course/struts2/browse/src/java/SubscribeSave.java
new file mode 100644
index 0000000..f5cba7d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/SubscribeSave.java
@@ -0,0 +1,8 @@
+public final class SubscribeSave extends Subscribe {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ getSubscription().setAutoConnect(false);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/browse/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/browse/src/java/resources.properties
new file mode 100644
index 0000000..7fc1152
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/resources.properties
@@ -0,0 +1,105 @@
+hello.message = Congratulations! Struts is up and running ...
+
+index.title=MailReader
+index.login=Log into MailReader
+index.registration=Register with MailReader
+
+registration.title.create=MailReader - Register - Create
+registration.title.edit=MailReader - Register - Edit
+
+username=Username
+password=Password
+password2=(Repeat) Password
+fullName=Full Name
+fromAddress=From Address
+replyToAddress=Reply To Address
+
+button.cancel=Cancel
+button.save=Save
+button.reset=Reset
+button.confirm=Confirm
+
+menu.title=MailReader - Main Menu
+menu.heading=Menu Options for
+menu.registration=Edit your registration profile
+menu.logout=Log out of MailReader
+
+login.title=MailReader - Logon
+
+error.database.missing=User database is missing, cannot validate logon credentials
+error.username.unique=That username is already in use - please select another
+error.password.mismatch=Invalid username and/or password, please try again
+
+error.username.required=Username is required
+error.fullName.required=Full Name is required
+error.fromAddress.required=From Address is required
+error.fromAddress.format=Invalid format for From Address
+error.replyToAddress.format=Invalid format for Reply To Address
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+
+error.host.required=Mail Server is required
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+
+# Future use
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+struts.messages.invalid.token=Cannot submit this form out of order
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/resources_ja.properties b/struts-sandbox/mailreader-course/struts2/browse/src/java/resources_ja.properties
new file mode 100644
index 0000000..60eb6d2
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/resources_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.login=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+login.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+menu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+menu.logout=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+menu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+menu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/resources_ru.properties b/struts-sandbox/mailreader-course/struts2/browse/src/java/resources_ru.properties
new file mode 100644
index 0000000..bff1ac3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/resources_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.login=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+login.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+menu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+menu.logout=\u0412\u044b\u0439\u0442\u0438
+menu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/struts.properties b/struts-sandbox/mailreader-course/struts2/browse/src/java/struts.properties
new file mode 100644
index 0000000..75c8136
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/struts.properties
@@ -0,0 +1 @@
+struts.custom.i18n.resources=resources
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/browse/src/java/struts.xml
new file mode 100644
index 0000000..bde680f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/java/struts.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <interceptors>
+
+ <interceptor name="authentication"
+ class="AuthenticationInterceptor"/>
+
+ <interceptor-stack name="user">
+ <interceptor-ref name="authentication"/>
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="user-submit">
+ <interceptor-ref name="token-session"/>
+ <interceptor-ref name="user"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="guest">
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="guest-submit">
+ <interceptor-ref name="token-session"/>
+ <interceptor-ref name="guest"/>
+ </interceptor-stack>
+
+ </interceptors>
+
+ <default-interceptor-ref name="user"/>
+
+ <default-action-ref name="Missing"/>
+
+ <global-results>
+ <result name="error">/pages/Error.jsp</result>
+ <result name="login" type="redirect-action">Login</result>
+ </global-results>
+
+ <global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Throwable"/>
+ </global-exception-mappings>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Register_cancel" class="Register" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Register_create" class="RegisterCreate" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Menu" class="MailReaderSupport">
+ <result>/pages/Menu.jsp</result>
+ </action>
+
+ <action name="Logout" class="Logout">
+ <result type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login" class="Login" method="input">
+ <result name="input">/pages/Login.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Login_cancel" class="Login" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Login_save" class="Login" method="save">
+ <result name="input">/pages/Login.jsp</result>
+ <result type="redirect-action">Menu</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Subscribe" class="Subscribe" method="input">
+ <result name="input">/pages/Subscribe.jsp</result>
+ <result type="redirect-action">Register</result>
+ </action>
+
+ <action name="Subscribe_delete" class="Subscribe" method="delete">
+ <result name="input" type="redirect-action">Login</result>
+ <result>/pages/Subscribe.jsp</result>
+ </action>
+
+ <action name="Subscribe_edit" class="Subscribe" method="edit">
+ <result name="input" type="redirect-action">Login</result>
+ <result>/pages/Subscribe.jsp</result>
+ </action>
+
+ <action name="Subscribe_save" class="SubscribeSave" method="save">
+ <result name="input">/pages/Subscribe.jsp</result>
+ <result type="redirect-action">Register</result>
+ <interceptor-ref name="user-submit"/>
+ </action>
+
+ <action name="NPE" class="NPE">
+ <result>/pages/Hello.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/browse/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/browse/src/test/RegisterTest.java
new file mode 100644
index 0000000..8586366
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/test/RegisterTest.java
@@ -0,0 +1,35 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setSession(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testSave() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/browse/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..74fbac7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,5 @@
+&welcome-open;
+<clickLink
+ description="Click Register"
+ label="Register with MailReader"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..54601e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration page title"
+ text="MailReader - Register"/>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-trillian.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-trillian.xml
new file mode 100644
index 0000000..7561f05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/register-trillian.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+<setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/save-click.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/save-click.xml
new file mode 100644
index 0000000..a02a1db
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/save-click.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Save"
+ name="Save"/>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/welcome-open.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/welcome-open.xml
new file mode 100644
index 0000000..a073531
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/entities/welcome-open.xml
@@ -0,0 +1,6 @@
+<invoke
+ description="Open welcome action"
+ url="Welcome.do"/>
+<verifyTitle
+ description="Welcome page title"
+ text="MailReader"/>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2151ea8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..aa6975a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = lab-2-2
+webapps.home = /opt/Apache/Tomcat-5.5/webapps/
+resource.home = ${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"
+# mailreader.home =
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..4f34768
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+ */
+ -->
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="lab-2-2"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register"/>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Trillian (MSS)">
+ &config;
+ <steps>
+ ®ister-open;
+ ®ister-trillian;
+ <verifyTitle
+ description="Menu page title"
+ text="MailReader - Menu"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Error.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Error.jsp
new file mode 100644
index 0000000..adb7e93
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Error.jsp
@@ -0,0 +1,38 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Unexpected Error</title>
+</head>
+
+<body>
+<h2>An unexpected error has occured</h2>
+
+<p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+</p>
+
+<hr/>
+
+<h3>Error Message</h3>
+
+<s:actionerror/>
+
+<p>
+ <s:property value="%{exception.message}"/>
+</p>
+
+<hr/>
+
+<h3>Technical Details</h3>
+
+<p>
+ <s:property value="%{exceptionStack}"/>
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..51e788d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Hello.jsp
@@ -0,0 +1,14 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Login.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Login.jsp
new file mode 100644
index 0000000..97d89a0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Login.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="login.title"/>
+ </title>
+</head>
+
+<body onLoad="self.focus();document.Login_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Login_save" validate="true">
+ <s:textfield key="username"/>
+
+ <s:password key="password" showPassword="true"/>
+
+ <s:submit key="button.save"/>
+
+ <s:submit action="Login_cancel" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Menu.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Menu.jsp
new file mode 100644
index 0000000..874a6f7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Menu.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="menu.title"/>
+ </title>
+</head>
+
+<body>
+<h3>
+ <s:text name="menu.heading"/>
+ <s:property value="user.fullName"/>
+</h3>
+<ul>
+ <li><a href="<s:url action="Register" />">
+ <s:text name="menu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url action="Logout"/>">
+ <s:text name="menu.logout"/>
+ </a>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..5bcc12e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Register.jsp
@@ -0,0 +1,126 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title>
+ <s:text name="registration.title.create"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title>
+ <s:text name="registration.title.edit"/>
+ </title>
+ </s:if>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save" validate="true">
+ <s:hidden name="task"/>
+ <s:if test="task == 'Create'">
+ <s:textfield key="username"/>
+ </s:if>
+ <s:else>
+ <s:label key="username"/>
+ <s:hidden name="username"/>
+ </s:else>
+
+ <s:password key="password"/>
+
+ <s:password key="password2"/>
+
+ <s:textfield key="fullName"/>
+
+ <s:textfield key="fromAddress"/>
+
+ <s:textfield key="replyToAddress"/>
+
+ <s:if test="task == 'Create'">
+ <s:submit key="button.save" action="Register_create"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Welcome" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:if>
+ <s:else>
+ <s:submit key="button.save"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Menu" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:else>
+
+</s:form>
+
+<s:if test="task == 'Edit'">
+ <div align="center">
+ <h3>
+ <s:text name="heading.subscriptions"/>
+ </h3>
+ </div>
+
+ <table border="1" width="100%">
+
+ <tr>
+ <th align="center" width="30%">
+ <s:text name="heading.host"/>
+ </th>
+ <th align="center" width="25%">
+ <s:text name="heading.user"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.type"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.autoConnect"/>
+ </th>
+ <th align="center" width="15%">
+ <s:text name="heading.action"/>
+ </th>
+ </tr>
+
+ <s:iterator value="user.subscriptions">
+ <tr>
+ <td align="left">
+ <s:property value="host"/>
+ </td>
+ <td align="left">
+ <s:property value="username"/>
+ </td>
+ <td align="center">
+ <s:property value="type"/>
+ </td>
+ <td align="center">
+ <s:property value="autoConnect"/>
+ </td>
+ <td align="center">
+
+ <a href="<s:url action="Subscribe_delete"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.deleteSubscription"/>
+ </a>
+
+ <a href="<s:url action="Subscribe_edit"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.editSubscription"/>
+ </a>
+
+ </td>
+ </tr>
+ </s:iterator>
+
+ </table>
+
+ <a href="<s:url action="Subscribe"/>">
+ <s:text
+ name="registration.addSubscription"/>
+ </a>
+
+</s:if>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Subscribe.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Subscribe.jsp
new file mode 100644
index 0000000..69f8b10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Subscribe.jsp
@@ -0,0 +1,69 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title>
+ <s:text name="subscription.title.create"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title>
+ <s:text name="subscription.title.edit"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title>
+ <s:text name="subscription.title.delete"/>
+ </title>
+ </s:if>
+</head>
+
+<body onLoad="self.focus();document.Subscribe_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Subscribe_save" validate="true">
+ <s:hidden name="task"/>
+ <s:label key="user.username"/>
+
+ <s:if test="task == 'Create'">
+ <s:textfield key="mailHostname" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label key="mailHostname" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label key="mailUsername"
+ name="subscription.username"/>
+ <s:label key="mailPassword"
+ name="subscription.password"/>
+ <s:label key="mailServerType"
+ name="subscription.type"/>
+ <s:label key="autoConnect"
+ name="subscription.autoConnect"/>
+ <s:submit key="button.confirm"/>
+ </s:if>
+ <s:else>
+ <s:textfield key="mailUsername"
+ name="subscription.username"/>
+ <s:textfield key="mailPassword"
+ name="subscription.password"/>
+ <s:select key="mailServerType"
+ name="subscription.type" list="types"/>
+ <s:checkbox key="autoConnect"
+ name="subscription.autoConnect"/>
+ <s:submit key="button.save"/>
+ <s:reset key="button.reset"/>
+ </s:else>
+
+ <s:submit action="Register"
+ key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..4b735bf
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/browse/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,50 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>
+ <s:text name="index.title"/>
+ </title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Register"/>">
+ <s:text
+ name="index.registration"/>
+ </a></li>
+ <li><a href="<s:url action="Login"/>">
+ <s:text
+ name="index.login"/>
+ </a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li>
+ <s:url id="en" action="Welcome">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="ja" action="Welcome">
+ <s:param name="request_locale">ja</s:param>
+ </s:url>
+ <s:a href="%{ja}">Japanese</s:a>
+ </li>
+ <li>
+ <s:url id="ru" action="Welcome">
+ <s:param name="request_locale">ru</s:param>
+ </s:url>
+ <s:a href="%{ru}">Russian</s:a>
+ </li>
+</ul>
+<hr/>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/hello/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/hello/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/hello/hello.iml b/struts-sandbox/mailreader-course/struts2/hello/hello.iml
new file mode 100644
index 0000000..14dad79
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/hello.iml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/hello/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/hello" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/hello" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/hello/src/java/Hello.java
new file mode 100644
index 0000000..73bae87
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing an returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/hello/src/java/resources.properties
new file mode 100644
index 0000000..9faaec7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/java/resources.properties
@@ -0,0 +1,2 @@
+hello.message = Congratulations! Struts is up and running ...
+# Add your messages here ...
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/java/struts.properties b/struts-sandbox/mailreader-course/struts2/hello/src/java/struts.properties
new file mode 100644
index 0000000..75c8136
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/java/struts.properties
@@ -0,0 +1 @@
+struts.custom.i18n.resources=resources
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/hello/src/java/struts.xml
new file mode 100644
index 0000000..2f1421e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/java/struts.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Hello"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <!-- Add your actions here -->
+ </package>
+
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/hello/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/hello/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2f60f95
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/hello/src/webapp/index.html
new file mode 100644
index 0000000..c6d9854
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Hello.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/hello/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/hello/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..1e9d87b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/hello/src/webapp/pages/Hello.jsp
@@ -0,0 +1,12 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/localize/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/localize.iml b/struts-sandbox/mailreader-course/struts2/localize/localize.iml
new file mode 100644
index 0000000..16c7373
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/localize.iml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/localize/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/localize" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/localize" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/localize/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/localize/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/Login-validation.xml b/struts-sandbox/mailreader-course/struts2/localize/src/java/Login-validation.xml
new file mode 100644
index 0000000..4a04c76
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/Login-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/Login.java b/struts-sandbox/mailreader-course/struts2/localize/src/java/Login.java
new file mode 100644
index 0000000..16deb09
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/Login.java
@@ -0,0 +1,22 @@
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Login extends MailReaderSupport {
+
+ public String save() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/Logout.java b/struts-sandbox/mailreader-course/struts2/localize/src/java/Logout.java
new file mode 100644
index 0000000..4f17f10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/Logout.java
@@ -0,0 +1,9 @@
+public class Logout extends MailReaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/localize/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..7f41d53
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/MailReaderSupport.java
@@ -0,0 +1,214 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport
+ implements ApplicationAware, SessionAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String USER_KEY = "user";
+
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ public static final String CANCEL = "cancel";
+
+ // ---- Message Keys ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "error.database.missing";
+
+ public static final String ERROR_USERNAME_UNIQUE =
+ "error.username.unique";
+
+ public static final String ERROR_PASSWORD_MISMATCH =
+ "error.password.mismatch";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText(ERROR_DATABASE_MISSING));
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(USER_KEY, user);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+
+ User user = getDatabase().findUser(username);
+
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+
+ if (user == null) {
+ addFieldError(PASSWORD_MISMATCH_FIELD,
+ getText(ERROR_PASSWORD_MISMATCH));
+ }
+
+ return user;
+
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+ // ---- Alias ----
+
+ public String cancel() {
+ return CANCEL;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/localize/src/java/Register-validation.xml
new file mode 100644
index 0000000..8ce6a3a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/Register-validation.xml
@@ -0,0 +1,55 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="error.fromAddress.format"/>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message key="error.replyToAddress.format"/>
+ </field-validator>
+ </field>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="error.password.mismatch"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.mismatch"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/localize/src/java/Register.java
new file mode 100644
index 0000000..774a852
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/Register.java
@@ -0,0 +1,26 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String save()
+ throws Exception {
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return Action.INPUT;
+ }
+
+ user = createUser(getUsername(), getPassword());
+
+ setUser(user);
+
+ saveUser();
+
+ return Action.SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/localize/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/localize/src/java/resources.properties
new file mode 100644
index 0000000..76dc9cd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/resources.properties
@@ -0,0 +1,105 @@
+hello.message = Congratulations! Struts is up and running ...
+
+index.title=MailReader
+index.login=Log into MailReader
+index.registration=Register with MailReader
+
+registration.title.create=MailReader - Register - Create
+registration.title.edit=MailReader - Register - Edit
+
+username=Username
+password=Password
+password2=(Repeat) Password
+fullName=Full Name
+fromAddress=From Address
+replyToAddress=Reply To Address
+
+button.cancel=Cancel
+button.save=Save
+button.reset=Reset
+
+menu.title=MailReader - Main Menu
+menu.heading=Menu Options for
+menu.registration=Edit your registration profile
+menu.logout=Log out of MailReader
+
+login.title=MailReader - Logon
+
+error.database.missing=User database is missing, cannot validate logon credentials
+error.username.unique=That username is already in use - please select another
+error.password.mismatch=Invalid username and/or password, please try again
+
+error.username.required=Username is required
+error.fullName.required=Full Name is required
+error.fromAddress.required=From Address is required
+error.fromAddress.format=Invalid format for From Address
+error.replyToAddress.format=Invalid format for Reply To Address
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+
+error.host.required=Mail Server is required
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+
+# Future use
+button.confirm=Confirm
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+struts.messages.invalid.token=Cannot submit this form out of order
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/resources_ja.properties b/struts-sandbox/mailreader-course/struts2/localize/src/java/resources_ja.properties
new file mode 100644
index 0000000..5c99bc3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/resources_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.login=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+login.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+menu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+menu.logout=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+menu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+menu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/resources_ru.properties b/struts-sandbox/mailreader-course/struts2/localize/src/java/resources_ru.properties
new file mode 100644
index 0000000..bff1ac3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/resources_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.login=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+login.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+menu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+menu.logout=\u0412\u044b\u0439\u0442\u0438
+menu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/struts.properties b/struts-sandbox/mailreader-course/struts2/localize/src/java/struts.properties
new file mode 100644
index 0000000..75c8136
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/struts.properties
@@ -0,0 +1 @@
+struts.custom.i18n.resources=resources
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/localize/src/java/struts.xml
new file mode 100644
index 0000000..739b56b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/java/struts.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Register_cancel" class="Register" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Menu" class="MailReaderSupport">
+ <result>/pages/Menu.jsp</result>
+ </action>
+
+ <action name="Logout" class="Logout">
+ <result type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login" class="Login" method="input">
+ <result name="input">/pages/Login.jsp</result>
+ </action>
+
+ <action name="Login_save" class="Login" method="save">
+ <result name="input">/pages/Login.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Login_cancel" class="Login" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/localize/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/localize/src/test/RegisterTest.java
new file mode 100644
index 0000000..8586366
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/test/RegisterTest.java
@@ -0,0 +1,35 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setSession(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testSave() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/localize/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..74fbac7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,5 @@
+&welcome-open;
+<clickLink
+ description="Click Register"
+ label="Register with MailReader"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..0b0d582
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration page title"
+ text="${registration.title.create}"/>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-trillian.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-trillian.xml
new file mode 100644
index 0000000..7561f05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/register-trillian.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+<setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/save-click.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/save-click.xml
new file mode 100644
index 0000000..0ba5801
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/save-click.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Save"
+ name="${button.save}"/>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/welcome-open.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/welcome-open.xml
new file mode 100644
index 0000000..bcbbe8b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/entities/welcome-open.xml
@@ -0,0 +1,6 @@
+<invoke
+ description="Open welcome action"
+ url="Welcome.do"/>
+<verifyTitle
+ description="Welcome page title"
+ text="${index.title}"/>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2151ea8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..aa6975a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = lab-2-2
+webapps.home = /opt/Apache/Tomcat-5.5/webapps/
+resource.home = ${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"
+# mailreader.home =
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..3893e88
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+
+ @version $Revision: 1.2 $ $Date: 2005-12-31 15:10:04 -0500 (Sat, 31 Dec 2005) $
+ */
+ -->
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="lab-2-2"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register"/>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Trillian (MSS)">
+ &config;
+ <steps>
+ ®ister-open;
+ ®ister-trillian;
+ <verifyTitle
+ description="Menu page title"
+ text="${menu.title}"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..1e9d87b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Hello.jsp
@@ -0,0 +1,12 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Login.jsp b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Login.jsp
new file mode 100644
index 0000000..97d89a0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Login.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="login.title"/>
+ </title>
+</head>
+
+<body onLoad="self.focus();document.Login_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Login_save" validate="true">
+ <s:textfield key="username"/>
+
+ <s:password key="password" showPassword="true"/>
+
+ <s:submit key="button.save"/>
+
+ <s:submit action="Login_cancel" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Menu.jsp b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Menu.jsp
new file mode 100644
index 0000000..874a6f7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Menu.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="menu.title"/>
+ </title>
+</head>
+
+<body>
+<h3>
+ <s:text name="menu.heading"/>
+ <s:property value="user.fullName"/>
+</h3>
+<ul>
+ <li><a href="<s:url action="Register" />">
+ <s:text name="menu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url action="Logout"/>">
+ <s:text name="menu.logout"/>
+ </a>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..b86aec4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Register.jsp
@@ -0,0 +1,38 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="registration.title.create"/>
+ </title>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save" validate="true">
+
+ <s:textfield key="username"/>
+
+ <s:password key="password"/>
+
+ <s:password key="password2"/>
+
+ <s:textfield key="fullName"/>
+
+ <s:textfield key="fromAddress"/>
+
+ <s:textfield key="replyToAddress"/>
+
+ <s:submit key="button.save"/>
+
+ <s:submit action="Register_cancel" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+
+</s:form>
+
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..ca19d1f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/localize/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,53 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>
+ <s:text name="index.title"/>
+ </title>
+</head>
+
+<body>
+<h3>
+ <s:text name="index.heading"/>
+</h3>
+
+<ul>
+ <li><a href="<s:url action="Register"/>">
+ <s:text
+ name="index.registration"/>
+ </a></li>
+ <li><a href="<s:url action="Login"/>">
+ <s:text
+ name="index.login"/>
+ </a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li>
+ <s:url id="en" action="Welcome">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="ja" action="Welcome">
+ <s:param name="request_locale">ja</s:param>
+ </s:url>
+ <s:a href="%{ja}">Japanese</s:a>
+ </li>
+ <li>
+ <s:url id="ru" action="Welcome">
+ <s:param name="request_locale">ru</s:param>
+ </s:url>
+ <s:a href="%{ru}">Russian</s:a>
+ </li>
+</ul>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/mailreader-course/struts2/logout/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/logout/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/logout.iml b/struts-sandbox/mailreader-course/struts2/logout/logout.iml
new file mode 100644
index 0000000..882fe49
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/logout.iml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/logout/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/logout" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/logout" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/logout/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/logout/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/Login-validation.xml b/struts-sandbox/mailreader-course/struts2/logout/src/java/Login-validation.xml
new file mode 100644
index 0000000..008e825
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/Login-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message>Username is required</message>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message>Password is required</message>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/Login.java b/struts-sandbox/mailreader-course/struts2/logout/src/java/Login.java
new file mode 100644
index 0000000..a55875c
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/Login.java
@@ -0,0 +1,24 @@
+import com.opensymphony.util.BeanUtils;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Login extends MailReaderSupport {
+
+ public String save() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ BeanUtils.setValues(this, user, null);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/Logout.java b/struts-sandbox/mailreader-course/struts2/logout/src/java/Logout.java
new file mode 100644
index 0000000..4f17f10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/Logout.java
@@ -0,0 +1,9 @@
+public class Logout extends MailReaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/logout/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..c743b6f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/MailReaderSupport.java
@@ -0,0 +1,215 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport
+ implements ApplicationAware, SessionAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String USER_KEY = "user";
+
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ public static final String CANCEL = "cancel";
+
+ // ---- Messages ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "Database is missing";
+
+ public static final String ERROR_USERNAME_UNIQUE =
+ "That username is already in use - please select another";
+
+ public static final String ERROR_PASSWORD_MISMATCH =
+ "Invalid username and/or password, please try again";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(ERROR_DATABASE_MISSING);
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(USER_KEY, user);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+
+ User user = getDatabase().findUser(username);
+
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+
+ if (user == null) {
+ addFieldError(PASSWORD_MISMATCH_FIELD,
+ ERROR_PASSWORD_MISMATCH);
+ }
+
+ return user;
+
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ BeanUtils.setValues(getUser(), this, null);
+ getDatabase().save();
+ }
+
+ // ---- Alias ----
+
+ public String cancel() {
+ return CANCEL;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/logout/src/java/Register-validation.xml
new file mode 100644
index 0000000..17055d3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/Register-validation.xml
@@ -0,0 +1,55 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message>Username is required</message>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message>Full Name is required</message>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message>From Address is required</message>
+ </field-validator>
+ <field-validator type="email">
+ <message>Invalid format for From Address</message>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message>Invalid format for Reply To Address</message>
+ </field-validator>
+ </field>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message>Password is required</message>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message>Password length is not in the range 4 through 10.</message>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message>Confirmation password is required</message>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message>Invalid username and/or password, please try again</message>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/logout/src/java/Register.java
new file mode 100644
index 0000000..babb114
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/Register.java
@@ -0,0 +1,25 @@
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String save()
+ throws Exception {
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return INPUT;
+ }
+
+ user = createUser(getUsername(), getPassword());
+
+ setUser(user);
+
+ saveUser();
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/logout/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/logout/src/java/resources.properties
new file mode 100644
index 0000000..9faaec7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/resources.properties
@@ -0,0 +1,2 @@
+hello.message = Congratulations! Struts is up and running ...
+# Add your messages here ...
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/logout/src/java/struts.xml
new file mode 100644
index 0000000..a19f94b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/java/struts.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ </action>
+
+ <action name="Register_cancel" class="Register" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Menu" class="MailReaderSupport">
+ <result>/pages/Menu.jsp</result>
+ </action>
+
+ <action name="Logout" class="Logout">
+ <result type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login" class="Login" method="input">
+ <result name="input">/pages/Login.jsp</result>
+ </action>
+
+ <action name="Login_cancel" class="Login" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login_save" class="Login" method="save">
+ <result name="input">/pages/Login.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/logout/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/logout/src/test/RegisterTest.java
new file mode 100644
index 0000000..8586366
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/test/RegisterTest.java
@@ -0,0 +1,35 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setSession(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testSave() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/logout/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..74fbac7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,5 @@
+&welcome-open;
+<clickLink
+ description="Click Register"
+ label="Register with MailReader"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..54601e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration page title"
+ text="MailReader - Register"/>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-trillian.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-trillian.xml
new file mode 100644
index 0000000..7561f05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/register-trillian.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+<setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/save-click.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/save-click.xml
new file mode 100644
index 0000000..a02a1db
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/save-click.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Save"
+ name="Save"/>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/welcome-open.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/welcome-open.xml
new file mode 100644
index 0000000..a073531
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/entities/welcome-open.xml
@@ -0,0 +1,6 @@
+<invoke
+ description="Open welcome action"
+ url="Welcome.do"/>
+<verifyTitle
+ description="Welcome page title"
+ text="MailReader"/>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2151ea8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..aa6975a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = lab-2-2
+webapps.home = /opt/Apache/Tomcat-5.5/webapps/
+resource.home = ${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"
+# mailreader.home =
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..4f34768
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+ */
+ -->
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="lab-2-2"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register"/>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Trillian (MSS)">
+ &config;
+ <steps>
+ ®ister-open;
+ ®ister-trillian;
+ <verifyTitle
+ description="Menu page title"
+ text="MailReader - Menu"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..c6ce5ac
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Hello.jsp
@@ -0,0 +1,13 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Login.jsp b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Login.jsp
new file mode 100644
index 0000000..856135d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Login.jsp
@@ -0,0 +1,22 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader - Login</title>
+</head>
+
+<body onLoad="self.focus();document.Login_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Login_save" validate="true">
+ <s:textfield label="Username" name="username"/>
+
+ <s:password label="Password" name="password" showPassword="true"/>
+
+ <s:submit value="Save" name="Save"/>
+
+ <s:submit action="Login_cancel" value="Cancel" name="Cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Menu.jsp b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Menu.jsp
new file mode 100644
index 0000000..954f311
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Menu.jsp
@@ -0,0 +1,21 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader - Menu</title>
+</head>
+
+<body>
+<h3>Menu Options for
+ <s:property value="user.fullName"/>
+</h3>
+<ul>
+ <li><a href="<s:url action="Register" />">
+ Edit your registration profile
+ </a>
+ </li>
+ <li><a href="<s:url action="Logout"/>">
+ Log out of MailReader application
+ </a>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..57936f5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Register.jsp
@@ -0,0 +1,33 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader - Register</title>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save" validate="true">
+
+ <s:textfield label="Username" name="username"/>
+
+ <s:password label="Password" name="password"/>
+
+ <s:password label="(Repeat) Password" name="password2"/>
+
+ <s:textfield label="Full Name" name="fullName"/>
+
+ <s:textfield label="From Address" name="fromAddress"/>
+
+ <s:textfield label="Reply To Address" name="replyToAddress"/>
+
+ <s:submit value="Save" name="Save"/>
+
+ <s:submit action="Register_cancel" value="Cancel" name="Cancel"
+ onclick="form.onsubmit=null"/>
+
+</s:form>
+
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..8115f28
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/logout/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,24 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader</title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Register"/>">Register with MailReader</a></li>
+ <li><a href="<s:url action="Login"/>">Log into MailReader</a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li><a href="<s:url action="Missing"/>">English</a></li>
+ <li><a href="<s:url action="Missing"/>">Japanese</a></li>
+ <li><a href="<s:url action="Missing"/>">Russian</a></li>
+</ul>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/mailreader-course/struts2/mailreader-course-struts2.iml b/struts-sandbox/mailreader-course/struts2/mailreader-course-struts2.iml
new file mode 100644
index 0000000..04c05eb
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/mailreader-course-struts2.iml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/classes" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/mailreader-course-struts2.ipr b/struts-sandbox/mailreader-course/struts2/mailreader-course-struts2.ipr
new file mode 100644
index 0000000..dad0368
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/mailreader-course-struts2.ipr
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4" relativePaths="false">
+ <component name="AntConfiguration">
+ <defaultAnt bundledAnt="true" />
+ <buildFile url="file://$PROJECT_DIR$/menu/src/webapp/WEB-INF/webtest.xml">
+ <additionalClassPath />
+ <antReference projectDefault="true" />
+ <customJdkName value="" />
+ <maximumHeapSize value="128" />
+ <properties />
+ </buildFile>
+ </component>
+ <component name="BuildJarProjectSettings">
+ <option name="BUILD_JARS_ON_MAKE" value="false" />
+ </component>
+ <component name="CodeStyleProjectProfileManger">
+ <option name="PROJECT_PROFILE" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ </component>
+ <component name="CodeStyleSettingsManager">
+ <option name="PER_PROJECT_SETTINGS" />
+ <option name="USE_PER_PROJECT_SETTINGS" value="false" />
+ </component>
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <option name="DEPLOY_AFTER_MAKE" value="0" />
+ <resourceExtensions>
+ <entry name=".+\.(properties|xml|html|dtd|tld)" />
+ <entry name=".+\.(gif|png|jpeg|jpg)" />
+ </resourceExtensions>
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ </wildcardResourcePatterns>
+ </component>
+ <component name="DataSourceManagerImpl" />
+ <component name="DependenciesAnalyzeManager">
+ <option name="myForwardDirection" value="false" />
+ </component>
+ <component name="DependencyValidationManager" />
+ <component name="EclipseCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="EclipseEmbeddedCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="EntryPointsManager">
+ <entry_points />
+ </component>
+ <component name="ExportToHTMLSettings">
+ <option name="PRINT_LINE_NUMBERS" value="false" />
+ <option name="OPEN_IN_BROWSER" value="false" />
+ <option name="OUTPUT_DIRECTORY" />
+ </component>
+ <component name="GUI Designer component loader factory" />
+ <component name="IdProvider" IDEtalkID="3FF8EED9FF399F6D50D2620FB9215934" />
+ <component name="InspectionProjectProfileManager">
+ <option name="PROJECT_PROFILE" value="Project Default" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ <scopes />
+ <profiles>
+ <profile version="1.0" is_locked="false">
+ <option name="myName" value="Project Default" />
+ <option name="myLocal" value="false" />
+ <used_levels>
+ <error>
+ <option name="myName" value="ERROR" />
+ <option name="myVal" value="400" />
+ </error>
+ <warning>
+ <option name="myName" value="WARNING" />
+ <option name="myVal" value="300" />
+ </warning>
+ <information>
+ <option name="myName" value="INFO" />
+ <option name="myVal" value="200" />
+ </information>
+ <server>
+ <option name="myName" value="SERVER PROBLEM" />
+ <option name="myVal" value="100" />
+ </server>
+ </used_levels>
+ </profile>
+ </profiles>
+ </component>
+ <component name="JavacSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="DEPRECATION" value="true" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="JavadocGenerationManager">
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="OPTION_SCOPE" value="protected" />
+ <option name="OPTION_HIERARCHY" value="true" />
+ <option name="OPTION_NAVIGATOR" value="true" />
+ <option name="OPTION_INDEX" value="true" />
+ <option name="OPTION_SEPARATE_INDEX" value="true" />
+ <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+ <option name="OPTION_DEPRECATED_LIST" value="true" />
+ <option name="OTHER_OPTIONS" value="" />
+ <option name="HEAP_SIZE" />
+ <option name="LOCALE" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ </component>
+ <component name="JikesSettings">
+ <option name="JIKES_PATH" value="" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="DEPRECATION" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="IS_EMACS_ERRORS_MODE" value="true" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="LogConsolePreferences">
+ <option name="FILTER_ERRORS" value="false" />
+ <option name="FILTER_WARNINGS" value="false" />
+ <option name="FILTER_INFO" value="true" />
+ <option name="CUSTOM_FILTER" />
+ </component>
+ <component name="Palette2">
+ <group name="Swing">
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+ </item>
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+ <initial-values>
+ <property name="text" value="Button" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="RadioButton" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="CheckBox" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="Label" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+ <preferred-size width="-1" height="20" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+ </item>
+ </group>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/browse/browse.iml" filepath="$PROJECT_DIR$/browse/browse.iml" />
+ <module fileurl="file://$PROJECT_DIR$/hello/hello.iml" filepath="$PROJECT_DIR$/hello/hello.iml" />
+ <module fileurl="file://$PROJECT_DIR$/localize/localize.iml" filepath="$PROJECT_DIR$/localize/localize.iml" />
+ <module fileurl="file://$PROJECT_DIR$/logout/logout.iml" filepath="$PROJECT_DIR$/logout/logout.iml" />
+ <module fileurl="file://$PROJECT_DIR$/mailreader-course-struts2.iml" filepath="$PROJECT_DIR$/mailreader-course-struts2.iml" />
+ <module fileurl="file://$PROJECT_DIR$/menu/menu.iml" filepath="$PROJECT_DIR$/menu/menu.iml" />
+ <module fileurl="file://$PROJECT_DIR$/migrating/migrating.iml" filepath="$PROJECT_DIR$/migrating/migrating.iml" />
+ <module fileurl="file://$PROJECT_DIR$/profile/profile.iml" filepath="$PROJECT_DIR$/profile/profile.iml" />
+ <module fileurl="file://$PROJECT_DIR$/register/register.iml" filepath="$PROJECT_DIR$/register/register.iml" />
+ <module fileurl="file://$PROJECT_DIR$/register2/register2.iml" filepath="$PROJECT_DIR$/register2/register2.iml" />
+ <module fileurl="file://$PROJECT_DIR$/retain/retain.iml" filepath="$PROJECT_DIR$/retain/retain.iml" />
+ <module fileurl="file://$PROJECT_DIR$/subscribe/subscribe.iml" filepath="$PROJECT_DIR$/subscribe/subscribe.iml" />
+ <module fileurl="file://$PROJECT_DIR$/theme/theme.iml" filepath="$PROJECT_DIR$/theme/theme.iml" />
+ <module fileurl="file://$PROJECT_DIR$/welcome/welcome.iml" filepath="$PROJECT_DIR$/welcome/welcome.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="false" project-jdk-name="1.5" />
+ <component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="Tomcat 5.5" type="#com.intellij.j2ee.web.tomcat.TomcatRunConfigurationFactory" factoryName="Local" APPLICATION_SERVER_NAME="Tomcat 5">
+ <option name="WORKING_DIRECTORY" />
+ <option name="HOST" value="localhost" />
+ <option name="PORT" value="8080" />
+ <option name="LOCAL" value="true" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ <option name="OPEN_IN_BROWSER_URL" value="http://localhost:8080/subscribe" />
+ <option name="COMMON_VM_ARGUMENTS" value="" />
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="theme" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="hello" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="welcome" />
+ <option name="DEPLOY" value="true" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="profile" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="subscribe" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="retain" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="browse" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="migrating" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="menu" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="register2" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="logout" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="localize" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <J2EE_MODULE DEPLOYMENT_SOURCE_NAME="exploded">
+ <option name="CONTEXT_PATH" value="/" />
+ <option name="MODULE_NAME" value="register" />
+ <option name="DEPLOY" value="false" />
+ </J2EE_MODULE>
+ <option name="DEPLOY_TOMCAT_MANAGER" value="false" />
+ <option name="BASE_DIRECTORY_NAME" value="tomcat_Unnamed_7fefd381" />
+ <predefined_log_file id="TOMCAT_LOCALHOST_LOG_ID" enabled="true" />
+ <RunnerSettings RunnerId="Debug">
+ <option name="DEBUG_PORT" value="3781" />
+ <option name="TRANSPORT" value="0" />
+ <option name="LOCAL" value="true" />
+ </RunnerSettings>
+ <RunnerSettings RunnerId="Run" />
+ <ConfigurationWrapper VM_VAR="JAVA_OPTS" RunnerId="Debug">
+ <option name="USE_ENV_VARIABLES" value="true" />
+ <STARTUP>
+ <option name="USE_DEFAULT" value="true" />
+ <option name="SCRIPT" value="C:\opt\Apache\Tomcat-5.5\bin\catalina.bat" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value=" run" />
+ </STARTUP>
+ <SHUTDOWN>
+ <option name="USE_DEFAULT" value="true" />
+ <option name="SCRIPT" value="C:\opt\Apache\Tomcat-5.5\bin\catalina.bat" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value=" stop" />
+ </SHUTDOWN>
+ </ConfigurationWrapper>
+ <ConfigurationWrapper VM_VAR="JAVA_OPTS" RunnerId="Run">
+ <option name="USE_ENV_VARIABLES" value="true" />
+ <STARTUP>
+ <option name="USE_DEFAULT" value="true" />
+ <option name="SCRIPT" value="C:\opt\Apache\Tomcat-5.5\bin\catalina.bat" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value=" run" />
+ </STARTUP>
+ <SHUTDOWN>
+ <option name="USE_DEFAULT" value="true" />
+ <option name="SCRIPT" value="C:\opt\Apache\Tomcat-5.5\bin\catalina.bat" />
+ <option name="VM_PARAMETERS" value="" />
+ <option name="PROGRAM_PARAMETERS" value=" stop" />
+ </SHUTDOWN>
+ </ConfigurationWrapper>
+ <method>
+ <option name="Make" value="true" />
+ </method>
+ </configuration>
+ </component>
+ <component name="RmicSettings">
+ <option name="IS_EANABLED" value="false" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="GENERATE_IIOP_STUBS" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="StarteamVcsAdapter" />
+ <component name="VssVcs" />
+ <component name="com.intellij.jsf.UserDefinedFacesConfigs">
+ <option name="USER_DEFINED_CONFIGS">
+ <value>
+ <list size="0" />
+ </value>
+ </option>
+ </component>
+ <component name="libraryTable">
+ <library name="Struts2">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/lib/struts-core-1.3.5.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/struts2-api-2.0.3.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/ognl-2.6.9.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-logging-1.0.4.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/xwork-2.0.0.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/struts2-core-2.0.3.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/freemarker-2-3-8.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ <library name="Mailreader-dao">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/lib/sitemesh-2.2.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/struts-mailreader-dao-1.3.5.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/oscore.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-digester-1.6.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-collections-3.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ <library name="Struts1">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/lib/oro-2.0.8.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-collections-3.1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-beanutils-1.6.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/struts-core-1.3.5.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-chain-1.1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-logging-1.0.4.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-digester-1.6.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-validator-1.3.0.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/antlr-2.7.2.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/struts-taglib-1.3.5.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </component>
+ <component name="uidesigner-configuration">
+ <option name="INSTRUMENT_CLASSES" value="true" />
+ <option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" />
+ <option name="DEFAULT_LAYOUT_MANAGER" value="GridLayoutManager" />
+ </component>
+ <UsedPathMacros />
+</project>
+
diff --git a/struts-sandbox/mailreader-course/struts2/menu/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/menu/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/menu.iml b/struts-sandbox/mailreader-course/struts2/menu/menu.iml
new file mode 100644
index 0000000..a60e5d4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/menu.iml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/menu/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/menu" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/menu" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/menu/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/menu/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/menu/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..78efcb7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/MailReaderSupport.java
@@ -0,0 +1,141 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts2.interceptor.ApplicationAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport implements ApplicationAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String USER_KEY = "user";
+
+ // ---- Messages ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "Database is missing";
+
+ public static String ERROR_USERNAME_UNIQUE =
+ "That username is already in use - please select another";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(ERROR_DATABASE_MISSING);
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+ return getDatabase().findUser(username);
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/menu/src/java/Register-validation.xml
new file mode 100644
index 0000000..b29e130
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/Register-validation.xml
@@ -0,0 +1,55 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message>Username is required</message>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message>Full Name is required</message>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message>From Address is required</message>
+ </field-validator>
+ <field-validator type="email">
+ <message>Invalid format for From Address</message>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message>Invalid format for Reply To Address</message>
+ </field-validator>
+ </field>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message>Password is required</message>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message>Password length is not in the range 4 through 10.</message>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message>Confirmation password is required</message>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message>Invalid username and/or password, please try again</message>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/menu/src/java/Register.java
new file mode 100644
index 0000000..c337330
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/Register.java
@@ -0,0 +1,23 @@
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String save()
+ throws Exception {
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return INPUT;
+ }
+
+ createUser(getUsername(), getPassword());
+
+ saveUser();
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/menu/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/menu/src/java/resources.properties
new file mode 100644
index 0000000..9faaec7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/resources.properties
@@ -0,0 +1,2 @@
+hello.message = Congratulations! Struts is up and running ...
+# Add your messages here ...
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/menu/src/java/struts.xml
new file mode 100644
index 0000000..978ac15
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/java/struts.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="chain">Menu</result>
+ </action>
+
+ <action name="Menu" class="MailReaderSupport">
+ <result>/pages/Menu.jsp</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/menu/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/menu/src/test/RegisterTest.java
new file mode 100644
index 0000000..31653b4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/test/RegisterTest.java
@@ -0,0 +1,34 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testSave() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/menu/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..74fbac7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,5 @@
+&welcome-open;
+<clickLink
+ description="Click Register"
+ label="Register with MailReader"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..54601e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration page title"
+ text="MailReader - Register"/>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-trillian.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-trillian.xml
new file mode 100644
index 0000000..7561f05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/register-trillian.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+<setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/save-click.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/save-click.xml
new file mode 100644
index 0000000..a02a1db
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/save-click.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Save"
+ name="Save"/>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/welcome-open.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/welcome-open.xml
new file mode 100644
index 0000000..5eac140
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/entities/welcome-open.xml
@@ -0,0 +1,6 @@
+<invoke
+ description="Open welcome action"
+ url="Welcome.action"/>
+<verifyTitle
+ description="Welcome page title"
+ text="MailReader"/>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2151ea8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest-start.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest-start.xml
new file mode 100644
index 0000000..a881975
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest-start.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir=".">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+ */
+ -->
+
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="menu"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..c0d01c7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = menu
+webapps.home = /opt/Apache/Tomcat-5.5/webapps/
+resource.home = ${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"
+# mailreader.home =
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..4ad0957
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+ */
+ -->
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="menu"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register"/>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Trillian (MSS)">
+ &config;
+ <steps>
+ &welcome-open;
+ ®ister-open;
+ <setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+ <setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+ <setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+ <setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+ <setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
+ <verifyTitle
+ description="Menu page title"
+ text="MailReader - Menu"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..1e9d87b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Hello.jsp
@@ -0,0 +1,12 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Menu.jsp b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Menu.jsp
new file mode 100644
index 0000000..357c6a8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Menu.jsp
@@ -0,0 +1,21 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader - Menu</title>
+</head>
+
+<body>
+<h3>Main Menu Options for
+ <s:property value="fullName"/>
+</h3>
+<ul>
+ <li><a href="<s:url action="Register" />">
+ Edit your registration profile
+ </a>
+ </li>
+ <li><a href="<s:url action="Logout"/>">
+ Log out of MailReader application
+ </a>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..1296d05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Register.jsp
@@ -0,0 +1,30 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader - Register</title>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save" validate="true">
+
+ <s:textfield label="Username" name="username"/>
+
+ <s:password label="Password" name="password"/>
+
+ <s:password label="(Repeat) Password" name="password2"/>
+
+ <s:textfield label="Full Name" name="fullName"/>
+
+ <s:textfield label="From Address" name="fromAddress"/>
+
+ <s:textfield label="Reply To Address" name="replyToAddress"/>
+
+ <s:submit value="Save" name="Save"/>
+
+</s:form>
+
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..c19e61d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/menu/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,24 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader</title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Register"/>">Register with MailReader</a></li>
+ <li><a href="<s:url action="Missing"/>">Log into MailReader</a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li><a href="<s:url action="Missing"/>">English</a></li>
+ <li><a href="<s:url action="Missing"/>">Japanese</a></li>
+ <li><a href="<s:url action="Missing"/>">Russian</a></li>
+</ul>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/migrating/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/migrating.iml b/struts-sandbox/mailreader-course/struts2/migrating/migrating.iml
new file mode 100644
index 0000000..c62c3dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/migrating.iml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/migrating/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/migrating" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$APPLICATION_HOME_DIR$/lib/j2ee.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" name="Struts1" level="project" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/migrating" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="true" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" level="module">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ <url>jar://$APPLICATION_HOME_DIR$/lib/j2ee.jar!/</url>
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts1" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/main/resources" relative="/WEB-INF/classes" />
+ <root url="file://$MODULE_DIR$/src/main/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/main/java" relative="/WEB-INF/classes" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/pom.xml b/struts-sandbox/mailreader-course/struts2/migrating/pom.xml
new file mode 100644
index 0000000..806946e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/pom.xml
@@ -0,0 +1,204 @@
+<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>
+ <groupId>migrating-tutorial</groupId>
+ <artifactId>migrating-tutorial</artifactId>
+ <packaging>war</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <name>Migrating to Apache Struts 2</name>
+ <url>http://www.planetstruts.org/migrating</url>
+ <organization>
+ <name>Struts Mentor</name>
+ <url>http://www.strutsmentor.com</url>
+ </organization>
+ <licenses>
+ <license>
+ <name>Apache License 2.0</name>
+ <url>http://www.apache.org/LICENSE.txt</url>
+ <comments>see http://www.apache.org/LICENSE.txt</comments>
+ </license>
+ </licenses>
+ <build>
+ <resources>
+ <!-- Include resources under src/main/java in WEB-INF/classes -->
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.properties</include>
+ <include>**/*.xml</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/*Test.java</include>
+ </includes>
+ <excludes>
+ <exclude>**/XWorkTestCase.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-javadoc</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-source</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty6-plugin</artifactId>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-j2ee_1.4_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ <defaultGoal>install</defaultGoal>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>opensymphony</groupId>
+ <artifactId>xwork</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-api</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-core</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-extras</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ <version>1.2.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>1.2.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>1.2.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>1.2.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>1.2.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-mock</artifactId>
+ <version>1.2.8</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.3</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts-core</artifactId>
+ <version>1.3.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts-taglib</artifactId>
+ <version>1.3.5</version>
+ </dependency>
+
+ <!--dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts-tiles</artifactId>
+ <version>1.3.5</version>
+ </dependency-->
+
+ <!--dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts-extras</artifactId>
+ <version>1.3.5</version>
+ </dependency-->
+
+ <!--dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts-el</artifactId>
+ <version>1.3.5</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.0.4</version>
+ </dependency>
+ <dependency>
+ <groupId>taglibs</groupId>
+ <artifactId>standard</artifactId>
+ <version>1.0.4</version>
+ </dependency-->
+
+ </dependencies>
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/MessageResources.properties b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/MessageResources.properties
new file mode 100644
index 0000000..62cd51f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/MessageResources.properties
@@ -0,0 +1,30 @@
+# -- standard errors --
+errors.header=<UL>
+errors.prefix=<LI>
+errors.suffix=</LI>
+errors.footer=</UL>
+# -- validator --
+errors.invalid={0} is invalid.
+errors.maxlength={0} can not be greater than {1} characters.
+errors.minlength={0} can not be less than {1} characters.
+errors.range={0} is not in the range {1} through {2}.
+errors.required={0} is required.
+errors.byte={0} must be an byte.
+errors.date={0} is not a date.
+errors.double={0} must be an double.
+errors.float={0} must be an float.
+errors.integer={0} must be an integer.
+errors.long={0} must be an long.
+errors.short={0} must be an short.
+errors.creditcard={0} is not a valid credit card number.
+errors.email={0} is an invalid e-mail address.
+errors.url={0} is not a valid URL.
+# -- other --
+errors.cancel=Operation cancelled.
+errors.detail={0}
+errors.general=The process did not complete. Details should follow.
+errors.token=Request could not be completed. Operation is not in sequence.
+# -- welcome --
+welcome.title=Struts Blank Application
+welcome.heading=Welcome!
+welcome.message=To get started on your own application, copy the struts-blank.war to a new WAR file using the name for your application. Place it in your container's "webapp" folder (or equivalent), and let your container auto-deploy the application. Edit the skeleton configuration files as needed, restart your container, and you are on your way! (You can find the application.properties file with this message in the /WEB-INF/src/java/resources folder.)
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/Hello-validation.xml b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/Hello-validation.xml
new file mode 100644
index 0000000..6998705
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/Hello-validation.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="message">
+ <field-validator type="requiredstring">
+ <message key="requiredstring"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/Hello.java b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/Hello.java
new file mode 100644
index 0000000..06f9bba
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/Hello.java
@@ -0,0 +1,23 @@
+package actions;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class Hello extends ActionSupport {
+
+ /*
+ public String execute() throws Exception {
+ setMessage(getText(MESSAGE));
+ return SUCCESS;
+ }
+ */
+
+ private String message;
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/HelloAction.java b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/HelloAction.java
new file mode 100644
index 0000000..895643b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/HelloAction.java
@@ -0,0 +1,28 @@
+package actions;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class HelloAction extends Action {
+
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ HelloForm input = (HelloForm) form;
+ input.setMessage(getResources(request).getMessage(MESSAGE));
+ return mapping.findForward(SUCCESS);
+ }
+
+ public static final String MESSAGE = "message";
+ public static final String SUCCESS = "success";
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/HelloForm.java b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/HelloForm.java
new file mode 100644
index 0000000..b704b99
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/HelloForm.java
@@ -0,0 +1,16 @@
+package actions;
+
+import org.apache.struts.validator.ValidatorForm;
+
+public class HelloForm extends ValidatorForm {
+
+ private String message;
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/LocaleAction.java b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/LocaleAction.java
new file mode 100644
index 0000000..5379910
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/LocaleAction.java
@@ -0,0 +1,42 @@
+package actions;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Locale;
+
+
+public final class LocaleAction extends Action {
+
+ public ActionForward execute(ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ String language = request.getParameter(LANGUAGE);
+ String country = request.getParameter(COUNTRY);
+
+ Locale locale = getLocale(request);
+
+ if ((language != null && language.length() > 0) &&
+ (country != null && country.length() > 0)) {
+ locale = new java.util.Locale(language, country);
+ } else if (language != null && language.length() > 0) {
+ locale = new java.util.Locale(language, "");
+ }
+
+ setLocale(request, locale);
+
+ return mapping.findForward(SUCCESS);
+ }
+
+ private static final String LANGUAGE = "language";
+ private static final String COUNTRY = "country";
+ private static final String SUCCESS = "success";
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/build.bat b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/build.bat
new file mode 100644
index 0000000..e5a5746
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/actions/build.bat
@@ -0,0 +1,4 @@
+@echo off
+del *.class
+set CLASSPATH=..\..\lib\xwork-2.0.0.jar;..\..\lib\struts-core-1.3.5.jar;%CATALINA_HOME%\common\lib\servlet-api.jar
+javac *.java
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/struts-config.xml b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/struts-config.xml
new file mode 100644
index 0000000..ba57267
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/struts-config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+<struts-config>
+ <form-beans>
+
+ <form-bean name="HelloForm"
+ type="actions.HelloForm">
+ </form-bean>
+
+ </form-beans>
+
+ <action-mappings>
+
+ <action path="/HelloInput"
+ name="HelloForm"
+ forward="/HelloInput.jsp"
+ validate="false"/>
+
+ <action path="/Hello"
+ name="HelloForm"
+ forward="/HelloPage.jsp"
+ validate="true"
+ input="/HelloInput.do"/>
+
+ <action path="/Locale"
+ type="actions.LocaleAction">
+ <forward name="success" path="/HelloInput.do"/>
+ </action>
+
+ </action-mappings>
+
+ <message-resources parameter="resources"/>
+
+ <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
+ <set-property
+ property="pathnames"
+ value="/org/apache/struts/validator/validator-rules.xml,
+ /WEB-INF/classes/validation.xml"/>
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/struts.xml b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/struts.xml
new file mode 100644
index 0000000..77627ad
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/struts.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+ <constant name="struts.custom.i18n.resources" value="resources"/>
+
+ <package name="hello-default" extends="struts-default">
+
+ <action name="Hello_*" method="{1}" class="actions.Hello">
+ <result name="input">/Hello_input.jsp</result>
+ <result>/Hello.jsp</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/validation.xml b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/validation.xml
new file mode 100644
index 0000000..de6f2ca
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/java/validation.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">
+
+<form-validation>
+ <formset>
+ <form name="HelloForm">
+ <field property="message" depends="required">
+ <arg key="message"/>
+ </field>
+ </form>
+ </formset>
+</form-validation>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/actions/build.bat b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/actions/build.bat
new file mode 100644
index 0000000..75b0280
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/actions/build.bat
@@ -0,0 +1,4 @@
+@echo off
+del *.class
+set CLASSPATH=..\..\lib\xwork-2.0-SNAPSHOT.jar;..\..\lib\struts-core-1.3.5.jar;..\..\..\..\..\common\lib\servlet-api.jar
+javac *.java
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/resources.properties b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/resources.properties
new file mode 100644
index 0000000..3c8e15b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/resources.properties
@@ -0,0 +1,7 @@
+message = Message
+prompt = Enter Message
+# Struts 1
+errors.required={0} is required.
+# Struts 2
+requiredstring = ${getText(fieldName)} is required.
+
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/resources_es.properties b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/resources_es.properties
new file mode 100644
index 0000000..0accea6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/resources_es.properties
@@ -0,0 +1,6 @@
+prompt = Entre el mensaje
+message = Mensaje
+# Struts 1
+errors.required={0} se requiere.
+# Struts 2
+requiredstring = ${getText(fieldName)} se requiere.
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/struts.properties b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/struts.properties
new file mode 100644
index 0000000..75c8136
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/resources/struts.properties
@@ -0,0 +1 @@
+struts.custom.i18n.resources=resources
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/Hello.jsp b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/Hello.jsp
new file mode 100644
index 0000000..0ffbf95
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/Hello.jsp
@@ -0,0 +1,39 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>
+ <s:text name="message"/>
+ </title>
+</head>
+
+<body>
+<h2>
+ <s:property value="message"/>
+</h2>
+
+<ul>
+ <li>
+ <s:url id="url" action="Hello_input"/>
+ <s:a href="%{url}">
+ <s:property value="prompt"/>
+ </s:a>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <s:url id="en" action="Hello_input">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="es" action="Hello_input">
+ <s:param name="request_locale">es</s:param>
+ </s:url>
+ <s:a href="%{es}">Español</s:a>
+ </li>
+</ul>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/HelloInput.jsp b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/HelloInput.jsp
new file mode 100644
index 0000000..b00fcae
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/HelloInput.jsp
@@ -0,0 +1,31 @@
+<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
+<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
+<html>
+<head>
+ <title>
+ <bean:message key="prompt"/>
+ </title>
+</head>
+
+<body>
+<h2>
+ <bean:message key="prompt"/>
+</h2>
+<html:errors/>
+<html:form action="/Hello">
+ <table>
+ <tr>
+ <td>
+ <bean:message key="message"/>
+ </td>
+ <td>
+ <html:text property="message"/>
+ </td>
+ </tr>
+ <td colspan="2">
+ <html:submit/>
+ </td>
+ </table>
+</html:form>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/HelloPage.jsp b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/HelloPage.jsp
new file mode 100644
index 0000000..1ac0bd3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/HelloPage.jsp
@@ -0,0 +1,34 @@
+<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean" %>
+<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html" %>
+<html>
+<head>
+ <title>
+ <bean:message key="message"/>
+ </title>
+</head>
+
+<body>
+<h2>
+ <bean:write name="HelloForm" property="message"/>
+</h2>
+
+<ul>
+ <li>
+ <html:link action="/HelloInput">
+ <bean:message key="prompt"/>
+ </html:link>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <html:link action="/Locale?language=en">English</html:link>
+ </li>
+ <li>
+ <html:link action="/Locale?language=es">Español</html:link>
+ </li>
+
+</ul>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/Hello_input.jsp b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/Hello_input.jsp
new file mode 100644
index 0000000..3d352be
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/Hello_input.jsp
@@ -0,0 +1,21 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>
+ <s:text name="prompt"/>
+ </title>
+</head>
+
+<body>
+<h2>
+ <s:text name="prompt"/>
+</h2>
+
+<p>
+ <s:form action="Hello">
+ <s:textfield key="message"/>
+ <s:submit/>
+ </s:form>
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/struts-config.xml b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/struts-config.xml
new file mode 100644
index 0000000..195c88d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/struts-config.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
+ "http://struts.apache.org/dtds/struts-config_1_3.dtd">
+
+<struts-config>
+ <message-resources parameter="MessageResources"/>
+ <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
+ <set-property property="pathnames"
+ value="/org/apache/struts/validator/validator-rules.xml,/WEB-INF/validation.xml"/>
+ </plug-in>
+</struts-config>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/validation.xml b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/validation.xml
new file mode 100644
index 0000000..6a24e97
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/validation.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE form-validation PUBLIC
+ "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
+ "http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">
+
+
+<form-validation>
+</form-validation>
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..6a597d5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <!-- Struts 2 -->
+ <filter>
+ <filter-name>struts2</filter-name>
+ <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Struts 1 -->
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
+ <init-param>
+ <param-name>config</param-name>
+ <param-value>/WEB-INF/classes/struts-config.xml</param-value>
+ </init-param>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>action</servlet-name>
+ <url-pattern>*.do</url-pattern>
+ </servlet-mapping>
+
+ <!-- Either version -->
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+</web-app>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/index.html b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/index.html
new file mode 100644
index 0000000..97f6d92
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/migrating/src/main/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Hello_input.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/profile/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/profile.iml b/struts-sandbox/mailreader-course/struts2/profile/profile.iml
new file mode 100644
index 0000000..1bded33
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/profile.iml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/profile/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/profile" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/profile" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/profile/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/profile/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/Login-validation.xml b/struts-sandbox/mailreader-course/struts2/profile/src/java/Login-validation.xml
new file mode 100644
index 0000000..ed9359f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/Login-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/Login.java b/struts-sandbox/mailreader-course/struts2/profile/src/java/Login.java
new file mode 100644
index 0000000..16deb09
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/Login.java
@@ -0,0 +1,22 @@
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Login extends MailReaderSupport {
+
+ public String save() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/Logout.java b/struts-sandbox/mailreader-course/struts2/profile/src/java/Logout.java
new file mode 100644
index 0000000..4f17f10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/Logout.java
@@ -0,0 +1,9 @@
+public class Logout extends MailReaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/profile/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..fc99f88
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/MailReaderSupport.java
@@ -0,0 +1,233 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport
+ implements ApplicationAware, SessionAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Task property (utilized by UI) ----
+
+ private String task = null;
+
+ public String getTask() {
+ return task;
+ }
+
+ public void setTask(String value) {
+ task = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String USER_KEY = "user";
+
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ public static final String CANCEL = "cancel";
+
+ public static final String CREATE = "Create";
+
+ public static final String EDIT = "Edit";
+
+ // ---- Message Keys ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "error.database.missing";
+
+ public static final String ERROR_USERNAME_UNIQUE =
+ "error.username.unique";
+
+ public static final String ERROR_PASSWORD_MISMATCH =
+ "error.password.mismatch";
+
+ public static final String ERROR_PASSWORD_MATCH =
+ "error.password.match";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText(ERROR_DATABASE_MISSING));
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(USER_KEY, user);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+
+ User user = getDatabase().findUser(username);
+
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+
+ if (user == null) {
+ addFieldError(PASSWORD_MISMATCH_FIELD,
+ getText(ERROR_PASSWORD_MISMATCH));
+ }
+
+ return user;
+
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+ // ---- Alias ----
+
+ public String cancel() {
+ return CANCEL;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/profile/src/java/Register-validation.xml
new file mode 100644
index 0000000..f8155f6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/Register-validation.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/profile/src/java/Register.java
new file mode 100644
index 0000000..b2a9749
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/Register.java
@@ -0,0 +1,65 @@
+import com.opensymphony.util.BeanUtils;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String input() throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ setTask(EDIT);
+ BeanUtils.setValues(this, user, null);
+ setPassword(null);
+ } else {
+ setTask(CREATE);
+ }
+
+ return INPUT;
+ }
+
+ public String save()
+ throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ // FIXME: Any way to call the RegisterCreate validators from here?
+ String newPassword = getPassword();
+ boolean changing = ((null != newPassword) && (newPassword.length() > 0));
+ if (!changing) {
+ setPassword(user.getPassword());
+ } else {
+ String confirmPassword = getPassword2();
+ boolean matches = ((null != confirmPassword)
+ && (confirmPassword.equals(newPassword)));
+ if (matches) {
+ user.setPassword(newPassword);
+ } else {
+ addActionError(getText(ERROR_PASSWORD_MATCH));
+ return INPUT;
+ }
+ }
+ BeanUtils.setValues(user, this, null);
+ }
+
+ if (!editing) {
+ user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return INPUT;
+ }
+
+ user = createUser(getUsername(), getPassword());
+ setUser(user);
+ }
+
+ saveUser();
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/RegisterCreate-validation.xml b/struts-sandbox/mailreader-course/struts2/profile/src/java/RegisterCreate-validation.xml
new file mode 100644
index 0000000..6896407
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/RegisterCreate-validation.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="errors.range"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.match"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/RegisterCreate.java b/struts-sandbox/mailreader-course/struts2/profile/src/java/RegisterCreate.java
new file mode 100644
index 0000000..4895652
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/RegisterCreate.java
@@ -0,0 +1,5 @@
+/**
+ * <p>Stub class to allow extra validation on initial Save.</p>
+ */
+public class RegisterCreate extends Register {
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/profile/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/profile/src/java/resources.properties
new file mode 100644
index 0000000..474ec93
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/resources.properties
@@ -0,0 +1,105 @@
+hello.message = Congratulations! Struts is up and running ...
+
+index.title=MailReader
+index.login=Log into MailReader
+index.registration=Register with MailReader
+
+registration.title.create=MailReader - Register - Create
+registration.title.edit=MailReader - Register - Edit
+
+username=Username
+password=Password
+password2=(Repeat) Password
+fullName=Full Name
+fromAddress=From Address
+replyToAddress=Reply To Address
+
+button.cancel=Cancel
+button.save=Save
+
+menu.title=MailReader - Main Menu
+menu.heading=Menu Options for
+menu.registration=Edit your registration profile
+menu.logout=Log out of MailReader
+
+login.title=MailReader - Logon
+
+error.database.missing=User database is missing, cannot validate logon credentials
+error.username.unique=That username is already in use - please select another
+error.password.mismatch=Invalid username and/or password, please try again
+
+error.username.required=Username is required
+error.fullName.required=Full Name is required
+error.fromAddress.required=From Address is required
+error.fromAddress.format=Invalid format for From Address
+error.replyToAddress.format=Invalid format for Reply To Address
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+
+error.host.required=Mail Server is required
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+
+# Future use
+button.confirm=Confirm
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+button.reset=Reset
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+struts.messages.invalid.token=Cannot submit this form out of order
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/resources_ja.properties b/struts-sandbox/mailreader-course/struts2/profile/src/java/resources_ja.properties
new file mode 100644
index 0000000..60eb6d2
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/resources_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.login=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+login.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+menu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+menu.logout=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+menu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+menu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/resources_ru.properties b/struts-sandbox/mailreader-course/struts2/profile/src/java/resources_ru.properties
new file mode 100644
index 0000000..bff1ac3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/resources_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.login=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+login.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+menu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+menu.logout=\u0412\u044b\u0439\u0442\u0438
+menu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/struts.properties b/struts-sandbox/mailreader-course/struts2/profile/src/java/struts.properties
new file mode 100644
index 0000000..75c8136
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/struts.properties
@@ -0,0 +1 @@
+struts.custom.i18n.resources=resources
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/profile/src/java/struts.xml
new file mode 100644
index 0000000..39ec015
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/java/struts.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ </action>
+
+ <action name="Register_cancel" class="Register" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Register_create" class="RegisterCreate" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Menu" class="MailReaderSupport">
+ <result>/pages/Menu.jsp</result>
+ </action>
+
+ <action name="Logout" class="Logout">
+ <result type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login" class="Login" method="input">
+ <result name="input">/pages/Login.jsp</result>
+ </action>
+
+ <action name="Login_cancel" class="Login" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login_save" class="Login" method="save">
+ <result name="input">/pages/Login.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/profile/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/profile/src/test/RegisterTest.java
new file mode 100644
index 0000000..1f5aa28
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/test/RegisterTest.java
@@ -0,0 +1,35 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setSession(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testExecute() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/profile/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..74fbac7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,5 @@
+&welcome-open;
+<clickLink
+ description="Click Register"
+ label="Register with MailReader"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..54601e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration page title"
+ text="MailReader - Register"/>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-trillian.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-trillian.xml
new file mode 100644
index 0000000..7561f05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/register-trillian.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+<setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/save-click.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/save-click.xml
new file mode 100644
index 0000000..a02a1db
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/save-click.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Save"
+ name="Save"/>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/welcome-open.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/welcome-open.xml
new file mode 100644
index 0000000..a073531
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/entities/welcome-open.xml
@@ -0,0 +1,6 @@
+<invoke
+ description="Open welcome action"
+ url="Welcome.do"/>
+<verifyTitle
+ description="Welcome page title"
+ text="MailReader"/>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2151ea8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..aa6975a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = lab-2-2
+webapps.home = /opt/Apache/Tomcat-5.5/webapps/
+resource.home = ${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"
+# mailreader.home =
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..4f34768
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+ */
+ -->
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="lab-2-2"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register"/>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Trillian (MSS)">
+ &config;
+ <steps>
+ ®ister-open;
+ ®ister-trillian;
+ <verifyTitle
+ description="Menu page title"
+ text="MailReader - Menu"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..51e788d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Hello.jsp
@@ -0,0 +1,14 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Login.jsp b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Login.jsp
new file mode 100644
index 0000000..c7036ce
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Login.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="login.title"/>
+ </title>
+</head>
+
+<body onLoad="self.focus();document.Login_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Login_save" validate="true">
+ <s:textfield key="username"/>
+
+ <s:password key="password" showPassword="true"/>
+
+ <s:submit key="Save"/>
+
+ <s:submit action="Login_cancel" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Menu.jsp b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Menu.jsp
new file mode 100644
index 0000000..874a6f7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Menu.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="menu.title"/>
+ </title>
+</head>
+
+<body>
+<h3>
+ <s:text name="menu.heading"/>
+ <s:property value="user.fullName"/>
+</h3>
+<ul>
+ <li><a href="<s:url action="Register" />">
+ <s:text name="menu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url action="Logout"/>">
+ <s:text name="menu.logout"/>
+ </a>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..e2647b0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Register.jsp
@@ -0,0 +1,62 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title>
+ <s:text name="registration.title.create"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title>
+ <s:text name="registration.title.edit"/>
+ </title>
+ </s:if>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save" validate="true">
+ <s:hidden name="task"/>
+ <s:if test="task == 'Create'">
+ <s:textfield key="username"/>
+ </s:if>
+ <s:else>
+ <s:label key="username"/>
+ <s:hidden name="username"/>
+ </s:else>
+
+ <s:password key="password"/>
+
+ <s:password key="password2"/>
+
+ <s:textfield key="fullName"/>
+
+ <s:textfield key="fromAddress"/>
+
+ <s:textfield key="replyToAddress"/>
+
+ <s:if test="task == 'Create'">
+ <s:submit key="button.save" action="Register_create"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Welcome" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:if>
+ <s:else>
+ <s:submit key="button.save"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Menu" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:else>
+
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..bc3e546
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/profile/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,51 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>
+ <s:text name="index.title"/>
+ </title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Register"/>">
+ <s:text
+ name="index.registration"/>
+ </a></li>
+ <li><a href="<s:url action="Login"/>">
+ <s:text
+ name="index.login"/>
+ </a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li>
+ <s:url id="en" action="Welcome">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="ja" action="Welcome">
+ <s:param name="request_locale">ja</s:param>
+ </s:url>
+ <s:a href="%{ja}">Japanese</s:a>
+ </li>
+ <li>
+ <s:url id="ru" action="Welcome">
+ <s:param name="request_locale">ru</s:param>
+ </s:url>
+ <s:a href="%{ru}">Russian</s:a>
+ </li>
+</ul>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/mailreader-course/struts2/register/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/register/META-INF/context.xml
new file mode 100644
index 0000000..eb6ca34
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/register/register.iml b/struts-sandbox/mailreader-course/struts2/register/register.iml
new file mode 100644
index 0000000..07f080a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/register.iml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/register/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/register" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/register" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/register/src/java/DatabaseListener.java
new file mode 100644
index 0000000..7c829ae
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/register/src/java/Hello.java
new file mode 100644
index 0000000..d0a139e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/register/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..70b6d90
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/java/MailReaderSupport.java
@@ -0,0 +1,141 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts2.interceptor.ApplicationAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport implements ApplicationAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String USER_KEY = "user";
+
+ // ---- Messages ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "Database is missing";
+
+ public static String ERROR_USERNAME_UNIQUE =
+ "That username is already in use - please select another";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(ERROR_DATABASE_MISSING);
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+ return getDatabase().findUser(username);
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/register/src/java/Register.java
new file mode 100644
index 0000000..9b784d7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/java/Register.java
@@ -0,0 +1,23 @@
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String save()
+ throws Exception {
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return INPUT;
+ }
+
+ createUser(getUsername(), getPassword());
+
+ saveUser();
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/register/src/java/database.xml
new file mode 100644
index 0000000..5710477
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/register/src/java/resources.properties
new file mode 100644
index 0000000..8577b17
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/java/resources.properties
@@ -0,0 +1,2 @@
+hello.message = Congratulations! Struts is up and running ...
+# Add your messages here ...
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/register/src/java/struts.xml
new file mode 100644
index 0000000..6b1ce04
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/java/struts.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/register/src/test/HelloTest.java
new file mode 100644
index 0000000..695f0b8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/register/src/test/RegisterTest.java
new file mode 100644
index 0000000..d6902bb
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/test/RegisterTest.java
@@ -0,0 +1,34 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testSave() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/register/src/test/RetainTest.java
new file mode 100644
index 0000000..508e924
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/register/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7709df9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/register/src/webapp/index.html
new file mode 100644
index 0000000..9d05a91
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..db0fd87
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Hello.jsp
@@ -0,0 +1,12 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..3690d0d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..bd5082c
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Register.jsp
@@ -0,0 +1,28 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader - Register</title>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save">
+
+ <s:textfield label="Username" name="username"/>
+
+ <s:password label="Password" name="password"/>
+
+ <s:password label="(Repeat) Password" name="password2"/>
+
+ <s:textfield label="Full Name" name="fullName"/>
+
+ <s:textfield label="From Address" name="fromAddress"/>
+
+ <s:textfield label="Reply To Address" name="replyToAddress"/>
+
+ <s:submit value="Save" name="Save"/>
+
+</s:form>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..2560ff7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,23 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader</title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Register"/>">Register with the MailReader</a></li>
+ <li><a href="<s:url action="Missing"/>">Log on to the MailReader</a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li><a href="<s:url action="Missing"/>">English</a></li>
+ <li><a href="<s:url action="Missing"/>">Japanese</a></li>
+ <li><a href="<s:url action="Missing"/>">Russian</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/register2/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/register2.iml b/struts-sandbox/mailreader-course/struts2/register2/register2.iml
new file mode 100644
index 0000000..25ef39f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/register2.iml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/register2/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/register2" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/register2" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/register2/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/register2/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/register2/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..78efcb7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/MailReaderSupport.java
@@ -0,0 +1,141 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts2.interceptor.ApplicationAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport implements ApplicationAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String USER_KEY = "user";
+
+ // ---- Messages ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "Database is missing";
+
+ public static String ERROR_USERNAME_UNIQUE =
+ "That username is already in use - please select another";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(ERROR_DATABASE_MISSING);
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+ return getDatabase().findUser(username);
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/register2/src/java/Register-validation.xml
new file mode 100644
index 0000000..17055d3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/Register-validation.xml
@@ -0,0 +1,55 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message>Username is required</message>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message>Full Name is required</message>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message>From Address is required</message>
+ </field-validator>
+ <field-validator type="email">
+ <message>Invalid format for From Address</message>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message>Invalid format for Reply To Address</message>
+ </field-validator>
+ </field>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message>Password is required</message>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message>Password length is not in the range 4 through 10.</message>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message>Confirmation password is required</message>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message>Invalid username and/or password, please try again</message>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/register2/src/java/Register.java
new file mode 100644
index 0000000..c337330
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/Register.java
@@ -0,0 +1,23 @@
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String save()
+ throws Exception {
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(ERROR_USERNAME_UNIQUE);
+ return INPUT;
+ }
+
+ createUser(getUsername(), getPassword());
+
+ saveUser();
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/register2/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/register2/src/java/resources.properties
new file mode 100644
index 0000000..9faaec7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/resources.properties
@@ -0,0 +1,2 @@
+hello.message = Congratulations! Struts is up and running ...
+# Add your messages here ...
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/register2/src/java/struts.xml
new file mode 100644
index 0000000..89d3ffe
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/java/struts.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/register2/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/register2/src/test/RegisterTest.java
new file mode 100644
index 0000000..31653b4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/test/RegisterTest.java
@@ -0,0 +1,34 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testSave() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/register2/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2151ea8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..1e9d87b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Hello.jsp
@@ -0,0 +1,12 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..18194e8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Register.jsp
@@ -0,0 +1,27 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader - Register</title>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+<s:actionerror/>
+<s:form action="Register_save">
+
+ <s:textfield label="Username" name="username"/>
+
+ <s:password label="Password" name="password"/>
+
+ <s:password label="(Repeat) Password" name="password2"/>
+
+ <s:textfield label="Full Name" name="fullName"/>
+
+ <s:textfield label="From Address" name="fromAddress"/>
+
+ <s:textfield label="Reply To Address" name="replyToAddress"/>
+
+ <s:submit value="Save" name="Save"/>
+
+</s:form>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..b9d8086
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/register2/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,22 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader</title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+<ul>
+ <li><a href="<s:url action="Register"/>">Register with the MailReader</a></li>
+ <li><a href="<s:url action="Missing"/>">Log on to the MailReader</a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li><a href="<s:url action="Missing"/>">English</a></li>
+ <li><a href="<s:url action="Missing"/>">Japanese</a></li>
+ <li><a href="<s:url action="Missing"/>">Russian</a></li>
+</ul>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/retain/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/retain/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/retain/retain.iml b/struts-sandbox/mailreader-course/struts2/retain/retain.iml
new file mode 100644
index 0000000..03b98fd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/retain.iml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/retain/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/retain" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/retain" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/retain/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/retain/src/java/resources.properties
new file mode 100644
index 0000000..9faaec7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/java/resources.properties
@@ -0,0 +1,2 @@
+hello.message = Congratulations! Struts is up and running ...
+# Add your messages here ...
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/retain/src/java/struts.xml
new file mode 100644
index 0000000..596b0f2
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/java/struts.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/retain/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/retain/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2f60f95
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..1e9d87b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Hello.jsp
@@ -0,0 +1,12 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..4e3768e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/retain/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,24 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader</title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Missing"/>">Register with MailReader</a></li>
+ <li><a href="<s:url action="Missing"/>">Log into MailReader</a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li><a href="<s:url action="Missing"/>">English</a></li>
+ <li><a href="<s:url action="Missing"/>">Japanese</a></li>
+ <li><a href="<s:url action="Missing"/>">Russian</a></li>
+</ul>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/subscribe/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Login-save-validation.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Login-save-validation.xml
new file mode 100644
index 0000000..ed9359f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Login-save-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Login.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Login.java
new file mode 100644
index 0000000..16deb09
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Login.java
@@ -0,0 +1,22 @@
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Login extends MailReaderSupport {
+
+ public String save() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Logout.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Logout.java
new file mode 100644
index 0000000..4f17f10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Logout.java
@@ -0,0 +1,9 @@
+public class Logout extends MailReaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..4fa163b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/MailReaderSupport.java
@@ -0,0 +1,325 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport
+ implements ApplicationAware, SessionAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Subscription form properties ----
+
+ private String host;
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String value) {
+ host = value;
+ }
+
+ // ---- Task property (utilized by UI) ----
+
+ private String task = null;
+
+ public String getTask() {
+ return task;
+ }
+
+ public void setTask(String value) {
+ task = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ public static final String USER_KEY = "user";
+
+ public static final String HOST = "host";
+
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ public static final String CANCEL = "cancel";
+
+ public static final String CREATE = "Create";
+
+ public static final String EDIT = "Edit";
+
+ public static final String DELETE = "Delete";
+
+ // ---- Message Keys ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "error.database.missing";
+
+ public static final String ERROR_USERNAME_UNIQUE =
+ "error.username.unique";
+
+ public static final String ERROR_PASSWORD_MISMATCH =
+ "error.password.mismatch";
+
+ public static final String ERROR_PASSWORD_MATCH =
+ "error.password.match";
+
+ public static final String ERROR_HOST_UNIQUE
+ = "That hostname is already defined";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText(ERROR_DATABASE_MISSING));
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- Subscription property ----
+
+ public Subscription getSubscription() {
+ return (Subscription) getSession().get(SUBSCRIPTION_KEY);
+ }
+
+ public void setSubscription(Subscription subscription) {
+ getSession().put(SUBSCRIPTION_KEY, subscription);
+ }
+
+
+ public String getSubscriptionHost() {
+ Subscription sub = getSubscription();
+ if (null == sub) {
+ return null;
+ }
+ return sub.getHost();
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(USER_KEY, user);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+
+ User user = getDatabase().findUser(username);
+
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+
+ if (user == null) {
+ addFieldError(PASSWORD_MISMATCH_FIELD,
+ getText(ERROR_PASSWORD_MISMATCH));
+ }
+
+ return user;
+
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+ /**
+ * <p>Provide a "temporary" User Subscription object
+ * that can be used tocapture input values.</p>
+ */
+ public void createInputSubscription() {
+ Subscription sub = new MemorySubscription(getUser(), null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = getUser().findSubscription(host);
+ return subscription;
+ }
+
+ public Subscription findSubscription() {
+ return findSubscription(getHost());
+ }
+
+ public void removeSubscription() {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(SUBSCRIPTION_KEY);
+ }
+
+ public void copySubscription(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ BeanUtils.setValues(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }
+
+ public Subscription createSubscription(String host) {
+
+ Subscription sub;
+
+ sub = findSubscription(host);
+
+ if (null != sub) {
+ // FIXME - localization - "error.host.unique")
+ addFieldError(HOST, ERROR_HOST_UNIQUE);
+ return null;
+ }
+
+ return getUser().createSubscription(host);
+ }
+
+ // ---- Alias ----
+
+ public String cancel() {
+ return CANCEL;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Register-validation.xml
new file mode 100644
index 0000000..f8155f6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Register-validation.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Register.java
new file mode 100644
index 0000000..78f2bde
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Register.java
@@ -0,0 +1,65 @@
+import com.opensymphony.util.BeanUtils;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String input() throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ setTask(EDIT);
+ BeanUtils.setValues(this, user, null);
+ setPassword(null);
+ } else {
+ setTask(CREATE);
+ }
+
+ return INPUT;
+ }
+
+ public String save()
+ throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ // FIXME: Any way to call the RegisterSave validators from here?
+ String newPassword = getPassword();
+ boolean changing = ((null != newPassword) && (newPassword.length() > 0));
+ if (!changing) {
+ setPassword(user.getPassword());
+ } else {
+ String confirmPassword = getPassword2();
+ boolean matches = ((null != confirmPassword)
+ && (confirmPassword.equals(newPassword)));
+ if (matches) {
+ user.setPassword(newPassword);
+ } else {
+ addActionError(getText(ERROR_PASSWORD_MATCH));
+ return INPUT;
+ }
+ }
+ BeanUtils.setValues(user, this, null);
+ }
+
+ if (!editing) {
+ user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return INPUT;
+ }
+
+ user = createUser(getUsername(), getPassword());
+ setUser(user);
+ }
+
+ saveUser();
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/RegisterCreate-validation.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/RegisterCreate-validation.xml
new file mode 100644
index 0000000..6896407
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/RegisterCreate-validation.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="errors.range"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.match"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/RegisterCreate.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/RegisterCreate.java
new file mode 100644
index 0000000..4895652
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/RegisterCreate.java
@@ -0,0 +1,5 @@
+/**
+ * <p>Stub class to allow extra validation on initial Save.</p>
+ */
+public class RegisterCreate extends Register {
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe-Subscribe_save-validation.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe-Subscribe_save-validation.xml
new file mode 100644
index 0000000..9f2f6d7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe-Subscribe_save-validation.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="subscription.username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.type">
+ <field-validator type="requiredstring">
+ <message key="error.type.invalid"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe-validation.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe-validation.xml
new file mode 100644
index 0000000..bc422c8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe-validation.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="host">
+ <field-validator type="requiredstring">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe.java
new file mode 100644
index 0000000..40c6e1b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/Subscribe.java
@@ -0,0 +1,74 @@
+import com.opensymphony.xwork2.Preparable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class Subscribe extends MailReaderSupport
+ implements Preparable {
+
+ private Map types = null;
+
+ public Map getTypes() {
+ return types;
+ }
+
+ public void prepare() {
+
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+
+ setHost(getSubscriptionHost());
+ }
+
+ public String input() {
+ createInputSubscription();
+ setTask(CREATE);
+ return INPUT;
+ }
+
+ protected String find() {
+
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+
+ if (sub == null) {
+ return ERROR;
+ }
+
+ setSubscription(sub);
+
+ return SUCCESS;
+
+ }
+
+ public String delete() {
+
+ setTask(DELETE);
+ return find();
+ }
+
+ public String edit() {
+
+ setTask(EDIT);
+ return find();
+ }
+
+ public String save() throws Exception {
+
+ if (DELETE.equals(getTask())) {
+ removeSubscription();
+ }
+
+ if (CREATE.equals(getTask())) {
+ copySubscription(getHost());
+ }
+
+ if (hasErrors()) return INPUT;
+
+ saveUser();
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources.properties
new file mode 100644
index 0000000..7fc1152
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources.properties
@@ -0,0 +1,105 @@
+hello.message = Congratulations! Struts is up and running ...
+
+index.title=MailReader
+index.login=Log into MailReader
+index.registration=Register with MailReader
+
+registration.title.create=MailReader - Register - Create
+registration.title.edit=MailReader - Register - Edit
+
+username=Username
+password=Password
+password2=(Repeat) Password
+fullName=Full Name
+fromAddress=From Address
+replyToAddress=Reply To Address
+
+button.cancel=Cancel
+button.save=Save
+button.reset=Reset
+button.confirm=Confirm
+
+menu.title=MailReader - Main Menu
+menu.heading=Menu Options for
+menu.registration=Edit your registration profile
+menu.logout=Log out of MailReader
+
+login.title=MailReader - Logon
+
+error.database.missing=User database is missing, cannot validate logon credentials
+error.username.unique=That username is already in use - please select another
+error.password.mismatch=Invalid username and/or password, please try again
+
+error.username.required=Username is required
+error.fullName.required=Full Name is required
+error.fromAddress.required=From Address is required
+error.fromAddress.format=Invalid format for From Address
+error.replyToAddress.format=Invalid format for Reply To Address
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+
+error.host.required=Mail Server is required
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+
+# Future use
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+struts.messages.invalid.token=Cannot submit this form out of order
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources_ja.properties b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources_ja.properties
new file mode 100644
index 0000000..60eb6d2
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.login=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+login.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+menu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+menu.logout=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+menu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+menu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources_ru.properties b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources_ru.properties
new file mode 100644
index 0000000..bff1ac3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/resources_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.login=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+login.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+menu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+menu.logout=\u0412\u044b\u0439\u0442\u0438
+menu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/struts.properties b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/struts.properties
new file mode 100644
index 0000000..75c8136
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/struts.properties
@@ -0,0 +1 @@
+struts.custom.i18n.resources=resources
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/struts.xml
new file mode 100644
index 0000000..841ced0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/java/struts.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <action name="Register" class="Register" method="input">
+ <result name="input">/pages/Register.jsp</result>
+ </action>
+
+ <action name="Register_cancel" class="Register" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Register_create" class="RegisterCreate" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Register_save" class="Register" method="save">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Menu" class="MailReaderSupport">
+ <result>/pages/Menu.jsp</result>
+ </action>
+
+ <action name="Logout" class="Logout">
+ <result type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login" class="Login" method="input">
+ <result name="input">/pages/Login.jsp</result>
+ </action>
+
+ <action name="Login_cancel" class="Login" method="cancel">
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login_save" class="Login" method="save">
+ <result name="input">/pages/Login.jsp</result>
+ <result type="redirect-action">Menu</result>
+ </action>
+
+ <action name="Subscribe" class="Subscribe" method="input">
+ <result name="input">/pages/Subscribe.jsp</result>
+ <result type="redirect-action">Register</result>
+ </action>
+
+ <action name="Subscribe_delete" class="Subscribe" method="delete">
+ <result name="input" type="redirect-action">Login</result>
+ <result>/pages/Subscribe.jsp</result>
+ </action>
+
+ <action name="Subscribe_edit" class="Subscribe" method="edit">
+ <result name="input" type="redirect-action">Login</result>
+ <result>/pages/Subscribe.jsp</result>
+ </action>
+
+ <action name="Subscribe_save" class="Subscribe" method="save">
+ <result name="input">/pages/Subscribe.jsp</result>
+ <result type="redirect-action">Register</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/test/RegisterTest.java
new file mode 100644
index 0000000..8586366
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/test/RegisterTest.java
@@ -0,0 +1,35 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setSession(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testSave() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/subscribe/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..74fbac7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,5 @@
+&welcome-open;
+<clickLink
+ description="Click Register"
+ label="Register with MailReader"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..54601e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration page title"
+ text="MailReader - Register"/>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-trillian.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-trillian.xml
new file mode 100644
index 0000000..7561f05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/register-trillian.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+<setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/save-click.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/save-click.xml
new file mode 100644
index 0000000..a02a1db
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/save-click.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Save"
+ name="Save"/>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/welcome-open.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/welcome-open.xml
new file mode 100644
index 0000000..a073531
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/entities/welcome-open.xml
@@ -0,0 +1,6 @@
+<invoke
+ description="Open welcome action"
+ url="Welcome.do"/>
+<verifyTitle
+ description="Welcome page title"
+ text="MailReader"/>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2151ea8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..aa6975a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = lab-2-2
+webapps.home = /opt/Apache/Tomcat-5.5/webapps/
+resource.home = ${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"
+# mailreader.home =
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..4f34768
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+ */
+ -->
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="lab-2-2"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register"/>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Trillian (MSS)">
+ &config;
+ <steps>
+ ®ister-open;
+ ®ister-trillian;
+ <verifyTitle
+ description="Menu page title"
+ text="MailReader - Menu"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..51e788d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Hello.jsp
@@ -0,0 +1,14 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Login.jsp b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Login.jsp
new file mode 100644
index 0000000..97d89a0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Login.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="login.title"/>
+ </title>
+</head>
+
+<body onLoad="self.focus();document.Login_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Login_save" validate="true">
+ <s:textfield key="username"/>
+
+ <s:password key="password" showPassword="true"/>
+
+ <s:submit key="button.save"/>
+
+ <s:submit action="Login_cancel" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Menu.jsp b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Menu.jsp
new file mode 100644
index 0000000..874a6f7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Menu.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="menu.title"/>
+ </title>
+</head>
+
+<body>
+<h3>
+ <s:text name="menu.heading"/>
+ <s:property value="user.fullName"/>
+</h3>
+<ul>
+ <li><a href="<s:url action="Register" />">
+ <s:text name="menu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url action="Logout"/>">
+ <s:text name="menu.logout"/>
+ </a>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..5bcc12e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Register.jsp
@@ -0,0 +1,126 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title>
+ <s:text name="registration.title.create"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title>
+ <s:text name="registration.title.edit"/>
+ </title>
+ </s:if>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save" validate="true">
+ <s:hidden name="task"/>
+ <s:if test="task == 'Create'">
+ <s:textfield key="username"/>
+ </s:if>
+ <s:else>
+ <s:label key="username"/>
+ <s:hidden name="username"/>
+ </s:else>
+
+ <s:password key="password"/>
+
+ <s:password key="password2"/>
+
+ <s:textfield key="fullName"/>
+
+ <s:textfield key="fromAddress"/>
+
+ <s:textfield key="replyToAddress"/>
+
+ <s:if test="task == 'Create'">
+ <s:submit key="button.save" action="Register_create"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Welcome" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:if>
+ <s:else>
+ <s:submit key="button.save"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Menu" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:else>
+
+</s:form>
+
+<s:if test="task == 'Edit'">
+ <div align="center">
+ <h3>
+ <s:text name="heading.subscriptions"/>
+ </h3>
+ </div>
+
+ <table border="1" width="100%">
+
+ <tr>
+ <th align="center" width="30%">
+ <s:text name="heading.host"/>
+ </th>
+ <th align="center" width="25%">
+ <s:text name="heading.user"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.type"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.autoConnect"/>
+ </th>
+ <th align="center" width="15%">
+ <s:text name="heading.action"/>
+ </th>
+ </tr>
+
+ <s:iterator value="user.subscriptions">
+ <tr>
+ <td align="left">
+ <s:property value="host"/>
+ </td>
+ <td align="left">
+ <s:property value="username"/>
+ </td>
+ <td align="center">
+ <s:property value="type"/>
+ </td>
+ <td align="center">
+ <s:property value="autoConnect"/>
+ </td>
+ <td align="center">
+
+ <a href="<s:url action="Subscribe_delete"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.deleteSubscription"/>
+ </a>
+
+ <a href="<s:url action="Subscribe_edit"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.editSubscription"/>
+ </a>
+
+ </td>
+ </tr>
+ </s:iterator>
+
+ </table>
+
+ <a href="<s:url action="Subscribe"/>">
+ <s:text
+ name="registration.addSubscription"/>
+ </a>
+
+</s:if>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Subscribe.jsp b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Subscribe.jsp
new file mode 100644
index 0000000..69f8b10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Subscribe.jsp
@@ -0,0 +1,69 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title>
+ <s:text name="subscription.title.create"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title>
+ <s:text name="subscription.title.edit"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title>
+ <s:text name="subscription.title.delete"/>
+ </title>
+ </s:if>
+</head>
+
+<body onLoad="self.focus();document.Subscribe_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Subscribe_save" validate="true">
+ <s:hidden name="task"/>
+ <s:label key="user.username"/>
+
+ <s:if test="task == 'Create'">
+ <s:textfield key="mailHostname" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label key="mailHostname" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label key="mailUsername"
+ name="subscription.username"/>
+ <s:label key="mailPassword"
+ name="subscription.password"/>
+ <s:label key="mailServerType"
+ name="subscription.type"/>
+ <s:label key="autoConnect"
+ name="subscription.autoConnect"/>
+ <s:submit key="button.confirm"/>
+ </s:if>
+ <s:else>
+ <s:textfield key="mailUsername"
+ name="subscription.username"/>
+ <s:textfield key="mailPassword"
+ name="subscription.password"/>
+ <s:select key="mailServerType"
+ name="subscription.type" list="types"/>
+ <s:checkbox key="autoConnect"
+ name="subscription.autoConnect"/>
+ <s:submit key="button.save"/>
+ <s:reset key="button.reset"/>
+ </s:else>
+
+ <s:submit action="Register"
+ key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..169b9eb
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,51 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>
+ <s:text name="index.title"/>
+ </title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Register"/>">
+ <s:text
+ name="index.registration"/>
+ </a></li>
+ <li><a href="<s:url action="Login"/>">
+ <s:text
+ name="index.login"/>
+ </a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li>
+ <s:url id="en" action="Welcome">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="ja" action="Welcome">
+ <s:param name="request_locale">ja</s:param>
+ </s:url>
+ <s:a href="%{ja}">Japanese</s:a>
+ </li>
+ <li>
+ <s:url id="ru" action="Welcome">
+ <s:param name="request_locale">ru</s:param>
+ </s:url>
+ <s:a href="%{ru}">Russian</s:a>
+ </li>
+</ul>
+<hr/>
+</body>
+</html>
+
diff --git a/struts-sandbox/mailreader-course/struts2/subscribe/subscribe.iml b/struts-sandbox/mailreader-course/struts2/subscribe/subscribe.iml
new file mode 100644
index 0000000..45a0409
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/subscribe/subscribe.iml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/subscribe/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/subscribe" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/subscribe" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/theme/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/theme/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/AuthenticationInterceptor.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/AuthenticationInterceptor.java
new file mode 100644
index 0000000..bf08889
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/AuthenticationInterceptor.java
@@ -0,0 +1,31 @@
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.Map;
+
+public class AuthenticationInterceptor implements Interceptor {
+
+ public void destroy() {
+ }
+
+ public void init() {
+ }
+
+ public String intercept(ActionInvocation actionInvocation) throws Exception {
+
+ Map session = actionInvocation.getInvocationContext().getSession();
+
+ User user = (User) session.get(MailReaderSupport.USER_KEY);
+
+ boolean isAuthenticated = (null != user) && (null != user.getDatabase());
+
+ if (!isAuthenticated) {
+ return Action.LOGIN;
+ } else {
+ return actionInvocation.invoke();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/DatabaseListener.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/DatabaseListener.java
new file mode 100644
index 0000000..3fa64d9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/DatabaseListener.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class DatabaseListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @return Absolute path to XML file.
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/Hello.java
new file mode 100644
index 0000000..7bd3506
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Login-validation.xml b/struts-sandbox/mailreader-course/struts2/theme/src/java/Login-validation.xml
new file mode 100644
index 0000000..ed9359f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Login-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Login.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/Login.java
new file mode 100644
index 0000000..d56a64c
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Login.java
@@ -0,0 +1,22 @@
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Login extends MailReaderSupport {
+
+ public String execute() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Logout.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/Logout.java
new file mode 100644
index 0000000..4f17f10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Logout.java
@@ -0,0 +1,9 @@
+public class Logout extends MailReaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/MailReaderSupport.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/MailReaderSupport.java
new file mode 100644
index 0000000..4fa163b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/MailReaderSupport.java
@@ -0,0 +1,325 @@
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+public class MailReaderSupport extends ActionSupport
+ implements ApplicationAware, SessionAware {
+
+ // ---- Register form properties ----
+
+ private String username = null;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ private String password = null;
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ private String password2 = null;
+
+ public String getPassword2() {
+ return password2;
+ }
+
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ private String fullName = null;
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public void setFullName(String value) {
+ fullName = value;
+ }
+
+ private String fromAddress = null;
+
+ public String getFromAddress() {
+ return fromAddress;
+ }
+
+ public void setFromAddress(String value) {
+ fromAddress = value;
+ }
+
+ private String replyToAddress = null;
+
+ public String getReplyToAddress() {
+ return replyToAddress;
+ }
+
+ public void setReplyToAddress(String value) {
+ replyToAddress = value;
+ }
+
+ // ---- Subscription form properties ----
+
+ private String host;
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String value) {
+ host = value;
+ }
+
+ // ---- Task property (utilized by UI) ----
+
+ private String task = null;
+
+ public String getTask() {
+ return task;
+ }
+
+ public void setTask(String value) {
+ task = value;
+ }
+
+ // ---- Keys ----
+
+ public static final String DATABASE_KEY = "database";
+
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ public static final String USER_KEY = "user";
+
+ public static final String HOST = "host";
+
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ public static final String CANCEL = "cancel";
+
+ public static final String CREATE = "Create";
+
+ public static final String EDIT = "Edit";
+
+ public static final String DELETE = "Delete";
+
+ // ---- Message Keys ----
+
+ public static final String ERROR_DATABASE_MISSING =
+ "error.database.missing";
+
+ public static final String ERROR_USERNAME_UNIQUE =
+ "error.username.unique";
+
+ public static final String ERROR_PASSWORD_MISMATCH =
+ "error.password.mismatch";
+
+ public static final String ERROR_PASSWORD_MATCH =
+ "error.password.match";
+
+ public static final String ERROR_HOST_UNIQUE
+ = "That hostname is already defined";
+
+ // ---- ApplicationAware ----
+
+ private Map application;
+
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- Database property ----
+
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText(ERROR_DATABASE_MISSING));
+ }
+ return (UserDatabase) db;
+ }
+
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(DATABASE_KEY, database);
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- Subscription property ----
+
+ public Subscription getSubscription() {
+ return (Subscription) getSession().get(SUBSCRIPTION_KEY);
+ }
+
+ public void setSubscription(Subscription subscription) {
+ getSession().put(SUBSCRIPTION_KEY, subscription);
+ }
+
+
+ public String getSubscriptionHost() {
+ Subscription sub = getSubscription();
+ if (null == sub) {
+ return null;
+ }
+ return sub.getHost();
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(USER_KEY, user);
+ }
+
+ // ---- Database methods ----
+
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+
+ User user = getDatabase().findUser(username);
+
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+
+ if (user == null) {
+ addFieldError(PASSWORD_MISMATCH_FIELD,
+ getText(ERROR_PASSWORD_MISMATCH));
+ }
+
+ return user;
+
+ }
+
+ public User createUser(String username, String password) throws Exception {
+
+ UserDatabase database = getDatabase();
+ User user = database.findUser(username);
+
+ if (user != null) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return null;
+ }
+
+ user = database.createUser(username);
+ BeanUtils.setValues(user, this, null);
+
+ return user;
+ }
+
+ public void saveUser() throws Exception {
+ getDatabase().save();
+ }
+
+ /**
+ * <p>Provide a "temporary" User Subscription object
+ * that can be used tocapture input values.</p>
+ */
+ public void createInputSubscription() {
+ Subscription sub = new MemorySubscription(getUser(), null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = getUser().findSubscription(host);
+ return subscription;
+ }
+
+ public Subscription findSubscription() {
+ return findSubscription(getHost());
+ }
+
+ public void removeSubscription() {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(SUBSCRIPTION_KEY);
+ }
+
+ public void copySubscription(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ BeanUtils.setValues(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }
+
+ public Subscription createSubscription(String host) {
+
+ Subscription sub;
+
+ sub = findSubscription(host);
+
+ if (null != sub) {
+ // FIXME - localization - "error.host.unique")
+ addFieldError(HOST, ERROR_HOST_UNIQUE);
+ return null;
+ }
+
+ return getUser().createSubscription(host);
+ }
+
+ // ---- Alias ----
+
+ public String cancel() {
+ return CANCEL;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/NPE.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/NPE.java
new file mode 100644
index 0000000..229ed0f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/NPE.java
@@ -0,0 +1,9 @@
+import com.opensymphony.xwork2.Action;
+
+public class NPE implements Action {
+
+ public String execute() {
+ throw new NullPointerException("Oops!");
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Register-validation.xml b/struts-sandbox/mailreader-course/struts2/theme/src/java/Register-validation.xml
new file mode 100644
index 0000000..f8155f6
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Register-validation.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+ <field name="replyToAddress">
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Register.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/Register.java
new file mode 100644
index 0000000..78f2bde
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Register.java
@@ -0,0 +1,65 @@
+import com.opensymphony.util.BeanUtils;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class Register extends MailReaderSupport {
+
+ public String input() throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ setTask(EDIT);
+ BeanUtils.setValues(this, user, null);
+ setPassword(null);
+ } else {
+ setTask(CREATE);
+ }
+
+ return INPUT;
+ }
+
+ public String save()
+ throws Exception {
+
+ User user = getUser();
+ boolean editing = (null != user);
+
+ if (editing) {
+ // FIXME: Any way to call the RegisterSave validators from here?
+ String newPassword = getPassword();
+ boolean changing = ((null != newPassword) && (newPassword.length() > 0));
+ if (!changing) {
+ setPassword(user.getPassword());
+ } else {
+ String confirmPassword = getPassword2();
+ boolean matches = ((null != confirmPassword)
+ && (confirmPassword.equals(newPassword)));
+ if (matches) {
+ user.setPassword(newPassword);
+ } else {
+ addActionError(getText(ERROR_PASSWORD_MATCH));
+ return INPUT;
+ }
+ }
+ BeanUtils.setValues(user, this, null);
+ }
+
+ if (!editing) {
+ user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText(ERROR_USERNAME_UNIQUE));
+ return INPUT;
+ }
+
+ user = createUser(getUsername(), getPassword());
+ setUser(user);
+ }
+
+ saveUser();
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/RegisterSave-validation.xml b/struts-sandbox/mailreader-course/struts2/theme/src/java/RegisterSave-validation.xml
new file mode 100644
index 0000000..6896407
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/RegisterSave-validation.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="errors.range"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.match"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/RegisterSave.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/RegisterSave.java
new file mode 100644
index 0000000..5360045
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/RegisterSave.java
@@ -0,0 +1,5 @@
+/**
+ * <p>Stub class to allow extra validation on initial Save.</p>
+ */
+public class RegisterSave extends Register {
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Subscribe-validation.xml b/struts-sandbox/mailreader-course/struts2/theme/src/java/Subscribe-validation.xml
new file mode 100644
index 0000000..bc422c8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Subscribe-validation.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="host">
+ <field-validator type="requiredstring">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/Subscribe.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/Subscribe.java
new file mode 100644
index 0000000..ee72b5f
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/Subscribe.java
@@ -0,0 +1,74 @@
+import com.opensymphony.xwork2.Preparable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class Subscribe extends MailReaderSupport
+ implements Preparable {
+
+ private Map types = null;
+
+ public Map getTypes() {
+ return types;
+ }
+
+ public void prepare() {
+
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+
+ setHost(getSubscriptionHost());
+ }
+
+ public String input() {
+ createInputSubscription();
+ setTask(CREATE);
+ return INPUT;
+ }
+
+ public String find() {
+
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+
+ if (sub == null) {
+ return ERROR;
+ }
+
+ setSubscription(sub);
+
+ return INPUT;
+
+ }
+
+ public String delete() {
+
+ setTask(DELETE);
+ return find();
+ }
+
+ public String edit() {
+
+ setTask(EDIT);
+ return find();
+ }
+
+ public String save() throws Exception {
+
+ if (DELETE.equals(getTask())) {
+ removeSubscription();
+ }
+
+ if (CREATE.equals(getTask())) {
+ copySubscription(getHost());
+ }
+
+ if (hasErrors()) return INPUT;
+
+ saveUser();
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/SubscribeSave-validation.xml b/struts-sandbox/mailreader-course/struts2/theme/src/java/SubscribeSave-validation.xml
new file mode 100644
index 0000000..7d28623
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/SubscribeSave-validation.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="subscription.username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.type">
+ <field-validator type="requiredstring">
+ <message key="error.type.invalid"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/SubscribeSave.java b/struts-sandbox/mailreader-course/struts2/theme/src/java/SubscribeSave.java
new file mode 100644
index 0000000..2f4e440
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/SubscribeSave.java
@@ -0,0 +1,12 @@
+public final class SubscribeSave extends Subscribe {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ getSubscription().setAutoConnect(false);
+ }
+
+ public String execute() throws Exception {
+ return save();
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/database.xml b/struts-sandbox/mailreader-course/struts2/theme/src/java/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/theme/src/java/resources.properties
new file mode 100644
index 0000000..7fc1152
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/resources.properties
@@ -0,0 +1,105 @@
+hello.message = Congratulations! Struts is up and running ...
+
+index.title=MailReader
+index.login=Log into MailReader
+index.registration=Register with MailReader
+
+registration.title.create=MailReader - Register - Create
+registration.title.edit=MailReader - Register - Edit
+
+username=Username
+password=Password
+password2=(Repeat) Password
+fullName=Full Name
+fromAddress=From Address
+replyToAddress=Reply To Address
+
+button.cancel=Cancel
+button.save=Save
+button.reset=Reset
+button.confirm=Confirm
+
+menu.title=MailReader - Main Menu
+menu.heading=Menu Options for
+menu.registration=Edit your registration profile
+menu.logout=Log out of MailReader
+
+login.title=MailReader - Logon
+
+error.database.missing=User database is missing, cannot validate logon credentials
+error.username.unique=That username is already in use - please select another
+error.password.mismatch=Invalid username and/or password, please try again
+
+error.username.required=Username is required
+error.fullName.required=Full Name is required
+error.fromAddress.required=From Address is required
+error.fromAddress.format=Invalid format for From Address
+error.replyToAddress.format=Invalid format for Reply To Address
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+
+error.host.required=Mail Server is required
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+
+# Future use
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+struts.messages.invalid.token=Cannot submit this form out of order
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/resources_ja.properties b/struts-sandbox/mailreader-course/struts2/theme/src/java/resources_ja.properties
new file mode 100644
index 0000000..60eb6d2
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/resources_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.login=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+login.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+menu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+menu.logout=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+menu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+menu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/resources_ru.properties b/struts-sandbox/mailreader-course/struts2/theme/src/java/resources_ru.properties
new file mode 100644
index 0000000..bff1ac3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/resources_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.login=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+login.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+menu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+menu.logout=\u0412\u044b\u0439\u0442\u0438
+menu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/struts.properties b/struts-sandbox/mailreader-course/struts2/theme/src/java/struts.properties
new file mode 100644
index 0000000..75c8136
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/struts.properties
@@ -0,0 +1 @@
+struts.custom.i18n.resources=resources
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/theme/src/java/struts.xml
new file mode 100644
index 0000000..54e6cc4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/java/struts.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <interceptors>
+
+ <interceptor name="authentication"
+ class="AuthenticationInterceptor"/>
+
+ <interceptor-stack name="user">
+ <interceptor-ref name="authentication"/>
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="user-submit">
+ <interceptor-ref name="token-session"/>
+ <interceptor-ref name="user"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="guest">
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="guest-submit">
+ <interceptor-ref name="token-session"/>
+ <interceptor-ref name="guest"/>
+ </interceptor-stack>
+
+ </interceptors>
+
+ <default-interceptor-ref name="user"/>
+
+ <default-action-ref name="Missing"/>
+
+ <global-results>
+ <result name="error">/pages/Error.jsp</result>
+ <result name="login" type="redirect-action">Login!input</result>
+ <result name="cancel" type="redirect-action">Welcome</result>
+ </global-results>
+
+ <global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Throwable"/>
+ </global-exception-mappings>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Register" class="Register">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="RegisterCreate" class="RegisterCreate">
+ <result name="input">/pages/Register.jsp</result>
+ <result type="redirect-action">Menu</result>
+ <interceptor-ref name="guest-submit"/>
+ </action>
+
+ <action name="Menu" class="MailReaderSupport">
+ <result>/pages/Menu.jsp</result>
+ </action>
+
+ <action name="Logout" class="Logout">
+ <result type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Login" class="Login">
+ <result name="input">/pages/Login.jsp</result>
+ <result type="redirect-action">Menu</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Subscribe" class="Subscribe">
+ <result name="input">/pages/Subscribe.jsp</result>
+ <result type="redirect-action">Register!input</result>
+ </action>
+
+ <action name="SubscribeSave" class="SubscribeSave">
+ <result name="input">/pages/Subscribe.jsp</result>
+ <result type="redirect-action">Register!input</result>
+ <interceptor-ref name="user-submit"/>
+ </action>
+
+ <action name="NPE" class="NPE">
+ <result>/pages/Hello.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/theme/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/test/RegisterTest.java b/struts-sandbox/mailreader-course/struts2/theme/src/test/RegisterTest.java
new file mode 100644
index 0000000..e1b43e0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/test/RegisterTest.java
@@ -0,0 +1,34 @@
+import com.opensymphony.xwork2.Action;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.HashMap;
+
+public class RegisterTest extends RetainTest {
+
+ Register action = null;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ action = new Register();
+ action.setApplication(new HashMap());
+ action.setDatabase(database);
+ }
+
+ public void testExecute() throws Exception {
+
+ action.setUsername("user");
+ action.setPassword("pass");
+ action.setFullName("John Q. User");
+ action.setFromAddress("John.User@somewhere.com");
+
+ String success = action.save();
+ assertTrue("Expected SUCCESS", Action.SUCCESS.equals(success));
+
+ User user = database.findUser("user");
+ assertNotNull("Expected user", user);
+
+ String input = action.save();
+ assertTrue("Expected INPUT", Action.INPUT.equals(input));
+ }
+
+}
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/test/RetainTest.java b/struts-sandbox/mailreader-course/struts2/theme/src/test/RetainTest.java
new file mode 100644
index 0000000..2666f73
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/test/RetainTest.java
@@ -0,0 +1,97 @@
+import junit.framework.TestCase;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+public class RetainTest extends TestCase {
+
+ protected UserDatabase database;
+ protected String testName = "test-database.xml";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ MemoryUserDatabase memoryUserDatabase = new MemoryUserDatabase();
+ memoryUserDatabase.setPathname(testName);
+ database = memoryUserDatabase;
+ }
+
+ public void testDatabaseClean() throws Exception {
+ User user = database.findUser("user");
+ assertNull("Expected user to be missing", user);
+ }
+
+ // Add your test methods here.
+ // The setUp method will run between each test.
+
+ public void testCreateUser() throws Exception {
+ User user = database.createUser("user");
+ assertNotNull(user);
+ }
+
+ public void testFindUser() throws Exception {
+ User user1 = database.createUser("user");
+ User user2 = database.findUser("user");
+ assertSame("Expected users to match", user1, user2);
+ }
+
+ public void testCreateSubscription() throws Exception {
+ Subscription sub = database.createUser("user").createSubscription("mail.yahoo.com");
+ assertNotNull("Expected subscription to be created", sub);
+ }
+
+ public void testFindSubscription() throws Exception {
+ Subscription sub1 = database.createUser("user").createSubscription("mail.yahoo.com");
+ Subscription sub2 = database.findUser("user").findSubscription("mail.yahoo.com");
+ assertSame("Expected Subscriptions to match", sub1, sub2);
+ }
+
+ public void testDatabsaeSave() throws Exception {
+
+ User user = database.createUser("user");
+ user.setPassword("pass");
+ user.setFullName("John Q. User");
+ user.setFromAddress("John.User@somewhere.com");
+
+ Subscription sub1 = user.createSubscription("mail.hotmail.com");
+ sub1.setUsername("user1234");
+ sub1.setAutoConnect(false);
+ sub1.setType("pop3");
+ sub1.setPassword("bar");
+
+ Subscription sub2 = user.createSubscription("mail.yahoo.com");
+ sub2.setUsername("jquser");
+ sub2.setAutoConnect(false);
+ sub2.setType("imap");
+ sub2.setPassword("foo");
+
+ database.save();
+
+ }
+
+ // Extra credit
+
+ public void testFinderUserBogus() throws Exception {
+ User user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ User user2 = database.createUser("user");
+ assertNotNull("Expected user to be created", user2);
+ user1 = database.findUser("bogus");
+ assertNull("Expected bogus user to be not found", user1);
+ user1 = database.findUser("user");
+ assertNotNull("Expected user to be found", user1);
+ }
+
+ public void testFindSubBogus() throws Exception {
+ User user = database.createUser("user");
+ Subscription sub = user.findSubscription("mail.bogus.com");
+ assertNull(sub);
+ sub = database.findUser("user").createSubscription("mail.hotmail.com");
+ assertNotNull(sub);
+ Subscription sub2 = user.findSubscription("mail.bogus.com");
+ assertNull(sub2);
+ Subscription sub3 = user.findSubscription("mail.hotmail.com");
+ assertSame(sub, sub3);
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/WebTest.dtd b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/WebTest.dtd
new file mode 100644
index 0000000..4f8a346
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/WebTest.dtd
@@ -0,0 +1,4697 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!ENTITY % boolean "(true|false|on|off|yes|no)">
+<!ENTITY % tasks "propertyfile | ccmkdir | importtypelib | vsscheckin | sql | cvspass | csc | dirname | replaceregexp | get | jjtree | sleep | jarlib-display | length | dependset | zip | patch | jspc | style | nice | test | tstamp | unwar | vsshistory | cvschangelog | ccmcheckin | bzip2 | sync | vssadd | javadoc | translate | signjar | cclock | chown | jarlib-available | WsdlToDotnet | buildnumber | jpcovmerge | cvsversion | ejbjar | war | rename | sequential | serverdeploy | property | subant | move | ildasm | copydir | cccheckin | ccunlock | wljspc | fixcrlf | sosget | pathconvert | record | exec | ccmklabel | manifest | jpcovreport | execon | ccmcheckout | ant | xmlvalidate | xslt | iplanet-ejbc | ccmcheckintask | gzip | native2ascii | ccrmtype | ear | input | presetdef | rmic | checksum | mail | loadfile | vsscheckout | soscheckin | mimemail | gunzip | concat | cab | touch | parallel | antcall | ccmkbl | cccheckout | typedef | filter | xmlproperty | import | copy | jsharpc | symlink | antstructure | script | ccmcreatetask | rpm | delete | replace | mmetrics | attrib | waitfor | untar | loadproperties | available | echoproperties | junit | chgrp | bunzip2 | whichresource | copyfile | vsscreate | macrodef | unjar | vbc | wsdltodotnet | mkdir | condition | cvs | tempfile | junitreport | ccmkattr | taskdef | echo | ccupdate | java | renameext | vsslabel | basename | javadoc2 | vsscp | tar | setproxy | ilasm | soscheckout | apply | ccuncheckout | jarlib-resolve | cvstagdiff | jlink | javacc | chmod | pvcs | jarlib-manifest | jar | ccmklbtype | scriptdef | defaultexcludes | mparse | blgenclient | uptodate | jjdoc | genkey | javah | ccmkelem | ccmreconfigure | fail | unzip | javac | jpcoverage | soslabel | depend | vssget | deltree">
+<!ENTITY % types "patternset | assertions | propertyset | filtermapper | filterset | libfileset | isfileselected | mergemapper | identitymapper | filterreader | scriptfilter | unpackagemapper | concatfilter | extension | fileset | dirset | globmapper | filelist | filterchain | path | compositemapper | classfileset | regexpmapper | selector | xmlcatalog | flattenmapper | description | chainedmapper | packagemapper | mapper | zipfileset | substitution | extensionSet | redirector | regexp">
+
+<!ELEMENT project (target | %tasks; | %types;)*>
+<!ATTLIST project
+ name CDATA #IMPLIED
+ default CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT target (%tasks; | %types;)*>
+
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ depends CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT patternset (include | patternset | exclude | excludesfile | includesfile)*>
+<!ATTLIST patternset
+ id ID #IMPLIED
+ includes CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT exclude EMPTY>
+<!ATTLIST exclude
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT excludesfile EMPTY>
+<!ATTLIST excludesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT includesfile EMPTY>
+<!ATTLIST includesfile
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT assertions (disable | enable)*>
+<!ATTLIST assertions
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ enablesystemassertions %boolean; #IMPLIED>
+
+<!ELEMENT disable EMPTY>
+<!ATTLIST disable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT enable EMPTY>
+<!ATTLIST enable
+ id ID #IMPLIED
+ package CDATA #IMPLIED
+ class CDATA #IMPLIED>
+
+<!ELEMENT propertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST propertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT propertyref EMPTY>
+<!ATTLIST propertyref
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ builtin (all | system | commandline) #IMPLIED
+ regex CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT mapper (classpath | mapper)*>
+<!ATTLIST mapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST classpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT fileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT custom (classpath | param)*>
+<!ATTLIST custom
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ error CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ type CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT present (mapper)*>
+<!ATTLIST present
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ present (srconly | both) #IMPLIED>
+
+<!ELEMENT none (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST none
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT not (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST not
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT type EMPTY>
+<!ATTLIST type
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ type (file | dir) #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT modified (param)*>
+<!ATTLIST modified
+ id ID #IMPLIED
+ comparator (equal | rule) #IMPLIED
+ seldirs %boolean; #IMPLIED
+ algorithm (hashvalue | digest) #IMPLIED
+ cache (propertyfile) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ update %boolean; #IMPLIED>
+
+<!ELEMENT or (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST or
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT contains EMPTY>
+<!ATTLIST contains
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ text CDATA #IMPLIED>
+
+<!ELEMENT depend (mapper)*>
+<!ATTLIST depend
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT different (mapper)*>
+<!ATTLIST different
+ id ID #IMPLIED
+ ignorecontents %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ targetdir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ ignorefiletimes %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT size EMPTY>
+<!ATTLIST size
+ id ID #IMPLIED
+ when (less | more | equal) #IMPLIED
+ units (K | k | kilo | KILO | Ki | KI | ki | kibi | KIBI | M | m | mega | MEGA | Mi | MI | mi | mebi | MEBI | G | g | giga | GIGA | Gi | GI | gi | gibi | GIBI | T | t | tera | TERA | Ti | TI | ti | tebi | TEBI) #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT majority (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST majority
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ allowtie %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT containsregexp EMPTY>
+<!ATTLIST containsregexp
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT filename EMPTY>
+<!ATTLIST filename
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT selector (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST selector
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT date EMPTY>
+<!ATTLIST date
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ millis CDATA #IMPLIED
+ checkdirs %boolean; #IMPLIED
+ datetime CDATA #IMPLIED
+ granularity CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ when (before | after | equal) #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT and (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST and
+ id ID #IMPLIED
+ error CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depth EMPTY>
+<!ATTLIST depth
+ id ID #IMPLIED
+ max CDATA #IMPLIED
+ error CDATA #IMPLIED
+ min CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT dirset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST dirset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT extdirs (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST extdirs
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT existing (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST existing
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filelist (file)*>
+<!ATTLIST filelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT file EMPTY>
+<!ATTLIST file
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT pathelement EMPTY>
+<!ATTLIST pathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT path (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST path
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT filtermapper (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filtermapper
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT headfilter EMPTY>
+<!ATTLIST headfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT classconstants EMPTY>
+<!ATTLIST classconstants
+ id ID #IMPLIED>
+
+<!ELEMENT linecontains (contains)*>
+<!ATTLIST linecontains
+ id ID #IMPLIED>
+
+<!ELEMENT filterreader (classpath | param)*>
+<!ATTLIST filterreader
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT replaceregex EMPTY>
+<!ATTLIST replaceregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT replacetokens (token)*>
+<!ATTLIST replacetokens
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED>
+
+<!ELEMENT token EMPTY>
+<!ATTLIST token
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT escapeunicode EMPTY>
+<!ATTLIST escapeunicode
+ id ID #IMPLIED>
+
+<!ELEMENT ignoreblank EMPTY>
+<!ATTLIST ignoreblank
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT tailfilter EMPTY>
+<!ATTLIST tailfilter
+ id ID #IMPLIED
+ lines CDATA #IMPLIED
+ skip CDATA #IMPLIED>
+
+<!ELEMENT tabstospaces EMPTY>
+<!ATTLIST tabstospaces
+ id ID #IMPLIED
+ tablength CDATA #IMPLIED>
+
+<!ELEMENT prefixlines EMPTY>
+<!ATTLIST prefixlines
+ id ID #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT trim EMPTY>
+<!ATTLIST trim
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED>
+
+<!ELEMENT expandproperties EMPTY>
+<!ATTLIST expandproperties
+ id ID #IMPLIED>
+
+<!ELEMENT striplinebreaks EMPTY>
+<!ATTLIST striplinebreaks
+ id ID #IMPLIED
+ linebreaks CDATA #IMPLIED>
+
+<!ELEMENT replacestring EMPTY>
+<!ATTLIST replacestring
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT striplinecomments (comment)*>
+<!ATTLIST striplinecomments
+ id ID #IMPLIED>
+
+<!ELEMENT comment EMPTY>
+<!ATTLIST comment
+ id ID #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT tokenfilter (containsstring | linetokenizer | trim | stringtokenizer | replaceregex | replacestring | ignoreblank | deletecharacters | containsregex | filetokenizer)*>
+<!ATTLIST tokenfilter
+ id ID #IMPLIED
+ delimoutput CDATA #IMPLIED>
+
+<!ELEMENT containsstring EMPTY>
+<!ATTLIST containsstring
+ id ID #IMPLIED
+ contains CDATA #IMPLIED>
+
+<!ELEMENT linetokenizer EMPTY>
+<!ATTLIST linetokenizer
+ id ID #IMPLIED
+ includedelims %boolean; #IMPLIED>
+
+<!ELEMENT stringtokenizer EMPTY>
+<!ATTLIST stringtokenizer
+ id ID #IMPLIED
+ suppressdelims %boolean; #IMPLIED
+ includedelims %boolean; #IMPLIED
+ delimsaretokens %boolean; #IMPLIED
+ delims CDATA #IMPLIED>
+
+<!ELEMENT deletecharacters EMPTY>
+<!ATTLIST deletecharacters
+ id ID #IMPLIED
+ chars CDATA #IMPLIED>
+
+<!ELEMENT containsregex EMPTY>
+<!ATTLIST containsregex
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filetokenizer EMPTY>
+<!ATTLIST filetokenizer
+ id ID #IMPLIED>
+
+<!ELEMENT stripjavacomments EMPTY>
+<!ATTLIST stripjavacomments
+ id ID #IMPLIED>
+
+<!ELEMENT linecontainsregexp (regexp)*>
+<!ATTLIST linecontainsregexp
+ id ID #IMPLIED>
+
+<!ELEMENT regexp EMPTY>
+<!ATTLIST regexp
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED>
+
+<!ELEMENT filterset (filterset | filter | filtersfile)*>
+<!ATTLIST filterset
+ id ID #IMPLIED
+ begintoken CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ filtersfile CDATA #IMPLIED>
+
+<!ELEMENT filter EMPTY>
+<!ATTLIST filter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT filtersfile EMPTY>
+<!ATTLIST filtersfile
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT libfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST libfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ urlbase CDATA #IMPLIED
+ includeimpl %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeurl %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT isfileselected (custom | none | present | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | date | and | depth)*>
+<!ATTLIST isfileselected
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT mergemapper EMPTY>
+<!ATTLIST mergemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT identitymapper EMPTY>
+<!ATTLIST identitymapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT scriptfilter (#PCDATA)>
+<!ATTLIST scriptfilter
+ id ID #IMPLIED
+ byline %boolean; #IMPLIED
+ token CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT unpackagemapper EMPTY>
+<!ATTLIST unpackagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT concatfilter EMPTY>
+<!ATTLIST concatfilter
+ id ID #IMPLIED
+ append CDATA #IMPLIED
+ prepend CDATA #IMPLIED>
+
+<!ELEMENT extension EMPTY>
+<!ATTLIST extension
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ implementationversion CDATA #IMPLIED
+ specificationversion CDATA #IMPLIED
+ extensionname CDATA #IMPLIED
+ implementationvendorid CDATA #IMPLIED
+ specificationvendor CDATA #IMPLIED
+ implementationurl CDATA #IMPLIED
+ description CDATA #IMPLIED
+ implementationvendor CDATA #IMPLIED>
+
+<!ELEMENT globmapper EMPTY>
+<!ATTLIST globmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT filterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST filterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT compositemapper (mapper)*>
+<!ATTLIST compositemapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT classfileset (patternset | exclude | include | custom | rootfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | root | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ rootclass CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT rootfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST rootfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT root EMPTY>
+<!ATTLIST root
+ id ID #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT regexpmapper EMPTY>
+<!ATTLIST regexpmapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT xmlcatalog (entity | classpath | catalogpath | dtd | xmlcatalog)*>
+<!ATTLIST xmlcatalog
+ id ID #IMPLIED
+ catalogpathref IDREF #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT entity EMPTY>
+<!ATTLIST entity
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT catalogpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST catalogpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT dtd EMPTY>
+<!ATTLIST dtd
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ base CDATA #IMPLIED
+ publicid CDATA #IMPLIED>
+
+<!ELEMENT flattenmapper EMPTY>
+<!ATTLIST flattenmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT chainedmapper (mapper)*>
+<!ATTLIST chainedmapper
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT packagemapper EMPTY>
+<!ATTLIST packagemapper
+ id ID #IMPLIED
+ handledirsep %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT zipfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipfileset
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT substitution EMPTY>
+<!ATTLIST substitution
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ expression CDATA #IMPLIED>
+
+<!ELEMENT extensionSet (fileset | libfileset | extension)*>
+<!ATTLIST extensionSet
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT redirector (errorfilterchain | outputfilterchain | errormapper | inputfilterchain | outputmapper | inputmapper)*>
+<!ATTLIST redirector
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ inputencoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ createemptyfiles %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ error CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ alwayslog %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ description CDATA #IMPLIED
+ errorencoding CDATA #IMPLIED
+ logerror %boolean; #IMPLIED>
+
+<!ELEMENT errorfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST errorfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST outputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT errormapper (classpath | mapper)*>
+<!ATTLIST errormapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputfilterchain (headfilter | classconstants | linecontains | filterreader | replaceregex | replacetokens | escapeunicode | ignoreblank | tailfilter | tabstospaces | prefixlines | trim | expandproperties | striplinebreaks | replacestring | striplinecomments | tokenfilter | stripjavacomments | containsregex | deletecharacters | linecontainsregexp)*>
+<!ATTLIST inputfilterchain
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT outputmapper (classpath | mapper)*>
+<!ATTLIST outputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT inputmapper (classpath | mapper)*>
+<!ATTLIST inputmapper
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ type (identity | flatten | glob | merge | regexp | package | unpackage) #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT propertyfile (entry)*>
+<!ATTLIST propertyfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT entry EMPTY>
+<!ATTLIST entry
+ id ID #IMPLIED
+ operation CDATA #IMPLIED
+ default CDATA #IMPLIED
+ key CDATA #IMPLIED
+ type (int | date | string) #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT ccmkdir EMPTY>
+<!ATTLIST ccmkdir
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT importtypelib EMPTY>
+<!ATTLIST importtypelib
+ id ID #IMPLIED
+ unsafe %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ usesysarray %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT vsscheckin EMPTY>
+<!ATTLIST vsscheckin
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT sql (#PCDATA | fileset | classpath | transaction)*>
+<!ATTLIST sql
+ id ID #IMPLIED
+ onerror (continue | stop | abort) #IMPLIED
+ userid CDATA #IMPLIED
+ password CDATA #IMPLIED
+ autocommit %boolean; #IMPLIED
+ rdbms CDATA #IMPLIED
+ print %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ encoding CDATA #IMPLIED
+ version CDATA #IMPLIED
+ url CDATA #IMPLIED
+ src CDATA #IMPLIED
+ output CDATA #IMPLIED
+ driver CDATA #IMPLIED
+ showheaders %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ delimitertype (normal | row) #IMPLIED
+ escapeprocessing %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ caching %boolean; #IMPLIED
+ keepformat %boolean; #IMPLIED
+ delimiter CDATA #IMPLIED>
+
+<!ELEMENT transaction (#PCDATA)>
+<!ATTLIST transaction
+ id ID #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT cvspass EMPTY>
+<!ATTLIST cvspass
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ password CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ passfile CDATA #IMPLIED>
+
+<!ELEMENT csc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST csc
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ definitions CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED
+ fullpaths %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ utf8output %boolean; #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ warnlevel CDATA #IMPLIED
+ win32res CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ extraoptions CDATA #IMPLIED
+ incremental %boolean; #IMPLIED
+ noconfig %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ references CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ docfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ unsafe %boolean; #IMPLIED
+ filealign CDATA #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED>
+
+<!ELEMENT resource EMPTY>
+<!ATTLIST resource
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ embed %boolean; #IMPLIED>
+
+<!ELEMENT define EMPTY>
+<!ATTLIST define
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT reference (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST reference
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT src (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST src
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT dirname EMPTY>
+<!ATTLIST dirname
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replaceregexp (fileset | substitution | regexp)*>
+<!ATTLIST replaceregexp
+ id ID #IMPLIED
+ flags CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ match CDATA #IMPLIED
+ byline %boolean; #IMPLIED
+ replace CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
+
+<!ELEMENT get EMPTY>
+<!ATTLIST get
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ ignoreerrors %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ usetimestamp %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT jjtree EMPTY>
+<!ATTLIST jjtree
+ id ID #IMPLIED
+ nodedefaultvoid %boolean; #IMPLIED
+ buildnodefiles %boolean; #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ static %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ nodeprefix CDATA #IMPLIED
+ nodefactory %boolean; #IMPLIED
+ multi %boolean; #IMPLIED
+ visitor %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ nodeusesparser %boolean; #IMPLIED
+ visitorexception CDATA #IMPLIED
+ nodescopehook %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nodepackage CDATA #IMPLIED>
+
+<!ELEMENT sleep EMPTY>
+<!ATTLIST sleep
+ id ID #IMPLIED
+ hours CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ milliseconds CDATA #IMPLIED
+ minutes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ seconds CDATA #IMPLIED>
+
+<!ELEMENT jarlib-display (fileset)*>
+<!ATTLIST jarlib-display
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT length EMPTY>
+<!ATTLIST length
+ id ID #IMPLIED
+ length CDATA #IMPLIED
+ file CDATA #IMPLIED
+ trim %boolean; #IMPLIED
+ mode (each | all) #IMPLIED
+ string CDATA #IMPLIED
+ when (equal | greater | less) #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT dependset (patternset | exclude | include | custom | present | none | not | type | targetfileset | srcfileset | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | srcfilelist | date | excludesfile | depth | and | targetfilelist)*>
+<!ATTLIST dependset
+ id ID #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT targetfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST targetfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT srcfilelist (file)*>
+<!ATTLIST srcfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT targetfilelist (file)*>
+<!ATTLIST targetfilelist
+ id ID #IMPLIED
+ dir CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ files CDATA #IMPLIED>
+
+<!ELEMENT zip (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST zip
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT zipgroupfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST zipgroupfileset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ id ID #IMPLIED
+ strip CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ originalfile CDATA #IMPLIED
+ patchfile CDATA #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ backups %boolean; #IMPLIED
+ ignorewhitespace %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jspc (patternset | exclude | include | custom | present | none | not | type | compilerclasspath | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | webapp | depth | and)*>
+<!ATTLIST jspc
+ id ID #IMPLIED
+ mapped %boolean; #IMPLIED
+ ieplugin CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ package CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ compilerclasspath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ uribase CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ uriroot CDATA #IMPLIED
+ webinc CDATA #IMPLIED>
+
+<!ELEMENT compilerclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST compilerclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT webapp EMPTY>
+<!ATTLIST webapp
+ id ID #IMPLIED
+ basedir CDATA #IMPLIED>
+
+<!ELEMENT style (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST style
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT factory (attribute)*>
+<!ATTLIST factory
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT attribute EMPTY>
+<!ATTLIST attribute
+ id ID #IMPLIED>
+
+<!ELEMENT outputproperty EMPTY>
+<!ATTLIST outputproperty
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED>
+
+<!ELEMENT nice EMPTY>
+<!ATTLIST nice
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ newpriority CDATA #IMPLIED
+ currentpriority CDATA #IMPLIED>
+
+<!ELEMENT test (classpath | sysproperty | redirector | bootclasspath | env | syspropertyset | permissions | jvmarg | arg | assertions | testlet)*>
+<!ATTLIST test
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ forceshowtrace %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ showsuccess %boolean; #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ showbanner CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED
+ showtrace %boolean; #IMPLIED>
+
+<!ELEMENT sysproperty EMPTY>
+<!ATTLIST sysproperty
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT bootclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST bootclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT env EMPTY>
+<!ATTLIST env
+ id ID #IMPLIED
+ key CDATA #IMPLIED
+ file CDATA #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT syspropertyset (propertyref | propertyset | mapper)*>
+<!ATTLIST syspropertyset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dynamic %boolean; #IMPLIED
+ negate %boolean; #IMPLIED>
+
+<!ELEMENT permissions (grant | revoke)*>
+<!ATTLIST permissions
+ id ID #IMPLIED>
+
+<!ELEMENT grant EMPTY>
+<!ATTLIST grant
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT revoke EMPTY>
+<!ATTLIST revoke
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ class CDATA #IMPLIED
+ actions CDATA #IMPLIED>
+
+<!ELEMENT jvmarg EMPTY>
+<!ATTLIST jvmarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT testlet (#PCDATA)>
+<!ATTLIST testlet
+ id ID #IMPLIED>
+
+<!ELEMENT tstamp (format)*>
+<!ATTLIST tstamp
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED>
+
+<!ELEMENT format EMPTY>
+<!ATTLIST format
+ id ID #IMPLIED
+ locale CDATA #IMPLIED
+ timezone CDATA #IMPLIED
+ unit (millisecond | second | minute | hour | day | week | month | year) #IMPLIED
+ pattern CDATA #IMPLIED
+ property CDATA #IMPLIED
+ offset CDATA #IMPLIED>
+
+<!ELEMENT unwar (fileset | patternset)*>
+<!ATTLIST unwar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsshistory EMPTY>
+<!ATTLIST vsshistory
+ id ID #IMPLIED
+ style (brief | codediff | nofile | default) #IMPLIED
+ numdays CDATA #IMPLIED
+ todate CDATA #IMPLIED
+ fromlabel CDATA #IMPLIED
+ output CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ fromdate CDATA #IMPLIED
+ user CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ tolabel CDATA #IMPLIED
+ dateformat CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT cvschangelog (fileset | user | commandline)*>
+<!ATTLIST cvschangelog
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ end CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ start CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ usersfile CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ daysinpast CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT user EMPTY>
+<!ATTLIST user
+ id ID #IMPLIED
+ userid CDATA #IMPLIED
+ displayname CDATA #IMPLIED>
+
+<!ELEMENT commandline (marker | argument)*>
+<!ATTLIST commandline
+ id ID #IMPLIED
+ executable CDATA #IMPLIED>
+
+<!ELEMENT marker EMPTY>
+<!ATTLIST marker
+ id ID #IMPLIED>
+
+<!ELEMENT argument EMPTY>
+<!ATTLIST argument
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ file CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT ccmcheckin (fileset)*>
+<!ATTLIST ccmcheckin
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT bzip2 EMPTY>
+<!ATTLIST bzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT sync (fileset)*>
+<!ATTLIST sync
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ granularity CDATA #IMPLIED>
+
+<!ELEMENT vssadd EMPTY>
+<!ATTLIST vssadd
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ writable %boolean; #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT javadoc (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT taglet (path)*>
+<!ATTLIST taglet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT doclet (path | param)*>
+<!ATTLIST doclet
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT package EMPTY>
+<!ATTLIST package
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ id ID #IMPLIED
+ href CDATA #IMPLIED
+ offline %boolean; #IMPLIED
+ packagelistloc CDATA #IMPLIED
+ resolvelink %boolean; #IMPLIED>
+
+<!ELEMENT doctitle (#PCDATA)>
+<!ATTLIST doctitle
+ id ID #IMPLIED>
+
+<!ELEMENT bottom (#PCDATA)>
+<!ATTLIST bottom
+ id ID #IMPLIED>
+
+<!ELEMENT group (package | title)*>
+<!ATTLIST group
+ id ID #IMPLIED
+ packages CDATA #IMPLIED
+ title CDATA #IMPLIED>
+
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ id ID #IMPLIED>
+
+<!ELEMENT packageset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST packageset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT sourcepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST sourcepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT footer (#PCDATA)>
+<!ATTLIST footer
+ id ID #IMPLIED>
+
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ id ID #IMPLIED
+ file CDATA #IMPLIED>
+
+<!ELEMENT header (#PCDATA)>
+<!ATTLIST header
+ id ID #IMPLIED>
+
+<!ELEMENT excludepackage EMPTY>
+<!ATTLIST excludepackage
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT tag (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tag
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ name CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ enabled %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ scope CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT translate (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST translate
+ id ID #IMPLIED
+ bundlecountry CDATA #IMPLIED
+ bundlelanguage CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ srcencoding CDATA #IMPLIED
+ bundle CDATA #IMPLIED
+ bundleencoding CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ destencoding CDATA #IMPLIED
+ bundlevariant CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ endtoken CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ starttoken CDATA #IMPLIED>
+
+<!ELEMENT signjar (fileset)*>
+<!ATTLIST signjar
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ lazy %boolean; #IMPLIED
+ jar CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ sectionsonly %boolean; #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ sigfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ internalsf %boolean; #IMPLIED
+ storetype CDATA #IMPLIED
+ signedjar CDATA #IMPLIED>
+
+<!ELEMENT cclock EMPTY>
+<!ATTLIST cclock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ nusers CDATA #IMPLIED
+ obsolete %boolean; #IMPLIED>
+
+<!ELEMENT chown (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chown
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ owner CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT srcfile EMPTY>
+<!ATTLIST srcfile
+ id ID #IMPLIED>
+
+<!ELEMENT targetfile EMPTY>
+<!ATTLIST targetfile
+ id ID #IMPLIED>
+
+<!ELEMENT jarlib-available (extensionset | extension)*>
+<!ATTLIST jarlib-available
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT extensionset (fileset | libfileset | extension)*>
+<!ATTLIST extensionset
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT WsdlToDotnet EMPTY>
+<!ATTLIST WsdlToDotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildnumber EMPTY>
+<!ATTLIST buildnumber
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jpcovmerge (fileset)*>
+<!ATTLIST jpcovmerge
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ home CDATA #IMPLIED>
+
+<!ELEMENT cvsversion (commandline)*>
+<!ATTLIST cvsversion
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ serverversionproperty CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ clientversionproperty CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT ejbjar (patternset | exclude | include | custom | weblogictoplink | present | none | jboss | not | borland | weblogic | type | modified | iplanet | or | jonas | contains | depend | support | classpath | different | size | majority | websphere | containsregexp | dtd | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ejbjar
+ id ID #IMPLIED
+ descriptordir CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basenameterminator CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ cmpversion (1.0 | 2.0) #IMPLIED
+ dependency CDATA #IMPLIED
+ basejarname CDATA #IMPLIED
+ flatdestdir %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ naming (ejb-name | directory | descriptor | basejarname) #IMPLIED
+ excludesfile CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT weblogictoplink (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogictoplink
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ toplinkdtd CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ toplinkdescriptor CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wlclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wlclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT jboss (classpath)*>
+<!ATTLIST jboss
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT borland (classpath)*>
+<!ATTLIST borland
+ id ID #IMPLIED
+ verifyargs CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ java2iiopparams CDATA #IMPLIED
+ version CDATA #IMPLIED
+ basdtd CDATA #IMPLIED
+ verify %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ generateclient %boolean; #IMPLIED>
+
+<!ELEMENT weblogic (classpath | wlclasspath | sysproperty)*>
+<!ATTLIST weblogic
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ args CDATA #IMPLIED
+ outputdir CDATA #IMPLIED
+ wldtd CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ weblogicdtd CDATA #IMPLIED
+ wlclasspath CDATA #IMPLIED
+ jvmdebuglevel CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ ejbcclass CDATA #IMPLIED
+ noejbc %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT iplanet (classpath)*>
+<!ATTLIST iplanet
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ iashome CDATA #IMPLIED>
+
+<!ELEMENT jonas (classpath)*>
+<!ATTLIST jonas
+ id ID #IMPLIED
+ jonasroot CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ additionalargs CDATA #IMPLIED
+ javac CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ orb CDATA #IMPLIED
+ jarsuffix CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED
+ nogenic %boolean; #IMPLIED
+ rmicopts CDATA #IMPLIED
+ javacopts CDATA #IMPLIED
+ novalidation %boolean; #IMPLIED
+ keepgenerated %boolean; #IMPLIED
+ nocompil %boolean; #IMPLIED
+ secpropag %boolean; #IMPLIED>
+
+<!ELEMENT support (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST support
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT websphere (classpath | wasclasspath)*>
+<!ATTLIST websphere
+ id ID #IMPLIED
+ newcmp %boolean; #IMPLIED
+ ejbdtd CDATA #IMPLIED
+ rmicoptions CDATA #IMPLIED
+ noinform %boolean; #IMPLIED
+ rebuild %boolean; #IMPLIED
+ suffix CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ dbschema CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ ejbdeploy %boolean; #IMPLIED
+ use35 %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ novalidate %boolean; #IMPLIED
+ codegen %boolean; #IMPLIED
+ dbvendor (SQL92 | SQL99 | DB2UDBWIN_V71 | DB2UDBOS390_V6 | DB2UDBAS400_V4R5 | ORACLE_V8 | INFORMIX_V92 | SYBASE_V1192 | MSSQLSERVER_V7 | MYSQL_V323) #IMPLIED
+ classpath CDATA #IMPLIED
+ wasclasspath CDATA #IMPLIED
+ oldcmp %boolean; #IMPLIED
+ dbname CDATA #IMPLIED
+ keepgeneric %boolean; #IMPLIED
+ trace %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ genericjarsuffix CDATA #IMPLIED>
+
+<!ELEMENT wasclasspath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST wasclasspath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT war (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | lib | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | classes | date | excludesfile | webinf | depth | and)*>
+<!ATTLIST war
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ webxml CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ warfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT manifest (attribute | section)*>
+<!ATTLIST manifest
+ id ID #IMPLIED>
+
+<!ELEMENT section (attribute)*>
+<!ATTLIST section
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT metainf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST metainf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT lib (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST lib
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT indexjars (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST indexjars
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT classes (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST classes
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT webinf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST webinf
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT rename EMPTY>
+<!ATTLIST rename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ replace CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT sequential (%tasks;)*>
+<!ATTLIST sequential
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT serverdeploy (weblogic | generic | jonas)*>
+<!ATTLIST serverdeploy
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ action CDATA #IMPLIED
+ source CDATA #IMPLIED>
+
+<!ELEMENT generic (arg | classpath | jvmarg)*>
+<!ATTLIST generic
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ password CDATA #IMPLIED
+ server CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ username CDATA #IMPLIED>
+
+<!ELEMENT property (classpath)*>
+<!ATTLIST property
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ url CDATA #IMPLIED
+ name CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ userproperty %boolean; #IMPLIED
+ resource CDATA #IMPLIED
+ environment CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ location CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT subant (reference | fileset | buildpathelement | dirset | buildpath | propertyset | filelist | property)*>
+<!ATTLIST subant
+ id ID #IMPLIED
+ genericantfile CDATA #IMPLIED
+ output CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ antfile CDATA #IMPLIED
+ buildpathref IDREF #IMPLIED
+ target CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ buildpath CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT buildpathelement EMPTY>
+<!ATTLIST buildpathelement
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT buildpath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST buildpath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT move (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST move
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT ildasm EMPTY>
+<!ATTLIST ildasm
+ id ID #IMPLIED
+ assembler %boolean; #IMPLIED
+ encoding (ascii | utf8 | unicode) #IMPLIED
+ executable CDATA #IMPLIED
+ progressbar %boolean; #IMPLIED
+ linenumbers %boolean; #IMPLIED
+ rawexceptionhandling %boolean; #IMPLIED
+ showsource %boolean; #IMPLIED
+ metadata %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ bytes %boolean; #IMPLIED
+ resourcedir CDATA #IMPLIED
+ quoteallnames %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ header %boolean; #IMPLIED
+ visibility CDATA #IMPLIED
+ sourcefile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ item CDATA #IMPLIED>
+
+<!ELEMENT copydir (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST copydir
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ src CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT cccheckin EMPTY>
+<!ATTLIST cccheckin
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ccunlock EMPTY>
+<!ATTLIST ccunlock
+ id ID #IMPLIED
+ objsel CDATA #IMPLIED
+ pname CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ objselect CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT wljspc (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST wljspc
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ package CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT fixcrlf (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST fixcrlf
+ id ID #IMPLIED
+ tab (add | asis | remove) #IMPLIED
+ excludes CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ cr (add | asis | remove) #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ javafiles %boolean; #IMPLIED
+ eof (add | asis | remove) #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ tablength CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ fixlast %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT sosget EMPTY>
+<!ATTLIST sosget
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocompress %boolean; #IMPLIED
+ nocache %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT pathconvert (path | map | mapper)*>
+<!ATTLIST pathconvert
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ pathsep CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ dirsep CDATA #IMPLIED
+ setonempty %boolean; #IMPLIED
+ property CDATA #IMPLIED
+ targetos CDATA #IMPLIED>
+
+<!ELEMENT map EMPTY>
+<!ATTLIST map
+ id ID #IMPLIED
+ to CDATA #IMPLIED
+ from CDATA #IMPLIED>
+
+<!ELEMENT record EMPTY>
+<!ATTLIST record
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ loglevel (error | warn | info | verbose | debug) #IMPLIED
+ description CDATA #IMPLIED
+ emacsmode %boolean; #IMPLIED
+ action (start | stop) #IMPLIED>
+
+<!ELEMENT exec (arg | redirector | env)*>
+<!ATTLIST exec
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED>
+
+<!ELEMENT ccmklabel EMPTY>
+<!ATTLIST ccmklabel
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT jpcovreport (reference | coveragepath | sourcepath)*>
+<!ATTLIST jpcovreport
+ id ID #IMPLIED
+ snapshot CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ filters CDATA #IMPLIED
+ percent CDATA #IMPLIED
+ home CDATA #IMPLIED
+ type (executive | summary | detailed | verydetailed) #IMPLIED
+ taskname CDATA #IMPLIED
+ format (html | text | xml) #IMPLIED
+ includesource %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT coveragepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST coveragepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT execon (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST execon
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckout (fileset)*>
+<!ATTLIST ccmcheckout
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT ant (reference | propertyset | property | target)*>
+<!ATTLIST ant
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ antfile CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT target EMPTY>
+<!ATTLIST target
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT xmlvalidate (fileset | classpath | dtd | xmlcatalog | attribute | property)*>
+<!ATTLIST xmlvalidate
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ lenient %boolean; #IMPLIED
+ warn %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT xslt (patternset | exclude | include | custom | present | none | not | type | factory | modified | param | or | contains | depend | classpath | different | size | majority | containsregexp | filename | xmlcatalog | selector | includesfile | outputproperty | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST xslt
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ processor CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ basedir CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ scanincludeddirectories %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ extension CDATA #IMPLIED
+ in CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ reloadstylesheet %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ out CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ style CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT iplanet-ejbc (classpath)*>
+<!ATTLIST iplanet-ejbc
+ id ID #IMPLIED
+ ejbdescriptor CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ iasdescriptor CDATA #IMPLIED
+ iashome CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ keepgenerated %boolean; #IMPLIED>
+
+<!ELEMENT ccmcheckintask (fileset)*>
+<!ATTLIST ccmcheckintask
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ task CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ comment CDATA #IMPLIED>
+
+<!ELEMENT gzip EMPTY>
+<!ATTLIST gzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ zipfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT native2ascii (patternset | exclude | include | custom | present | none | not | type | arg | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | mapper | date | excludesfile | depth | and)*>
+<!ATTLIST native2ascii
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ ext CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ reverse %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT ccrmtype EMPTY>
+<!ATTLIST ccrmtype
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ rmall %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ ignore %boolean; #IMPLIED
+ typekind CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT ear (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | archives | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST ear
+ id ID #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ comment CDATA #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ earfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ appxml CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT archives (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST archives
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ filemode CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ dirmode CDATA #IMPLIED>
+
+<!ELEMENT input (#PCDATA)>
+<!ATTLIST input
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ addproperty CDATA #IMPLIED
+ description CDATA #IMPLIED
+ defaultvalue CDATA #IMPLIED
+ validargs CDATA #IMPLIED
+ message CDATA #IMPLIED>
+
+<!ELEMENT presetdef (%tasks;)*>
+<!ATTLIST presetdef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT rmic (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | or | contains | depend | classpath | different | size | majority | containsregexp | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST rmic
+ id ID #IMPLIED
+ verify %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ iiop %boolean; #IMPLIED
+ idlopts CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ sourcebase CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ base CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ compiler CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ idl %boolean; #IMPLIED
+ iiopopts CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filtering %boolean; #IMPLIED
+ stubversion CDATA #IMPLIED>
+
+<!ELEMENT compilerarg EMPTY>
+<!ATTLIST compilerarg
+ id ID #IMPLIED
+ line CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ file CDATA #IMPLIED
+ compiler CDATA #IMPLIED
+ pathref IDREF #IMPLIED
+ value CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT checksum (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST checksum
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ fileext CDATA #IMPLIED
+ totalproperty CDATA #IMPLIED
+ property CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ readbuffersize CDATA #IMPLIED
+ verifyproperty CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ algorithm CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ provider CDATA #IMPLIED
+ forceoverwrite %boolean; #IMPLIED>
+
+<!ELEMENT mail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT bcc EMPTY>
+<!ATTLIST bcc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT message (#PCDATA)>
+<!ATTLIST message
+ id ID #IMPLIED
+ mimetype CDATA #IMPLIED
+ src CDATA #IMPLIED
+ charset CDATA #IMPLIED>
+
+<!ELEMENT replyto EMPTY>
+<!ATTLIST replyto
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT cc EMPTY>
+<!ATTLIST cc
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT from EMPTY>
+<!ATTLIST from
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT to EMPTY>
+<!ATTLIST to
+ id ID #IMPLIED
+ address CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT loadfile (filterchain)*>
+<!ATTLIST loadfile
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ property CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT vsscheckout EMPTY>
+<!ATTLIST vsscheckout
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ getlocalcopy %boolean; #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT soscheckin EMPTY>
+<!ATTLIST soscheckin
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT mimemail (fileset | bcc | message | replyto | cc | from | to)*>
+<!ATTLIST mimemail
+ id ID #IMPLIED
+ cclist CDATA #IMPLIED
+ messagefile CDATA #IMPLIED
+ password CDATA #IMPLIED
+ encoding (auto | mime | uu | plain) #IMPLIED
+ charset CDATA #IMPLIED
+ files CDATA #IMPLIED
+ subject CDATA #IMPLIED
+ message CDATA #IMPLIED
+ ssl %boolean; #IMPLIED
+ tolist CDATA #IMPLIED
+ mailport CDATA #IMPLIED
+ messagemimetype CDATA #IMPLIED
+ bcclist CDATA #IMPLIED
+ from CDATA #IMPLIED
+ description CDATA #IMPLIED
+ replyto CDATA #IMPLIED
+ mailhost CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ includefilenames %boolean; #IMPLIED
+ user CDATA #IMPLIED>
+
+<!ELEMENT gunzip EMPTY>
+<!ATTLIST gunzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT concat (#PCDATA | filterchain | fileset | filelist | path | footer | header)*>
+<!ATTLIST concat
+ id ID #IMPLIED
+ force %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ binary %boolean; #IMPLIED
+ eol (asis | cr | lf | crlf | mac | unix | dos) #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ fixlastline %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT cab (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST cab
+ id ID #IMPLIED
+ cabfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ options CDATA #IMPLIED>
+
+<!ELEMENT touch (fileset | filelist | mapper)*>
+<!ATTLIST touch
+ id ID #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ mkdirs %boolean; #IMPLIED
+ millis CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ pattern CDATA #IMPLIED
+ datetime CDATA #IMPLIED>
+
+<!ELEMENT parallel (%tasks; | daemons)*>
+<!ATTLIST parallel
+ id ID #IMPLIED
+ pollinterval CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ threadsperprocessor CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ threadcount CDATA #IMPLIED
+ failonany %boolean; #IMPLIED>
+
+<!ELEMENT daemons (%tasks;)*>
+<!ATTLIST daemons
+ id ID #IMPLIED>
+
+<!ELEMENT antcall (reference | propertyset | target | param)*>
+<!ATTLIST antcall
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ inheritall %boolean; #IMPLIED
+ inheritrefs %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ target CDATA #IMPLIED>
+
+<!ELEMENT ccmkbl EMPTY>
+<!ATTLIST ccmkbl
+ id ID #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nlabel %boolean; #IMPLIED
+ full %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ identical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ baselinerootname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT cccheckout EMPTY>
+<!ATTLIST cccheckout
+ id ID #IMPLIED
+ reserved %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ out CDATA #IMPLIED
+ notco %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ nodata %boolean; #IMPLIED
+ version %boolean; #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT typedef (classpath)*>
+<!ATTLIST typedef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT xmlproperty (xmlcatalog)*>
+<!ATTLIST xmlproperty
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ semanticattributes %boolean; #IMPLIED
+ keeproot %boolean; #IMPLIED
+ prefix CDATA #IMPLIED
+ collapseattributes %boolean; #IMPLIED
+ validate %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ rootdirectory CDATA #IMPLIED
+ includesemanticattribute %boolean; #IMPLIED>
+
+<!ELEMENT import EMPTY>
+<!ATTLIST import
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ optional %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT copy (filterchain | fileset | filterset | mapper)*>
+<!ATTLIST copy
+ id ID #IMPLIED
+ flatten %boolean; #IMPLIED
+ tofile CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ file CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ overwrite %boolean; #IMPLIED
+ enablemultiplemappings %boolean; #IMPLIED
+ granularity CDATA #IMPLIED
+ outputencoding CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ preservelastmodified %boolean; #IMPLIED
+ filtering %boolean; #IMPLIED>
+
+<!ELEMENT jsharpc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST jsharpc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ baseaddress CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ securescoping %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ purejava %boolean; #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT symlink (fileset)*>
+<!ATTLIST symlink
+ id ID #IMPLIED
+ linkfilename CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ link CDATA #IMPLIED
+ action CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT antstructure EMPTY>
+<!ATTLIST antstructure
+ id ID #IMPLIED
+ output CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED
+ language CDATA #IMPLIED>
+
+<!ELEMENT ccmcreatetask EMPTY>
+<!ATTLIST ccmcreatetask
+ id ID #IMPLIED
+ subsystem CDATA #IMPLIED
+ task CDATA #IMPLIED
+ platform CDATA #IMPLIED
+ resolver CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ ccmaction CDATA #IMPLIED
+ ccmdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ release CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT rpm EMPTY>
+<!ATTLIST rpm
+ id ID #IMPLIED
+ removesource %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ cleanbuilddir %boolean; #IMPLIED
+ removespec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ specfile CDATA #IMPLIED
+ topdir CDATA #IMPLIED
+ rpmbuildcommand CDATA #IMPLIED>
+
+<!ELEMENT delete (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | fileset | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST delete
+ id ID #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ includeemptydirs %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ deleteonexit %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replace (patternset | exclude | include | custom | present | none | not | type | modified | replacefilter | or | contains | depend | replacetoken | different | size | majority | containsregexp | filename | selector | includesfile | replacevalue | date | excludesfile | depth | and)*>
+<!ATTLIST replace
+ id ID #IMPLIED
+ encoding CDATA #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ token CDATA #IMPLIED
+ propertyfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ summary %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ replacefilterfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT replacefilter EMPTY>
+<!ATTLIST replacefilter
+ id ID #IMPLIED
+ token CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT replacetoken (#PCDATA)>
+<!ATTLIST replacetoken
+ id ID #IMPLIED>
+
+<!ELEMENT replacevalue (#PCDATA)>
+<!ATTLIST replacevalue
+ id ID #IMPLIED>
+
+<!ELEMENT mmetrics (fileset | jvmarg | classpath | path | sourcepath)*>
+<!ATTLIST mmetrics
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED
+ maxmemory CDATA #IMPLIED
+ home CDATA #IMPLIED
+ granularity (compilation-units | files | methods | types | packages) #IMPLIED>
+
+<!ELEMENT attrib (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST attrib
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ readonly %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ hidden %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ system %boolean; #IMPLIED
+ outputproperty CDATA #IMPLIED
+ archive %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT waitfor (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST waitfor
+ id ID #IMPLIED
+ checkeveryunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ checkevery CDATA #IMPLIED
+ maxwaitunit (millisecond | second | minute | hour | day | week) #IMPLIED
+ maxwait CDATA #IMPLIED
+ timeoutproperty CDATA #IMPLIED>
+
+<!ELEMENT isfalse EMPTY>
+<!ATTLIST isfalse
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isreference EMPTY>
+<!ATTLIST isreference
+ id ID #IMPLIED
+ type CDATA #IMPLIED
+ refid IDREF #IMPLIED>
+
+<!ELEMENT equals EMPTY>
+<!ATTLIST equals
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ arg2 CDATA #IMPLIED
+ arg1 CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED>
+
+<!ELEMENT available (classpath | filepath)*>
+<!ATTLIST available
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ ignoresystemclasses %boolean; #IMPLIED
+ type (file | dir) #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ value CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ filepath CDATA #IMPLIED>
+
+<!ELEMENT filepath (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST filepath
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT os EMPTY>
+<!ATTLIST os
+ id ID #IMPLIED
+ version CDATA #IMPLIED
+ name CDATA #IMPLIED
+ family CDATA #IMPLIED
+ arch CDATA #IMPLIED>
+
+<!ELEMENT filesmatch EMPTY>
+<!ATTLIST filesmatch
+ id ID #IMPLIED
+ file2 CDATA #IMPLIED
+ file1 CDATA #IMPLIED>
+
+<!ELEMENT istrue EMPTY>
+<!ATTLIST istrue
+ id ID #IMPLIED
+ value %boolean; #IMPLIED>
+
+<!ELEMENT isset EMPTY>
+<!ATTLIST isset
+ id ID #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT socket EMPTY>
+<!ATTLIST socket
+ id ID #IMPLIED
+ port CDATA #IMPLIED
+ server CDATA #IMPLIED>
+
+<!ELEMENT http EMPTY>
+<!ATTLIST http
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ errorsbeginat CDATA #IMPLIED>
+
+<!ELEMENT uptodate (srcfiles | mapper)*>
+<!ATTLIST uptodate
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ targetfile CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT srcfiles (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST srcfiles
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ file CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT untar (fileset | patternset)*>
+<!ATTLIST untar
+ id ID #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT loadproperties (filterchain | classpath)*>
+<!ATTLIST loadproperties
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ srcfile CDATA #IMPLIED>
+
+<!ELEMENT echoproperties (propertyset)*>
+<!ATTLIST echoproperties
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ format (xml | text) #IMPLIED
+ srcfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT junit (classpath | sysproperty | bootclasspath | syspropertyset | env | test | permissions | jvmarg | formatter | batchtest | assertions)*>
+<!ATTLIST junit
+ id ID #IMPLIED
+ fork %boolean; #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ printsummary (true | yes | false | no | on | off | withOutAndErr) #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ failureproperty CDATA #IMPLIED
+ showoutput %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ tempdir CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ forkmode (once | perTest | perBatch) #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ reloading %boolean; #IMPLIED>
+
+<!ELEMENT formatter EMPTY>
+<!ATTLIST formatter
+ id ID #IMPLIED
+ usefile %boolean; #IMPLIED
+ type (plain | xml | brief) #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT batchtest (fileset | formatter)*>
+<!ATTLIST batchtest
+ id ID #IMPLIED
+ if CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ haltonerror %boolean; #IMPLIED
+ fork %boolean; #IMPLIED
+ todir CDATA #IMPLIED
+ failureproperty CDATA #IMPLIED
+ filtertrace %boolean; #IMPLIED
+ haltonfailure %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED>
+
+<!ELEMENT chgrp (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST chgrp
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ group CDATA #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT bunzip2 EMPTY>
+<!ATTLIST bunzip2
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT whichresource (classpath)*>
+<!ATTLIST whichresource
+ id ID #IMPLIED
+ classpath CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ class CDATA #IMPLIED
+ property CDATA #IMPLIED>
+
+<!ELEMENT copyfile EMPTY>
+<!ATTLIST copyfile
+ id ID #IMPLIED
+ forceoverwrite %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ filtering CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vsscreate EMPTY>
+<!ATTLIST vsscreate
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT macrodef (sequential | element | attribute | text)*>
+<!ATTLIST macrodef
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED
+ uri CDATA #IMPLIED>
+
+<!ELEMENT element EMPTY>
+<!ATTLIST element
+ id ID #IMPLIED
+ implicit %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT text EMPTY>
+<!ATTLIST text
+ id ID #IMPLIED
+ trim %boolean; #IMPLIED
+ optional %boolean; #IMPLIED
+ name CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT unjar (fileset | patternset)*>
+<!ATTLIST unjar
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT vbc (patternset | exclude | include | custom | present | none | resource | define | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST vbc
+ id ID #IMPLIED
+ references CDATA #IMPLIED
+ useresponsefile %boolean; #IMPLIED
+ removeintchecks %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ mainclass CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ additionalmodules CDATA #IMPLIED
+ win32icon CDATA #IMPLIED
+ optionstrict %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ utf8output %boolean; #IMPLIED
+ includedefaultreferences %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ optimize %boolean; #IMPLIED
+ targettype (exe | library | module | winexe) #IMPLIED
+ destfile CDATA #IMPLIED
+ rootnamespace CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ win32res CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ optionexplicit %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ optioncompare CDATA #IMPLIED
+ imports CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ referencefiles CDATA #IMPLIED>
+
+<!ELEMENT wsdltodotnet EMPTY>
+<!ATTLIST wsdltodotnet
+ id ID #IMPLIED
+ url CDATA #IMPLIED
+ srcfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ server %boolean; #IMPLIED
+ namespace CDATA #IMPLIED
+ language CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT mkdir EMPTY>
+<!ATTLIST mkdir
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT condition (isfalse | isreference | equals | available | not | contains | os | or | and | filesmatch | checksum | istrue | isset | socket | http | uptodate)*>
+<!ATTLIST condition
+ id ID #IMPLIED
+ value CDATA #IMPLIED
+ property CDATA #IMPLIED
+ else CDATA #IMPLIED>
+
+<!ELEMENT cvs (commandline)*>
+<!ATTLIST cvs
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT tempfile EMPTY>
+<!ATTLIST tempfile
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT junitreport (report | fileset)*>
+<!ATTLIST junitreport
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ todir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tofile CDATA #IMPLIED>
+
+<!ELEMENT report EMPTY>
+<!ATTLIST report
+ id ID #IMPLIED
+ todir CDATA #IMPLIED
+ styledir CDATA #IMPLIED
+ format (frames | noframes) #IMPLIED
+ extension CDATA #IMPLIED>
+
+<!ELEMENT ccmkattr EMPTY>
+<!ATTLIST ccmkattr
+ id ID #IMPLIED
+ recurse %boolean; #IMPLIED
+ typevalue CDATA #IMPLIED
+ replace %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED>
+
+<!ELEMENT taskdef (classpath)*>
+<!ATTLIST taskdef
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ file CDATA #IMPLIED
+ classname CDATA #IMPLIED
+ resource CDATA #IMPLIED
+ adaptto CDATA #IMPLIED
+ onerror (fail | report | ignore) #IMPLIED
+ loaderref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ adapter CDATA #IMPLIED
+ format (properties | xml) #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT echo (#PCDATA)>
+<!ATTLIST echo
+ id ID #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ level (error | warning | info | verbose | debug) #IMPLIED>
+
+<!ELEMENT ccupdate EMPTY>
+<!ATTLIST ccupdate
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ rename %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ log CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ graphical %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ currenttime %boolean; #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT java (classpath | sysproperty | redirector | bootclasspath | syspropertyset | env | permissions | jvmarg | arg | assertions)*>
+<!ATTLIST java
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ jvmargs CDATA #IMPLIED
+ args CDATA #IMPLIED
+ fork %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ jar CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ jvm CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ jvmversion CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ classname CDATA #IMPLIED>
+
+<!ELEMENT renameext (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST renameext
+ id ID #IMPLIED
+ replace %boolean; #IMPLIED
+ toextension CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ fromextension CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT vsslabel EMPTY>
+<!ATTLIST vsslabel
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT basename EMPTY>
+<!ATTLIST basename
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ file CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ suffix CDATA #IMPLIED>
+
+<!ELEMENT javadoc2 (taglet | doclet | package | arg | link | doctitle | bottom | group | packageset | fileset | classpath | sourcepath | footer | source | bootclasspath | header | excludepackage | tag)*>
+<!ATTLIST javadoc2
+ id ID #IMPLIED
+ bottom CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ executable CDATA #IMPLIED
+ header CDATA #IMPLIED
+ link CDATA #IMPLIED
+ noindex %boolean; #IMPLIED
+ access (protected | public | package | private) #IMPLIED
+ doclet CDATA #IMPLIED
+ noqualifier CDATA #IMPLIED
+ public %boolean; #IMPLIED
+ author %boolean; #IMPLIED
+ footer CDATA #IMPLIED
+ docletpath CDATA #IMPLIED
+ package %boolean; #IMPLIED
+ useexternalfile %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ protected %boolean; #IMPLIED
+ breakiterator %boolean; #IMPLIED
+ nonavbar %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ group CDATA #IMPLIED
+ source CDATA #IMPLIED
+ linkoffline CDATA #IMPLIED
+ additionalparam CDATA #IMPLIED
+ linksource %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ locale CDATA #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ includenosourcepackages %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ private %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ charset CDATA #IMPLIED
+ nodeprecatedlist %boolean; #IMPLIED
+ classpathref IDREF #IMPLIED
+ stylesheetfile CDATA #IMPLIED
+ docencoding CDATA #IMPLIED
+ excludepackagenames CDATA #IMPLIED
+ docletpathref IDREF #IMPLIED
+ packagenames CDATA #IMPLIED
+ windowtitle CDATA #IMPLIED
+ notree %boolean; #IMPLIED
+ splitindex %boolean; #IMPLIED
+ packagelist CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ doctitle CDATA #IMPLIED
+ serialwarn %boolean; #IMPLIED
+ old %boolean; #IMPLIED
+ use %boolean; #IMPLIED
+ sourcepath CDATA #IMPLIED
+ helpfile CDATA #IMPLIED
+ version %boolean; #IMPLIED
+ sourcefiles CDATA #IMPLIED
+ extdirs CDATA #IMPLIED
+ nohelp %boolean; #IMPLIED
+ nodeprecated %boolean; #IMPLIED
+ overview CDATA #IMPLIED>
+
+<!ELEMENT vsscp EMPTY>
+<!ATTLIST vsscp
+ id ID #IMPLIED
+ login CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ vsspath CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ ssdir CDATA #IMPLIED
+ autoresponse CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT tar (patternset | exclude | include | custom | tarfileset | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tar
+ id ID #IMPLIED
+ tarfile CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ basedir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compression (none | gzip | bzip2) #IMPLIED
+ longfile (warn | fail | truncate | gnu | omit) #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT tarfileset (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST tarfileset
+ id ID #IMPLIED
+ excludes CDATA #IMPLIED
+ preserveleadingslashes %boolean; #IMPLIED
+ username CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ uid CDATA #IMPLIED
+ fullpath CDATA #IMPLIED
+ group CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ refid IDREF #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ mode CDATA #IMPLIED
+ gid CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ prefix CDATA #IMPLIED
+ dirmode CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED>
+
+<!ELEMENT setproxy EMPTY>
+<!ATTLIST setproxy
+ id ID #IMPLIED
+ nonproxyhosts CDATA #IMPLIED
+ proxyhost CDATA #IMPLIED
+ socksproxyhost CDATA #IMPLIED
+ proxyport CDATA #IMPLIED
+ socksproxyport CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ proxyuser CDATA #IMPLIED
+ description CDATA #IMPLIED
+ proxypassword CDATA #IMPLIED>
+
+<!ELEMENT ilasm (patternset | exclude | include | custom | present | none | not | type | modified | reference | src | or | contains | depend | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | depth | and)*>
+<!ATTLIST ilasm
+ id ID #IMPLIED
+ owner CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ extraoptions CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ targettype (exe | library) #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ debug %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ outputfile CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resourcefile CDATA #IMPLIED
+ srcdir CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ listing %boolean; #IMPLIED
+ keyfile CDATA #IMPLIED>
+
+<!ELEMENT soscheckout EMPTY>
+<!ATTLIST soscheckout
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ file CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT apply (mapper | srcfile | targetfile | redirector | filelist | env | fileset | dirset | arg)*>
+<!ATTLIST apply
+ id ID #IMPLIED
+ resultproperty CDATA #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ type (file | dir | both) #IMPLIED
+ maxparallel CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ os CDATA #IMPLIED
+ errorproperty CDATA #IMPLIED
+ output CDATA #IMPLIED
+ timeout CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ spawn %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ inputstring CDATA #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ searchpath %boolean; #IMPLIED
+ logerror %boolean; #IMPLIED
+ dir CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED>
+
+<!ELEMENT ccuncheckout EMPTY>
+<!ATTLIST ccuncheckout
+ id ID #IMPLIED
+ objselect CDATA #IMPLIED
+ keepcopy %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED>
+
+<!ELEMENT jarlib-resolve (ant | location | url | extension)*>
+<!ATTLIST jarlib-resolve
+ id ID #IMPLIED
+ checkextension %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ property CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED>
+
+<!ELEMENT location EMPTY>
+<!ATTLIST location
+ id ID #IMPLIED
+ location CDATA #IMPLIED>
+
+<!ELEMENT url EMPTY>
+<!ATTLIST url
+ id ID #IMPLIED
+ destdir CDATA #IMPLIED
+ url CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT cvstagdiff (commandline)*>
+<!ATTLIST cvstagdiff
+ id ID #IMPLIED
+ cvsrsh CDATA #IMPLIED
+ endtag CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ passfile CDATA #IMPLIED
+ command CDATA #IMPLIED
+ package CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ reallyquiet %boolean; #IMPLIED
+ starttag CDATA #IMPLIED
+ output CDATA #IMPLIED
+ port CDATA #IMPLIED
+ compressionlevel CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ destfile CDATA #IMPLIED
+ enddate CDATA #IMPLIED
+ noexec %boolean; #IMPLIED
+ error CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ date CDATA #IMPLIED
+ startdate CDATA #IMPLIED
+ compression %boolean; #IMPLIED
+ tag CDATA #IMPLIED>
+
+<!ELEMENT jlink (patternset | exclude | include | custom | present | none | not | type | modified | or | contains | depend | mergefiles | different | size | majority | containsregexp | filename | selector | includesfile | date | excludesfile | addfiles | depth | and)*>
+<!ATTLIST jlink
+ id ID #IMPLIED
+ outfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ addfiles CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ mergefiles CDATA #IMPLIED
+ includes CDATA #IMPLIED>
+
+<!ELEMENT mergefiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST mergefiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT addfiles (fileset | dirset | extdirs | existing | filelist | pathelement | path)*>
+<!ATTLIST addfiles
+ id ID #IMPLIED
+ location CDATA #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED
+ path CDATA #IMPLIED>
+
+<!ELEMENT javacc EMPTY>
+<!ATTLIST javacc
+ id ID #IMPLIED
+ debugparser %boolean; #IMPLIED
+ javacchome CDATA #IMPLIED
+ forcelacheck %boolean; #IMPLIED
+ optimizetokenmanager %boolean; #IMPLIED
+ commontokenaction %boolean; #IMPLIED
+ buildtokenmanager %boolean; #IMPLIED
+ sanitycheck %boolean; #IMPLIED
+ buildparser %boolean; #IMPLIED
+ otherambiguitycheck CDATA #IMPLIED
+ lookahead CDATA #IMPLIED
+ debuglookahead %boolean; #IMPLIED
+ choiceambiguitycheck CDATA #IMPLIED
+ unicodeinput %boolean; #IMPLIED
+ usercharstream %boolean; #IMPLIED
+ debugtokenmanager %boolean; #IMPLIED
+ keeplinecolumn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ outputdirectory CDATA #IMPLIED
+ cachetokens %boolean; #IMPLIED
+ javaunicodeescape %boolean; #IMPLIED
+ static %boolean; #IMPLIED
+ target CDATA #IMPLIED
+ ignorecase %boolean; #IMPLIED
+ usertokenmanager %boolean; #IMPLIED
+ errorreporting %boolean; #IMPLIED>
+
+<!ELEMENT chmod (mapper | include | srcfile | exclude | targetfile | patternset | redirector | env | filelist | fileset | dirset | arg)*>
+<!ATTLIST chmod
+ id ID #IMPLIED
+ addsourcefile %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ parallel %boolean; #IMPLIED
+ input CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ force %boolean; #IMPLIED
+ inputstring CDATA #IMPLIED
+ searchpath %boolean; #IMPLIED
+ relative %boolean; #IMPLIED
+ skipemptyfilesets %boolean; #IMPLIED
+ command CDATA #IMPLIED
+ forwardslash %boolean; #IMPLIED
+ spawn %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ includes CDATA #IMPLIED
+ vmlauncher %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ logerror %boolean; #IMPLIED
+ errorproperty CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ output CDATA #IMPLIED
+ error CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ os CDATA #IMPLIED
+ dest CDATA #IMPLIED
+ resolveexecutable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ resultproperty CDATA #IMPLIED
+ ignoremissing %boolean; #IMPLIED
+ failifexecutionfails %boolean; #IMPLIED
+ append %boolean; #IMPLIED
+ timeout CDATA #IMPLIED
+ maxparallel CDATA #IMPLIED
+ outputproperty CDATA #IMPLIED
+ perm CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ newenvironment %boolean; #IMPLIED
+ type (file | dir | both) #IMPLIED>
+
+<!ELEMENT pvcs (pvcsproject)*>
+<!ATTLIST pvcs
+ id ID #IMPLIED
+ updateonly %boolean; #IMPLIED
+ force CDATA #IMPLIED
+ config CDATA #IMPLIED
+ pvcsbin CDATA #IMPLIED
+ workspace CDATA #IMPLIED
+ pvcsproject CDATA #IMPLIED
+ filenameformat CDATA #IMPLIED
+ userid CDATA #IMPLIED
+ repository CDATA #IMPLIED
+ ignorereturncode %boolean; #IMPLIED
+ revision CDATA #IMPLIED
+ linestart CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ promotiongroup CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT pvcsproject EMPTY>
+<!ATTLIST pvcsproject
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT jarlib-manifest (options | attribute | depends | extension)*>
+<!ATTLIST jarlib-manifest
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ destfile CDATA #IMPLIED>
+
+<!ELEMENT options (fileset | libfileset | extension)*>
+<!ATTLIST options
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT depends (fileset | libfileset | extension)*>
+<!ATTLIST depends
+ id ID #IMPLIED
+ refid IDREF #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT jar (patternset | exclude | include | custom | present | none | not | manifest | type | metainf | modified | or | contains | depend | fileset | different | size | majority | containsregexp | indexjars | filename | selector | includesfile | zipgroupfileset | zipfileset | date | excludesfile | depth | and)*>
+<!ATTLIST jar
+ id ID #IMPLIED
+ whenempty (fail | skip | create) #IMPLIED
+ keepcompression %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ duplicate (add | preserve | fail) #IMPLIED
+ roundup %boolean; #IMPLIED
+ excludes CDATA #IMPLIED
+ basedir CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ manifest CDATA #IMPLIED
+ jarfile CDATA #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ index %boolean; #IMPLIED
+ update %boolean; #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ destfile CDATA #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ description CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ compress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ manifestencoding CDATA #IMPLIED
+ filesonly %boolean; #IMPLIED
+ file CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ filesetmanifest (skip | merge | mergewithoutmain) #IMPLIED
+ zipfile CDATA #IMPLIED>
+
+<!ELEMENT ccmklbtype EMPTY>
+<!ATTLIST ccmklbtype
+ id ID #IMPLIED
+ global %boolean; #IMPLIED
+ replace %boolean; #IMPLIED
+ shared %boolean; #IMPLIED
+ viewpath CDATA #IMPLIED
+ typename CDATA #IMPLIED
+ pbranch %boolean; #IMPLIED
+ comment CDATA #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ vob CDATA #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ ordinary %boolean; #IMPLIED>
+
+<!ELEMENT scriptdef (#PCDATA | classpath | element | attribute)*>
+<!ATTLIST scriptdef
+ id ID #IMPLIED
+ src CDATA #IMPLIED
+ name CDATA #IMPLIED
+ uri CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ language CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ loaderref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ reverseloader %boolean; #IMPLIED>
+
+<!ELEMENT defaultexcludes EMPTY>
+<!ATTLIST defaultexcludes
+ id ID #IMPLIED
+ remove CDATA #IMPLIED
+ echo %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ default %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ add CDATA #IMPLIED>
+
+<!ELEMENT mparse (fileset | jvmarg | classpath | sourcepath)*>
+<!ATTLIST mparse
+ id ID #IMPLIED
+ cleanup %boolean; #IMPLIED
+ verbose %boolean; #IMPLIED
+ maxmemory CDATA #IMPLIED
+ metamatahome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ debugparser %boolean; #IMPLIED
+ home CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ debugscanner %boolean; #IMPLIED>
+
+<!ELEMENT blgenclient (classpath)*>
+<!ATTLIST blgenclient
+ id ID #IMPLIED
+ debug %boolean; #IMPLIED
+ classpath CDATA #IMPLIED
+ mode CDATA #IMPLIED
+ ejbjar CDATA #IMPLIED
+ version CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ clientjar CDATA #IMPLIED>
+
+<!ELEMENT jjdoc EMPTY>
+<!ATTLIST jjdoc
+ id ID #IMPLIED
+ outputfile CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ javacchome CDATA #IMPLIED
+ target CDATA #IMPLIED
+ text %boolean; #IMPLIED
+ onetable %boolean; #IMPLIED>
+
+<!ELEMENT genkey (dname)*>
+<!ATTLIST genkey
+ id ID #IMPLIED
+ storepass CDATA #IMPLIED
+ sigalg CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ keypass CDATA #IMPLIED
+ dname CDATA #IMPLIED
+ keysize CDATA #IMPLIED
+ alias CDATA #IMPLIED
+ keyalg CDATA #IMPLIED
+ validity CDATA #IMPLIED
+ keystore CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ storetype CDATA #IMPLIED>
+
+<!ELEMENT dname (param)*>
+<!ATTLIST dname
+ id ID #IMPLIED>
+
+<!ELEMENT javah (arg | classpath | class | bootclasspath)*>
+<!ATTLIST javah
+ id ID #IMPLIED
+ stubs %boolean; #IMPLIED
+ force %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ old %boolean; #IMPLIED
+ outputfile CDATA #IMPLIED
+ implementation CDATA #IMPLIED
+ class CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ classpathref IDREF #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ id ID #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT ccmkelem EMPTY>
+<!ATTLIST ccmkelem
+ id ID #IMPLIED
+ preservetime %boolean; #IMPLIED
+ master %boolean; #IMPLIED
+ eltype CDATA #IMPLIED
+ viewpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ failonerr %boolean; #IMPLIED
+ objselect CDATA #IMPLIED
+ cleartooldir CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ nocheckout %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ commentfile CDATA #IMPLIED
+ checkin %boolean; #IMPLIED>
+
+<!ELEMENT ccmreconfigure EMPTY>
+<!ATTLIST ccmreconfigure
+ id ID #IMPLIED
+ ccmaction CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ ccmproject CDATA #IMPLIED
+ description CDATA #IMPLIED
+ recurse %boolean; #IMPLIED
+ ccmdir CDATA #IMPLIED>
+
+<!ELEMENT fail (#PCDATA | condition)*>
+<!ATTLIST fail
+ id ID #IMPLIED
+ status CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ description CDATA #IMPLIED
+ message CDATA #IMPLIED
+ unless CDATA #IMPLIED
+ if CDATA #IMPLIED>
+
+<!ELEMENT unzip (fileset | patternset)*>
+<!ATTLIST unzip
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ overwrite %boolean; #IMPLIED
+ dest CDATA #IMPLIED
+ description CDATA #IMPLIED
+ encoding CDATA #IMPLIED
+ src CDATA #IMPLIED>
+
+<!ELEMENT javac (patternset | exclude | include | custom | present | none | extdirs | not | type | modified | src | or | contains | depend | classpath | sourcepath | different | size | majority | containsregexp | bootclasspath | filename | selector | includesfile | compilerarg | date | excludesfile | depth | and)*>
+<!ATTLIST javac
+ id ID #IMPLIED
+ target CDATA #IMPLIED
+ excludes CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ bootclasspathref IDREF #IMPLIED
+ compiler CDATA #IMPLIED
+ executable CDATA #IMPLIED
+ debuglevel CDATA #IMPLIED
+ memoryinitialsize CDATA #IMPLIED
+ deprecation %boolean; #IMPLIED
+ includeantruntime %boolean; #IMPLIED
+ description CDATA #IMPLIED
+ sourcepathref IDREF #IMPLIED
+ depend %boolean; #IMPLIED
+ includes CDATA #IMPLIED
+ source CDATA #IMPLIED
+ includejavaruntime %boolean; #IMPLIED
+ failonerror %boolean; #IMPLIED
+ destdir CDATA #IMPLIED
+ debug %boolean; #IMPLIED
+ tempdir CDATA #IMPLIED
+ classpath CDATA #IMPLIED
+ followsymlinks %boolean; #IMPLIED
+ casesensitive %boolean; #IMPLIED
+ defaultexcludes %boolean; #IMPLIED
+ bootclasspath CDATA #IMPLIED
+ includesfile CDATA #IMPLIED
+ nowarn %boolean; #IMPLIED
+ proceed %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ classpathref IDREF #IMPLIED
+ fork %boolean; #IMPLIED
+ srcdir CDATA #IMPLIED
+ memorymaximumsize CDATA #IMPLIED
+ optimize %boolean; #IMPLIED
+ encoding CDATA #IMPLIED
+ excludesfile CDATA #IMPLIED
+ sourcepath CDATA #IMPLIED
+ listfiles %boolean; #IMPLIED
+ extdirs CDATA #IMPLIED>
+
+<!ELEMENT jpcoverage (arg | socket | fileset | jvmarg | classpath | triggers | filters)*>
+<!ATTLIST jpcoverage
+ id ID #IMPLIED
+ applet %boolean; #IMPLIED
+ recordfromstart (coverage | none | all) #IMPLIED
+ vm (java2 | jdk118 | jdk117) #IMPLIED
+ classname CDATA #IMPLIED
+ workingdir CDATA #IMPLIED
+ inputfile CDATA #IMPLIED
+ snapshotdir CDATA #IMPLIED
+ seedname CDATA #IMPLIED
+ javaexe CDATA #IMPLIED
+ home CDATA #IMPLIED
+ exitprompt CDATA #IMPLIED
+ taskname CDATA #IMPLIED
+ warnlevel CDATA #IMPLIED
+ finalsnapshot CDATA #IMPLIED
+ description CDATA #IMPLIED
+ tracknatives %boolean; #IMPLIED>
+
+<!ELEMENT triggers (method)*>
+<!ATTLIST triggers
+ id ID #IMPLIED>
+
+<!ELEMENT method EMPTY>
+<!ATTLIST method
+ id ID #IMPLIED
+ name CDATA #IMPLIED
+ event CDATA #IMPLIED
+ action CDATA #IMPLIED
+ param CDATA #IMPLIED>
+
+<!ELEMENT filters (include | exclude)*>
+<!ATTLIST filters
+ id ID #IMPLIED
+ defaultexclude %boolean; #IMPLIED>
+
+<!ELEMENT soslabel EMPTY>
+<!ATTLIST soslabel
+ id ID #IMPLIED
+ soshome CDATA #IMPLIED
+ verbose %boolean; #IMPLIED
+ vssserverpath CDATA #IMPLIED
+ username CDATA #IMPLIED
+ sosserverpath CDATA #IMPLIED
+ comment CDATA #IMPLIED
+ projectpath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ nocache %boolean; #IMPLIED
+ nocompress %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ localpath CDATA #IMPLIED
+ soscmd CDATA #IMPLIED
+ password CDATA #IMPLIED>
+
+<!ELEMENT vssget EMPTY>
+<!ATTLIST vssget
+ id ID #IMPLIED
+ ssdir CDATA #IMPLIED
+ date CDATA #IMPLIED
+ recursive %boolean; #IMPLIED
+ autoresponse CDATA #IMPLIED
+ quiet %boolean; #IMPLIED
+ vsspath CDATA #IMPLIED
+ version CDATA #IMPLIED
+ serverpath CDATA #IMPLIED
+ login CDATA #IMPLIED
+ filetimestamp (current | modified | updated) #IMPLIED
+ writable %boolean; #IMPLIED
+ taskname CDATA #IMPLIED
+ label CDATA #IMPLIED
+ description CDATA #IMPLIED
+ failonerror %boolean; #IMPLIED
+ localpath CDATA #IMPLIED
+ writablefiles (replace | skip | fail) #IMPLIED>
+
+<!ELEMENT deltree EMPTY>
+<!ATTLIST deltree
+ id ID #IMPLIED
+ taskname CDATA #IMPLIED
+ dir CDATA #IMPLIED
+ description CDATA #IMPLIED>
+
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/config.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/config.xml
new file mode 100644
index 0000000..873add3
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/config.xml
@@ -0,0 +1,6 @@
+<config
+ host="${host}"
+ port="${port}"
+ basepath="${basepath}"
+ protocol="http"/>
+
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-open.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-open.xml
new file mode 100644
index 0000000..74fbac7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-open.xml
@@ -0,0 +1,5 @@
+&welcome-open;
+<clickLink
+ description="Click Register"
+ label="Register with MailReader"/>
+ ®ister-page;
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-page.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-page.xml
new file mode 100644
index 0000000..54601e9
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-page.xml
@@ -0,0 +1,3 @@
+<verifyTitle
+ description="Registration page title"
+ text="MailReader - Register"/>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-trillian.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-trillian.xml
new file mode 100644
index 0000000..7561f05
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/register-trillian.xml
@@ -0,0 +1,21 @@
+<setInputField
+ description="username"
+ name="username"
+ value="trillian"/>
+<setInputField
+ description="password"
+ name="password"
+ value="astra"/>
+<setInputField
+ description="password2"
+ name="password2"
+ value="astra"/>
+<setInputField
+ description="fullName"
+ name="fullName"
+ value="Tricia McMillian"/>
+<setInputField
+ description="fromAddress"
+ name="fromAddress"
+ value="tricia@magrathea.com"/>
+ &save-click;
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/save-click.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/save-click.xml
new file mode 100644
index 0000000..a02a1db
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/save-click.xml
@@ -0,0 +1,3 @@
+<clickButton
+ description="Save"
+ name="Save"/>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/taskdef.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/taskdef.xml
new file mode 100644
index 0000000..fb4c1dd
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/taskdef.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" ?>
+<project name="taskdef">
+ <description>
+ This project provides following elements to use in your test scripts:
+
+ (0) all webtest's steps loaded and ready to use,
+ (1) the path "webtest.path.id" that includes all of webtest's
+ libraries,
+ (2) the class loader "webtest.loader" that is the original loader for
+ webtest.
+
+ Usage:
+ Set the property webtest.home to the directory in which the build.zip
+ is extracted,
+ and calls:
+ <import file="${webtest.home}/lib/taskdef.xml" >
+ </description>
+
+ <import file="${webtest.home}/lib/classpath.xml"/>
+
+ <taskdef resource="webtest.taskdef"
+ loaderref="webtest.loader"
+ classpathref="webtest.path.id"
+ />
+</project>
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/welcome-open.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/welcome-open.xml
new file mode 100644
index 0000000..a073531
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/entities/welcome-open.xml
@@ -0,0 +1,6 @@
+<invoke
+ description="Open welcome action"
+ url="Welcome.do"/>
+<verifyTitle
+ description="Welcome page title"
+ text="MailReader"/>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..f1445ec
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>struts-cleanup</filter-name>
+ <filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
+ </filter>
+ <filter>
+ <filter-name>sitemesh</filter-name>
+ <filter-class>org.apache.struts2.sitemesh.FreeMarkerPageFilter</filter-class>
+ </filter>
+ <filter>
+ <filter-name>struts2</filter-name>
+ <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>struts-cleanup</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>sitemesh</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ DatabaseListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/webtest.properties.sample b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/webtest.properties.sample
new file mode 100644
index 0000000..aa6975a
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/webtest.properties.sample
@@ -0,0 +1,15 @@
+# -----------------------------------------------------------------------------
+# webtest.properties.sample
+#
+# This is an example "webtest.properties" file, used to customize building Struts
+# for your local environment. Make any changes you need, and rename this file
+# to "webtest.properties" in the same directory that contains the Struts
+# "webtest.xml" file.
+# -----------------------------------------------------------------------------
+webtest.home = /opt/Canoo/webtest-1.7
+host = localhost
+port = 8080
+basepath = lab-2-2
+webapps.home = /opt/Apache/Tomcat-5.5/webapps/
+resource.home = ${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"
+# mailreader.home =
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/webtest.xml b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/webtest.xml
new file mode 100644
index 0000000..4f34768
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/WEB-INF/webtest.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "entities/WebTest.dtd" [
+
+ <!ENTITY taskdef-webtest SYSTEM "entities/taskdef.xml">
+ <!ENTITY config SYSTEM "entities/config.xml">
+
+ <!ENTITY register-open SYSTEM "file:./entities/register-open.xml">
+ <!ENTITY register-page SYSTEM "file:./entities/register-page.xml">
+ <!ENTITY register-trillian SYSTEM "file:./entities/register-trillian.xml">
+
+ <!ENTITY save-click SYSTEM "file:./entities/save-click.xml">
+
+ <!ENTITY welcome-open SYSTEM "file:./entities/welcome-open.xml">
+
+ ]>
+
+<project name="MailReader Training Course - Exercise navigation and database logic
+- Canoo WebTests" basedir="." default="clean">
+
+ <!--
+ Canoo WebTest configuration file to test navigating between pages and
+ creating and editing an account.
+
+ To run this test, first install the Canoo Webtest package on your
+ local system [http://webtest.canoo.com].
+
+ The default location for this build file is under
+ "/opt/Canoo/webtest-1.7".
+ See the webtest.properties.sample to use another location.
+
+ Once Canoo is installed, the webtest.xml file can be run as an Ant build
+ file (ant -f webtest.xml).
+
+ By default, the tests are configured to find the application under test
+ at "http://localhost:8080/lib-2-2".
+ See the webtest.properties.sample to use another location.
+
+ Deploy the application to your container, and use Ant to run the
+ webtest.xml.
+
+ The "clean" target can be run to test everything, but will fail if run again,
+ since the test-user will already be registered.
+ The "default" target skips registeration and can be run as often as needed
+ after "clean" is run once.
+
+ To reset the XML "database", either redeploy the application so that the
+ WEB-INF/classes/database.xml is overwritten,
+ or use the "clean-database" target to overwrite the file.
+ Only use "clean-database" when the server is stopped,
+ and then start it again before running other targets.
+
+ The tests are based on a set of MailReader Use Cases maintained at the
+ Struts University site
+ [http://opensource2.atlassian.com/confluence/oss/display/STRUTS/MailReader].
+ */
+ -->
+
+ <!-- Load local preferences, if any -->
+ <property file="webtest.properties"/>
+
+ <!-- These properties can be customized using via webtest.properties -->
+ <!-- See webtest.properties.sample for a starter file -->
+ <property name="webtest.home"
+ location="/opt/Canoo/webtest-1.7"/>
+
+ <property name="host"
+ value="localhost"/>
+
+ <property name="port"
+ value="8080"/>
+
+ <property name="basepath"
+ value="lab-2-2"/>
+
+ <property name="mailreader.home"
+ location="../../../"/>
+
+ <property name="webapps.home"
+ location="/opt/Apache/Tomcat-5.5/webapps"/>
+
+ <property file="${webapps.home}/${basepath}/WEB-INF/classes/resources.properties"/>
+
+
+ <taskdef file="${webtest.home}/webtestTaskdefs.properties">
+ <classpath>
+ <fileset dir="${webtest.home}" includes="**/lib/*.jar"/>
+ <fileset dir="${webtest.home}" includes="**/lib/runtime/*.jar"/>
+ </classpath>
+ </taskdef>
+
+ <target name="clean-database"
+ description="Sets database.xml to default. Stop server, run target, and Start server.">
+ <copy file="${mailreader.home}/src/java/database.xml"
+ tofile="${webapps.home}/${basepath}/WEB-INF/classes/database.xml"
+ overwrite="true"/>
+ </target>
+
+ <!-- ADD YOUR TARGETS HERE -->
+
+ <target name="clean" description="Only run against a clean database"
+ depends="Register"/>
+
+ <target name="Register"
+ description="Subscribers can store login credentials and a
+ primary email contact with the system.">
+
+ <webtest name="Register Trillian (MSS)">
+ &config;
+ <steps>
+ ®ister-open;
+ ®ister-trillian;
+ <verifyTitle
+ description="Menu page title"
+ text="MailReader - Menu"/>
+ </steps>
+ </webtest>
+
+ </target>
+
+</project>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/css/mailreader.css b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/css/mailreader.css
new file mode 100644
index 0000000..bfc7648
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/css/mailreader.css
@@ -0,0 +1,46 @@
+/**
+* Mailreader stylesheet
+*/
+
+body {
+ background-color: #FFFFFF;
+ color: #000000;
+ link: 000066;
+ visited: #660066;
+ active: #33CCCC;
+}
+
+A:hover {
+ color: #FF0000;
+}
+
+h1 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h5 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h6 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+font.hint {
+ font-style: italic;
+ font-size: 80%;
+ font-family: Arial, Helvetica, sans-serif;
+ text-align: left;
+}
\ No newline at end of file
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Error.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Error.jsp
new file mode 100644
index 0000000..d5558cf
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Error.jsp
@@ -0,0 +1,42 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Unexpected Error</title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h2>An unexpected error has occured</h2>
+
+<p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+</p>
+
+<hr/>
+
+<h3>Error Message</h3>
+
+<s:actionerror/>
+
+<p>
+ <s:property value="%{exception.message}"/>
+</p>
+
+<hr/>
+
+<h3>Technical Details</h3>
+
+<p>
+ <s:property value="%{exceptionStack}"/>
+</p>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Footer.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Footer.jsp
new file mode 100644
index 0000000..4afe5e4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Footer.jsp
@@ -0,0 +1,8 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<hr/>
+
+<p>
+ <a href="<s:url action="Welcome" />">
+ <s:text name="index.title"/>
+ </a>
+</p>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..231b166
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Hello.jsp
@@ -0,0 +1,16 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Login.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Login.jsp
new file mode 100644
index 0000000..97d89a0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Login.jsp
@@ -0,0 +1,27 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="login.title"/>
+ </title>
+</head>
+
+<body onLoad="self.focus();document.Login_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Login_save" validate="true">
+ <s:textfield key="username"/>
+
+ <s:password key="password" showPassword="true"/>
+
+ <s:submit key="button.save"/>
+
+ <s:submit action="Login_cancel" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Menu.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Menu.jsp
new file mode 100644
index 0000000..79302e8
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Menu.jsp
@@ -0,0 +1,30 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>
+ <s:text name="menu.title"/>
+ </title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h3>
+ <s:text name="menu.heading"/>
+ <s:property value="user.fullName"/>
+</h3>
+<ul>
+ <li><a href="<s:url action="Register!input" />">
+ <s:text name="menu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url action="Logout"/>">
+ <s:text name="menu.logout"/>
+ </a>
+</ul>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..eab03fc
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Missing.jsp
@@ -0,0 +1,16 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Missing Feature</title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Register.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Register.jsp
new file mode 100644
index 0000000..5bcc12e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Register.jsp
@@ -0,0 +1,126 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title>
+ <s:text name="registration.title.create"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title>
+ <s:text name="registration.title.edit"/>
+ </title>
+ </s:if>
+</head>
+
+<body onLoad="self.focus();document.Register_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Register_save" validate="true">
+ <s:hidden name="task"/>
+ <s:if test="task == 'Create'">
+ <s:textfield key="username"/>
+ </s:if>
+ <s:else>
+ <s:label key="username"/>
+ <s:hidden name="username"/>
+ </s:else>
+
+ <s:password key="password"/>
+
+ <s:password key="password2"/>
+
+ <s:textfield key="fullName"/>
+
+ <s:textfield key="fromAddress"/>
+
+ <s:textfield key="replyToAddress"/>
+
+ <s:if test="task == 'Create'">
+ <s:submit key="button.save" action="Register_create"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Welcome" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:if>
+ <s:else>
+ <s:submit key="button.save"/>
+
+ <s:reset key="button.reset"/>
+
+ <s:submit action="Menu" key="button.cancel"
+ onclick="form.onsubmit=null"/>
+ </s:else>
+
+</s:form>
+
+<s:if test="task == 'Edit'">
+ <div align="center">
+ <h3>
+ <s:text name="heading.subscriptions"/>
+ </h3>
+ </div>
+
+ <table border="1" width="100%">
+
+ <tr>
+ <th align="center" width="30%">
+ <s:text name="heading.host"/>
+ </th>
+ <th align="center" width="25%">
+ <s:text name="heading.user"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.type"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.autoConnect"/>
+ </th>
+ <th align="center" width="15%">
+ <s:text name="heading.action"/>
+ </th>
+ </tr>
+
+ <s:iterator value="user.subscriptions">
+ <tr>
+ <td align="left">
+ <s:property value="host"/>
+ </td>
+ <td align="left">
+ <s:property value="username"/>
+ </td>
+ <td align="center">
+ <s:property value="type"/>
+ </td>
+ <td align="center">
+ <s:property value="autoConnect"/>
+ </td>
+ <td align="center">
+
+ <a href="<s:url action="Subscribe_delete"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.deleteSubscription"/>
+ </a>
+
+ <a href="<s:url action="Subscribe_edit"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.editSubscription"/>
+ </a>
+
+ </td>
+ </tr>
+ </s:iterator>
+
+ </table>
+
+ <a href="<s:url action="Subscribe"/>">
+ <s:text
+ name="registration.addSubscription"/>
+ </a>
+
+</s:if>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Subscribe.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Subscribe.jsp
new file mode 100644
index 0000000..69f8b10
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Subscribe.jsp
@@ -0,0 +1,69 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title>
+ <s:text name="subscription.title.create"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title>
+ <s:text name="subscription.title.edit"/>
+ </title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title>
+ <s:text name="subscription.title.delete"/>
+ </title>
+ </s:if>
+</head>
+
+<body onLoad="self.focus();document.Subscribe_save.username.focus()">
+
+<s:actionerror/>
+<s:form action="Subscribe_save" validate="true">
+ <s:hidden name="task"/>
+ <s:label key="user.username"/>
+
+ <s:if test="task == 'Create'">
+ <s:textfield key="mailHostname" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label key="mailHostname" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label key="mailUsername"
+ name="subscription.username"/>
+ <s:label key="mailPassword"
+ name="subscription.password"/>
+ <s:label key="mailServerType"
+ name="subscription.type"/>
+ <s:label key="autoConnect"
+ name="subscription.autoConnect"/>
+ <s:submit key="button.confirm"/>
+ </s:if>
+ <s:else>
+ <s:textfield key="mailUsername"
+ name="subscription.username"/>
+ <s:textfield key="mailPassword"
+ name="subscription.password"/>
+ <s:select key="mailServerType"
+ name="subscription.type" list="types"/>
+ <s:checkbox key="autoConnect"
+ name="subscription.autoConnect"/>
+ <s:submit key="button.save"/>
+ <s:reset key="button.reset"/>
+ </s:else>
+
+ <s:submit action="Register"
+ key="button.cancel"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..5d42382
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,36 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>
+ <s:text name="index.title"/>
+ </title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Register!input"/>">
+ <s:text
+ name="index.registration"/>
+ </a></li>
+ <li><a href="<s:url action="Login!input"/>">
+ <s:text
+ name="index.login"/>
+ </a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li><a href="<s:url action="Welcome?request_locale=en"/>">English</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ja"/>">Japanese</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ru"/>">Russian</a></li>
+</ul>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/mailreader-course/struts2/theme/theme.iml b/struts-sandbox/mailreader-course/struts2/theme/theme.iml
new file mode 100644
index 0000000..e18cb11
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/theme/theme.iml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/theme/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/theme" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/struts2-sitemesh-plugin-2.0.3.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/sitemesh-2.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" name="Mailreader-dao" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntry type="library" name="servlet-api" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/theme" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" level="module">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib/sitemesh-2.2.jar" />
+ <url>jar://$MODULE_DIR$/../lib/sitemesh-2.2.jar!/</url>
+ </containerElement>
+ <containerElement type="library" level="module">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib/struts2-sitemesh-plugin-2.0.3.jar" />
+ <url>jar://$MODULE_DIR$/../lib/struts2-sitemesh-plugin-2.0.3.jar!/</url>
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Mailreader-dao" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <containerElement type="library" name="servlet-api" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/webtest.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/META-INF/context.xml b/struts-sandbox/mailreader-course/struts2/welcome/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/java/Hello.java b/struts-sandbox/mailreader-course/struts2/welcome/src/java/Hello.java
new file mode 100644
index 0000000..1b7dd9e
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/java/Hello.java
@@ -0,0 +1,16 @@
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example Action class.
+ */
+public class Hello extends ActionSupport {
+
+ /**
+ * An example implementation that does nothing and returns "success".
+ *
+ * @return {@link #SUCCESS} default result
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/java/resources.properties b/struts-sandbox/mailreader-course/struts2/welcome/src/java/resources.properties
new file mode 100644
index 0000000..9faaec7
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/java/resources.properties
@@ -0,0 +1,2 @@
+hello.message = Congratulations! Struts is up and running ...
+# Add your messages here ...
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/java/struts.xml b/struts-sandbox/mailreader-course/struts2/welcome/src/java/struts.xml
new file mode 100644
index 0000000..596b0f2
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/java/struts.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <constant name="struts.devMode" value="true"/>
+ <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="Missing"/>
+
+ <action name="Hello" class="Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <action name="Missing">
+ <result>/pages/Missing.jsp</result>
+ </action>
+
+ <action name="Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/test/HelloTest.java b/struts-sandbox/mailreader-course/struts2/welcome/src/test/HelloTest.java
new file mode 100644
index 0000000..60debf5
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/test/HelloTest.java
@@ -0,0 +1,16 @@
+import junit.framework.TestCase;
+
+/**
+ * An example text class to verify the configuration.
+ */
+public class HelloTest extends TestCase {
+
+ /**
+ * An example test that asserts true.
+ *
+ * @throws Exception On invalid assertions
+ */
+ public void testHelloAction() throws Exception {
+ assertTrue(true);
+ }
+}
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/WEB-INF/web.xml b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2f60f95
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/index.html b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Hello.jsp b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..1e9d87b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Hello.jsp
@@ -0,0 +1,12 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>Hello</title>
+</head>
+
+<body>
+<h2>
+ <s:text name="hello.message"/>
+</h2>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Missing.jsp b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Missing.jsp
new file mode 100644
index 0000000..d21b08b
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Missing.jsp
@@ -0,0 +1,10 @@
+<html>
+<head><title>Missing Feature</title></head>
+
+<body>
+<p>
+ This feature is under construction.
+ Please try again in the next interation.
+</p>
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Welcome.jsp b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..4e17f3c
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/src/webapp/pages/Welcome.jsp
@@ -0,0 +1,23 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+ <title>MailReader</title>
+</head>
+
+<body>
+<h3>MailReader Options</h3>
+
+<ul>
+ <li><a href="<s:url action="Missing"/>">Register with MailReader</a></li>
+ <li><a href="<s:url action="Missing"/>">Log into MailReader</a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li><a href="<s:url action="Missing"/>">English</a></li>
+ <li><a href="<s:url action="Missing"/>">Japanese</a></li>
+ <li><a href="<s:url action="Missing"/>">Russian</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/struts-sandbox/mailreader-course/struts2/welcome/welcome.iml b/struts-sandbox/mailreader-course/struts2/welcome/welcome.iml
new file mode 100644
index 0000000..faca0ba
--- /dev/null
+++ b/struts-sandbox/mailreader-course/struts2/welcome/welcome.iml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="J2EE_WEB_MODULE" j2ee-integration="Tomcat Server">
+ <component name="AppServerSpecificValidatorsManager" />
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/welcome/WEB-INF/classes" />
+ <exclude-output />
+ <exploded url="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/welcome" />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Struts2" level="project" />
+ <orderEntry type="library" name="junit" level="application" />
+ <orderEntryProperties />
+ </component>
+ <component name="WebModuleBuildComponent">
+ <setting name="EXPLODED_URL" value="file://$MODULE_DIR$/../../../../../../../opt/Apache/Tomcat-5.5/webapps/welcome" />
+ <setting name="EXPLODED_ENABLED" value="true" />
+ <setting name="JAR_URL" value="file://" />
+ <setting name="JAR_ENABLED" value="false" />
+ <setting name="SYNC_EXPLODED_DIR" value="true" />
+ <setting name="BUILD_MODULE_ON_FRAME_DEACTIVATION" value="false" />
+ <setting name="BUILD_EXTERNAL_DEPENDENCIES" value="false" />
+ <setting name="RUN_JASPER_VALIDATION" value="false" />
+ </component>
+ <component name="WebModuleProperties">
+ <containerElement type="library" name="junit" level="application">
+ <attribute name="method" value="0" />
+ <attribute name="URI" value="<N/A>" />
+ </containerElement>
+ <containerElement type="library" name="Struts2" level="project">
+ <attribute name="method" value="1" />
+ <attribute name="URI" value="/WEB-INF/lib" />
+ </containerElement>
+ <deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/webapp/WEB-INF/web.xml" optional="false" version="2.3" />
+ <deploymentDescriptor name="context.xml" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false" version="5.x" />
+ <deploymentDescriptor name="" url="file://$MODULE_DIR$/META-INF/context.xml" optional="false">
+ <option name="DEFAULT_DIR" value="WEB-INF" />
+ <option name="NAME" value="" />
+ <option name="DESCRIPTION" value="" />
+ </deploymentDescriptor>
+ <webroots>
+ <root url="file://$MODULE_DIR$/src/webapp" relative="/" />
+ <root url="file://$MODULE_DIR$/src/java" relative="/WEB-INF/src/java" />
+ <root url="file://$MODULE_DIR$/src/test" relative="/WEB-INF/src/test" />
+ </webroots>
+ </component>
+ <component name="WeblogicWebModuleProperties" />
+</module>
+
diff --git a/struts-sandbox/overdrive/Agility/Agility.sln b/struts-sandbox/overdrive/Agility/Agility.sln
new file mode 100644
index 0000000..8817b81
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Agility.sln
@@ -0,0 +1,32 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{7E15FF78-6661-4ED4-A1CC-64664647855F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{52B62C70-A39E-48BA-9759-DB33DB8F099F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {7E15FF78-6661-4ED4-A1CC-64664647855F}.Debug.ActiveCfg = Debug|.NET
+ {7E15FF78-6661-4ED4-A1CC-64664647855F}.Debug.Build.0 = Debug|.NET
+ {7E15FF78-6661-4ED4-A1CC-64664647855F}.Release.ActiveCfg = Release|.NET
+ {7E15FF78-6661-4ED4-A1CC-64664647855F}.Release.Build.0 = Release|.NET
+ {52B62C70-A39E-48BA-9759-DB33DB8F099F}.Debug.ActiveCfg = Debug|.NET
+ {52B62C70-A39E-48BA-9759-DB33DB8F099F}.Debug.Build.0 = Debug|.NET
+ {52B62C70-A39E-48BA-9759-DB33DB8F099F}.Release.ActiveCfg = Release|.NET
+ {52B62C70-A39E-48BA-9759-DB33DB8F099F}.Release.Build.0 = Release|.NET
+ EndGlobalSection
+ GlobalSection(SolutionItems) = postSolution
+ postbuild.bat = postbuild.bat
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/struts-sandbox/overdrive/Agility/Core/AssemblyInfo.cs b/struts-sandbox/overdrive/Agility/Core/AssemblyInfo.cs
new file mode 100644
index 0000000..05af947
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Core/Chain.cs b/struts-sandbox/overdrive/Agility/Core/Chain.cs
new file mode 100644
index 0000000..41fb1a6
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/Chain.cs
@@ -0,0 +1,188 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// Concrete {@link IIChain} implementation
+ /// </summary>
+ /// <remarks><p>@version $Revision$ $Date$</p></remarks>
+ ///
+ public class Chain : IChain
+ {
+ #region Constructors
+
+ /// <summary>
+ /// Construct a {@link IChain} with no configured {@link ICommand}s.
+ /// </summary>
+ public Chain()
+ {
+ }
+
+ /// <summary>
+ /// Construct a {@link IChain} configured with the specified {@link ICommand}.
+ /// </summary>
+ /// <param name="command">The {@link ICommand} to be configured.</param>
+ public Chain(ICommand command)
+ {
+ AddCommand(command);
+ }
+
+ /// <summary>
+ /// Construct a {@link IChain} configured with the specified {@link ICommand}s.
+ /// </summary>
+ /// <param name="commands">The {@link ICommand}s to be configured.</param>
+ public Chain(ICommand[] commands)
+ {
+ if (commands == null) // FIXME: Illegal Argument
+ throw new Exception();
+ for (int i = 0; i < commands.Length; i++) AddCommand(commands[i]);
+
+ }
+
+
+ /// <summary>
+ /// Construct a {@link IChain} configured with the specified {@link ICommand}s.
+ /// </summary>
+ /// <param name="commands">The {@link ICommand}s to be configured</param>
+ public Chain(IList commands) : base()
+ {
+ AddCommands = commands;
+ }
+
+ #endregion
+
+ #region Instance Variables
+
+ /// <summary>
+ /// The list of {@link ICommand}s configured for this {@link IChain}, in the order in which they may delegate processing to the remainder of the {@link IChain}.
+ /// </summary>
+ protected ICommand[] commands = new ICommand[0];
+
+ /// <summary>
+ /// Flag indicating whether the configuration of our commands list has been frozen by a call to the <code>execute()</code> method.
+ /// </summary>
+ protected bool frozen = false;
+
+ #endregion
+
+ #region Chain Methods
+
+ // See interface
+ public void AddCommand(ICommand command)
+ {
+ if (command == null)
+ throw new ArgumentNullException("command==null", "Chain.AddCommand");
+ if (frozen)
+ throw new ApplicationException("Chain.AddCommand: frozen==true");
+ ICommand[] results = new ICommand[commands.Length + 1];
+ Array.Copy(commands, 0, results, 0, commands.Length);
+ results[commands.Length] = command;
+ commands = results;
+
+ }
+
+ public IList AddCommands
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value==null", "Chain.AddCommands");
+ IEnumerator elements = value.GetEnumerator();
+ while (elements.MoveNext()) AddCommand(elements.Current as ICommand);
+ }
+ }
+
+
+ // See interface
+ public bool Execute(IContext context)
+ {
+ // Verify our parameters
+ if (context == null)
+ throw new ArgumentNullException("context==null", "Chain.Execute");
+
+ // Freeze the configuration of the command list
+ frozen = true;
+
+ // Execute the commands in this list until one returns true
+ // or throws an exception
+ bool saveResult = false;
+ Exception saveException = null;
+ int i;
+ int n = commands.Length;
+ ;
+ for (i = 0; i < n; i++)
+ {
+ try
+ {
+ saveResult = commands[i].Execute(context);
+ if (saveResult) break;
+ }
+ catch (Exception e)
+ {
+ saveException = e;
+ break;
+ }
+ }
+
+ // Call postprocess methods on Filters in reverse order
+ if (i >= n)
+ { // Fell off the end of the chain
+ i--;
+ }
+ bool handled = false;
+ bool result;
+ for (int j = i; j >= 0; j--)
+ {
+ if (commands[j] is IFilter)
+ {
+ try
+ {
+ result =
+ ((IFilter) commands[j]).PostProcess(context, saveException);
+ if (result)
+ handled = true;
+ }
+ catch (Exception e)
+ {
+ if (e == null) throw (e); // Silently ignore
+ }
+ }
+ }
+ // Return the exception or result state from the last execute()
+ if ((saveException != null) && !handled) throw saveException;
+ else return (saveResult);
+ }
+
+ #endregion
+
+ #region Internal Methods
+
+ /// <summary>
+ /// Return an array of the configured {@link ICommand}s for this {@link IChain}. This method is internal to the assembly and is used only for the unit tests.
+ /// </summary>
+ /// <returns>An array of the configured {@link ICommand}s for this {@link IChain}</returns>
+ public ICommand[] GetCommands()
+ {
+ return (commands);
+
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Core/Context.cs b/struts-sandbox/overdrive/Agility/Core/Context.cs
new file mode 100644
index 0000000..c37d0ef
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/Context.cs
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// Concrete {@link IContext} implementation.
+ /// </summary>
+ public class Context : Hashtable, IContext
+ {
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ public Context()
+ {
+ }
+
+ /// <summary>
+ /// Convenience constructor to create new Context
+ /// and add a new item.
+ /// </summary>
+ /// <param name="key">Index for entry</param>
+ /// <param name="_value">Value for entry</param>
+ public Context(string key, object _value)
+ {
+ this.Add(key, _value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Core/Core.csproj b/struts-sandbox/overdrive/Agility/Core/Core.csproj
new file mode 100644
index 0000000..af4018f
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/Core.csproj
@@ -0,0 +1,130 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{7E15FF78-6661-4ED4-A1CC-64664647855F}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "Agility.Core"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = "$(SolutionDir)postbuild.bat $(TargetDir) $(TargetName) $(SolutionName) $(SolutionDir)"
+ RootNamespace = "Agility.Core"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Chain.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Context.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "ICatalog.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IChain.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "ICommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IFilter.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/Agility/Core/ICatalog.cs b/struts-sandbox/overdrive/Agility/Core/ICatalog.cs
new file mode 100644
index 0000000..13d0420
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/ICatalog.cs
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A {@link ICatalog} is a collection of named {@link ICommand}s (or
+ /// {@link IChain}s) that can be used retrieve the set of commands that
+ /// should be performed based on a symbolic identifier.
+ /// </summary>
+ /// <remarks>
+ /// <p>Use of catalogs is optional, but convenient when there are multiple possible
+ /// chains that can be selected and executed based on environmental conditions.</p>
+ /// </remarks>
+ public interface ICatalog
+ {
+ /// <summary>
+ /// Add a new name and associated {@link ICommand} or {@link IChain}
+ /// to the set of named commands known to this {@link ICatalog},
+ /// replacing any previous command for that name.
+ /// </summary>
+ /// <param name="name">Name of the new command</param>
+ /// <param name="command">{@link ICommand} or {@link IChain} to be returned</param>
+ void AddCommand(String name, ICommand command);
+
+ /// <summary>
+ /// Return the {@link ICommand} or {@link IChain} associated with the
+ /// specified name, if any; otherwise, return <code>null</code>.
+ /// </summary>
+ /// <param name="name">Name for which a {@link ICommand} or {@link IChain}
+ /// should be retrieved</param>
+ ICommand GetCommand(String name);
+
+ /// <summary>
+ /// Return an <code>IEnumerator</code> over the set of named commands
+ /// known to this {@link ICatalog}.
+ /// </summary>
+ /// <remarks>
+ /// <p>If there are no known commands, an empty IEnumerator is returned.</p>
+ /// </remarks>
+ IEnumerator GetNames();
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Core/IChain.cs b/struts-sandbox/overdrive/Agility/Core/IChain.cs
new file mode 100644
index 0000000..76a0b0e
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/IChain.cs
@@ -0,0 +1,115 @@
+using System.Collections;
+/*
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A {@link IChain} represents a configured list of
+ /// {@link ICommand}s that will be executed in order to perform processing
+ /// on a specified {@link IContext}.
+ /// </summary>
+ /// <remarks>
+ /// <p>Each included {@link ICommand} will be
+ /// executed in turn, until either one of them returns <code>true</code>,
+ /// one of the executed {@link ICommand}s throws an Exception,
+ /// or the end of the chain has been reached. The {@link IChain} itself will
+ /// return the return value of the last {@link ICommand} that was executed
+ /// (if no exception was thrown), or rethrow the thrown Exception.</p>
+ ///
+ /// <p>Note that {@link IChain} extends {@link ICommand}, so that the two can
+ /// be used interchangeably when a {@link ICommand} is expected. This makes it
+ /// easy to assemble workflows in a hierarchical manner by combining subchains
+ /// into an overall processing chain.</p>
+ ///
+ /// <p>To protect applications from evolution of this interface, specialized
+ /// implementations of {@link IChain} should generally be created by extending
+ /// the provided base class {@link Agility.Core.Chain})
+ /// rather than directly implementing this interface.</p>
+ ///
+ /// <p>{@link IChain} implementations should be designed in a thread-safe
+ /// manner, suitable for execution on multiple threads simultaneously. In
+ /// general, this implies that the state information identifying which
+ /// {@link ICommand} is currently being executed should be maintained in a
+ /// local variable inside the <code>Execute</code> method, rather than
+ /// in an instance variable. The {@link ICommand}s in a {@link IChain} may be
+ /// configured (via calls to <code>AddCommand</code>) at any time before
+ /// the <code>Execute()</code> method of the {@link IChain} is first called.
+ /// After that, the configuration of the {@link IChain} is frozen.</p>
+ /// </remarks>
+ public interface IChain : ICommand
+ {
+ /// <summary>
+ /// Add a {@link ICommand} to the list of {@link ICommand}s that will
+ /// be called in turn when this {@link IChain}'s <code>Execute()</code>
+ /// method is called.
+ ///</summary>
+ ///<remarks>
+ /// <p>Once <code>Execute</code> has been called
+ /// at least once, it is no longer possible to add additional
+ /// {@link ICommand}s; instead, an Exception will be thrown.</p>
+ /// </remarks>
+ void AddCommand(ICommand command);
+
+ /// <summary>
+ /// Add a IList of {@link ICommand}s to the list of {@link ICommand}s.
+ ///</summary>
+ ///<remarks>
+ /// Although rendered as a property, this member does add a Command to the list,
+ /// without overwritign any existing commands, unless keys conflicts.
+ /// If key conflict, the last one added wins.
+ ///</remarks>
+ IList AddCommands { set; }
+
+ /// <summary>
+ /// Execute the processing represented by this {@link IChain}.
+ /// </summary>
+ /// <remarks>
+ /// <p>Processing uses the following algorithm:</p>
+ /// <ul>
+ /// <li>If there are no configured {@link ICommand}s in the {@link IChain},
+ /// return <code>false</code>.</li>
+ /// <li>Call the <code>Execute</code> method of each {@link ICommand}
+ /// configured on this chain, in the order they were added via calls
+ /// to the <code>AddCommand</code> method, until the end of the
+ /// configured {@link ICommand}s is encountered, or until one of
+ /// the executed {@link ICommand}s returns <code>true</code>
+ /// or throws an Exception.</li>
+ /// <li>Walk backwards through the {@link ICommand}s whose
+ /// <code>Execute</code> methods, starting with the last one that
+ /// was executed. If this {@link ICommand} instance is also a
+ /// {@link IFilter}, call its <code>PostProcess</code> method.
+ /// <b>If <code>PostProcess</code> throws an Exception, it is ignored.</b></li>
+ /// <li>If the last {@link ICommand} whose <code>Execute</code> method
+ /// was called throws an Exception, rethrow that Exception.</li>
+ /// <li>Otherwise, return the value returned by the <code>Execute</code>
+ /// method of the last {@link ICommand} that was executed. This will be
+ /// <code>true</code> if the last {@link ICommand} indicated that
+ /// processing of this {@link IContext} has been completed, or
+ /// <code>false</code> if none of the called {@link ICommand}s
+ /// returned <code>true</code>.</li>
+ /// </ul>
+ /// </remarks>
+ /// <param name="context">The {@link IContext} to be processed by this
+ /// {@link IChain}</param>
+ /// <returns><code>true</code> if the processing of this {@link IContext}
+ /// is complete, or <code>false</code> if further processing
+ /// of this {@link IContext} can be delegated to a subsequent
+ /// {@link ICommand} in an enclosing {@link IChain}</returns>
+ new bool Execute(IContext context);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Core/ICommand.cs b/struts-sandbox/overdrive/Agility/Core/ICommand.cs
new file mode 100644
index 0000000..ff22dd4
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/ICommand.cs
@@ -0,0 +1,97 @@
+ /*
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A {@link Command} encapsulates a unit of processing work to be
+ /// performed, whose purpose is to examine and/or modify the state of a
+ /// transaction that is represented by a {@link Context}.
+ /// </summary>
+ /// <remarks>
+ /// <p>Individual {@link Command}s can be assembled into a {@link Chain}, which allows
+ /// them to either complete the required processing or delegate further
+ /// processing to the next {@link Command} in the {@link Chain}.</p>
+ ///
+ /// <p>{@link Command} implementations should be designed in a thread-safe
+ /// manner, suitable for inclusion in multiple {@link Chain}s that might be
+ /// processed by different threads simultaneously. In general, this implies
+ /// that {@link Command} classes should not maintain state information in
+ /// instance variables. Instead, state information should be maintained via
+ /// suitable modifications to the attributes of the {@link Context} that is
+ /// passed to the <code>Execute</code> command.</p>
+ ///
+ /// <p>{@link Command} implementations typically retrieve and store state
+ /// information in the {@link Context} instance that is passed as a parameter
+ /// to the <code>Execute</code> method, using particular keys into the
+ /// <code>IDictionary</code> that can be acquired via
+ /// <code>Context.Keys</code>.
+ ///
+ /// <p>To improve interoperability of
+ /// {@link Command} implementations, a useful design pattern is to expose the
+ /// key values used as Properties of the {@link Command}
+ /// implementation class itself. For example, a {@link Command} that requires
+ /// an input and an output key might implement the following properties:</p>
+ ///
+ /// <pre>
+ /// private string _InputKey = "input";
+ /// public string InputKey {
+ /// get { return _InputKey; }
+ /// set { _InputKey = value; }
+ /// }
+ ///
+ /// private string _OutputKey = "output";
+ /// public string OutputKey {
+ /// get { return _OutputKey; }
+ /// set { _OutputKey = value; }
+ /// }
+ /// </pre>
+ ///
+ /// <p>And the operation of accessing the "input" information in the context
+ /// would be executed by calling:</p>
+ ///
+ /// <pre>
+ /// string input = context[getInputKey()] as string;
+ /// </pre>
+ ///
+ /// <p>instead of hard coding the key attribute. The use of the "Key"
+ /// suffix on such property names is a useful convention to identify properties
+ /// being used in this fashion, as opposed to properties that simply
+ /// configure the internal operation of this {@link Command}.</p>
+ /// </remarks>
+ public interface ICommand
+ {
+ /// <summary>
+ /// Execute a unit of processing work to be performed.
+ /// </summary>
+ /// <remarks>
+ /// This {@link ICommand} may either complete the required processing
+ /// and return <code>true</code>, or delegate remaining processing
+ /// to the next {@link ICommand} in a {@link IChain} containing this
+ /// {@link ICommand} by returning <code>false</code>
+ /// </remarks>
+ /// <param name="context">The {@link IContext} to be processed by this
+ /// {@link ICommand}</param>
+ /// <returns>
+ /// <code>true</code> if the processing of this {@link Context}
+ /// has been completed, or <code>false</code> if the processing
+ /// of this {@link IContext} should be delegated to a subsequent
+ /// {@link ICommand} in an enclosing {@link IChain}
+ /// </returns>
+ bool Execute(IContext context);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Core/IContext.cs b/struts-sandbox/overdrive/Agility/Core/IContext.cs
new file mode 100644
index 0000000..3db6d44
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/IContext.cs
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A {@link Context} represents the state information that is
+ /// accessed and manipulated by the execution of a {@link ICommand} or a
+ /// {@link IChain}.
+ /// </summary>
+ /// <remarks>
+ /// <p>Specialized implementations of {@link IContext} may
+ /// add properties that contain typesafe accessors to information that
+ /// is relevant to a particular use case for this context, and/or add
+ /// operations that affect the state information that is saved in the
+ /// context.</p>
+ ///
+ /// <p>Implementations of {@link IContext} must also implement all of the
+ /// required and optional contracts of the <code>IDictionary</code>
+ /// interface.</p>
+ ///
+ /// <p>To protect applications from evolution of this interface, specialized
+ /// implementations of {@link Context} should generally be created by extending
+ /// the provided base class ({@link Agility.Core.Context})
+ /// rather than directly implementing this interface.</p>
+ ///
+ /// <p>Applications should <strong>NOT</strong> assume that
+ /// {@link Context} implementations, or the values stored in its
+ /// attributes, may be accessed from multiple threads
+ /// simultaneously, unless this is explicitly documented for a particular
+ /// implementation.</p>
+ /// </remarks>
+ public interface IContext : IDictionary
+ {
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Core/IFilter.cs b/struts-sandbox/overdrive/Agility/Core/IFilter.cs
new file mode 100644
index 0000000..5b8e990
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Core/IFilter.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A {@link Filter} is a specialized {@link Command} that also expects the {@link Chain} that is executing it to call the <code>postprocess()</code> method if it called the <code>execute()</code> method.
+ /// </summary>
+ /// <remarks>
+ /// <p>This contract must be fulfilled regardless of any possible exceptions thrown by the <code>Execute</code> method of this {@link ICommand}, or any subsequent {@link ICommand} whose <code>Execute</code> method is called.
+ /// The owning {@link IChain} must call the <code>PostProcess</code> method of each {@link IFilter} in a {@link IChain} in reverse order of the invocation of their <code>Execute</code> methods.</p>
+ /// <p>The most common use case for a {@link IFilter}, as opposed to a {@link ICommand}, is where potentially expensive resources must be acquired and held until the processing of a particular request has been completed, even if execution is delegated to a subsequent {@link Command} via the <code>Execute</code> returning <code>false</code>.
+ /// A {@link IFilter} can reliably release such resources in the <code>PostProcess</code> method, which is guaranteed to be called by the owning {@link IChain}.</p>
+ /// <p>@version $Revision$ $Date$</p>
+ /// </remarks>
+ ///
+ public interface IFilter : ICommand
+ {
+ /// <summary>
+ /// Execute any cleanup activities, such as releasing resources that were acquired during the <code>execute()</code> method of this {@link Filter} instance.
+ /// </summary>
+ /// <param name="context">The {@link Context} to be processed by this {@link Filter}</param>
+ /// <param name="exception">The <code>Exception</code> (if any) that was thrown by the last {@link Command} that was executed; otherwise <code>null</code></param>
+ /// <returns>If a non-null <code>exception</code> was "handled" by this method (and therefore need not be rethrown), return <code>true</code>; otherwise return <code>false</code></returns>
+ bool PostProcess(IContext context, Exception exception);
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/LICENSE.txt b/struts-sandbox/overdrive/Agility/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/struts-sandbox/overdrive/Agility/NOTICE.txt b/struts-sandbox/overdrive/Agility/NOTICE.txt
new file mode 100644
index 0000000..73c4637
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/NOTICE.txt
@@ -0,0 +1,6 @@
+NOTICE
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the Apache Software Foundation and was
+originally based, in part, on public domain software written by the
+Oklahoma Department of Environmental Quality, Oklahoma City OK US.
diff --git a/struts-sandbox/overdrive/Agility/Test/AssemblyInfo.cs b/struts-sandbox/overdrive/Agility/Test/AssemblyInfo.cs
new file mode 100644
index 0000000..05af947
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/CommandTest.cs b/struts-sandbox/overdrive/Agility/Test/CommandTest.cs
new file mode 100644
index 0000000..cc1447e
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/CommandTest.cs
@@ -0,0 +1,69 @@
+using System;
+using NUnit.Framework;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// Test suite for the various Test*Commands.
+ /// </summary>
+ [TestFixture]
+ public class CommandTest
+ {
+ [Test]
+ public void ModifyCommand()
+ {
+ const string VALUE = TestInputCommand.VALUE;
+ TestContext context = new TestContext();
+ context.Add(context.InputKey, VALUE);
+ ICommand command = new TestModifyCommand();
+ command.Execute(context);
+ string output = context[context.OutputKey] as string;
+ Assert.IsNotNull(output, "Expected output");
+ Assert.IsFalse(VALUE.Equals(output), "Expected modified output");
+ string input = context[context.InputKey] as string;
+ Assert.IsTrue(VALUE.Equals(input), "Expected " + VALUE + " but found " + input);
+ }
+
+ [Test]
+ public void NotImplementedCommand()
+ {
+ TestContext context = new TestContext();
+ ICommand command = new TestNotImplementedCommand();
+ try
+ {
+ command.Execute(context);
+ Assert.Fail("Expected exception");
+ }
+ catch (NotImplementedException expected)
+ {
+ Assert.IsNotNull(expected, "Expected exception");
+ }
+ }
+
+ [Test]
+ public void NowCommand()
+ {
+ TestContext context = new TestContext();
+ ICommand command = new TestNowCommand();
+ command.Execute(context);
+ DateTime then = (DateTime) context[context.OutputKey];
+ int greater = DateTime.Now.CompareTo(then);
+ Assert.IsTrue(greater >= 0, "Expected now to be past");
+ }
+
+ [Test]
+ public void RemoveCommand()
+ {
+ ICommand command = new TestRemoveCommand();
+ const string VALUE = TestInputCommand.VALUE;
+ TestContext context = new TestContext();
+ context.Add(context.InputKey, VALUE);
+ command.Execute(context);
+ string input = context[context.InputKey] as string;
+ Assert.IsNull(input, "Expected input to be removed");
+ string output = context[context.OutputKey] as string;
+ Assert.IsNotNull(output, "Expected non-null output");
+ Assert.IsTrue(VALUE.Equals(output), "Expected " + VALUE + " but found " + output);
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/Test.csproj b/struts-sandbox/overdrive/Agility/Test/Test.csproj
new file mode 100644
index 0000000..dd701cc
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/Test.csproj
@@ -0,0 +1,161 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{52B62C70-A39E-48BA-9759-DB33DB8F099F}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "Agility.Test"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = "$(SolutionDir)postbuild.bat $(TargetDir) $(TargetName) $(SolutionName) $(SolutionDir)"
+ RootNamespace = "Agility.Core"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "nunit.framework"
+ AssemblyName = "nunit.framework"
+ HintPath = "..\..\..\..\..\..\..\Program Files\NUnit 2.2\bin\nunit.framework.dll"
+ AssemblyFolderKey = "hklm\dn\nunit.framework"
+ />
+ <Reference
+ Name = "Core"
+ Project = "{7E15FF78-6661-4ED4-A1CC-64664647855F}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "CommandTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestChain.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestFilterCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestFilterHandler.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestInputCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestModifyCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestNotImplementedCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestNowCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "TestRemoveCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/Agility/Test/TestChain.cs b/struts-sandbox/overdrive/Agility/Test/TestChain.cs
new file mode 100644
index 0000000..6d2fdf9
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestChain.cs
@@ -0,0 +1,121 @@
+using System;
+using NUnit.Framework;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// Summary description for TestChain.
+ /// </summary>
+ [TestFixture]
+ public class TestChain
+ {
+ private IChain chain;
+
+ [SetUp]
+ public void SetUp()
+ {
+ chain = new Chain();
+ }
+
+
+ // TODO: Test Constructors and AddCommands.
+
+ /// <summary>
+ /// Test adding commands and that chain "freezes" after execute.
+ /// </summary>
+ [Test]
+ public void TestAddCommand()
+ {
+ Chain test = chain as Chain;
+ ICommand[] before = test.GetCommands();
+ Assert.AreEqual(0, before.Length, "Expected an empty chain");
+
+ ICommand c1 = new TestCommand();
+ chain.AddCommand(c1);
+
+ ICommand[] first = test.GetCommands();
+ Assert.AreEqual(1, first.Length, "Expected one link in the chain");
+
+ ICommand c2 = new TestNowCommand();
+ chain.AddCommand(c2);
+
+ ICommand[] second = test.GetCommands();
+ Assert.AreEqual(2, second.Length, "Expected two links in the chain");
+
+ TestContext context = new TestContext();
+ chain.Execute(context);
+
+ DateTime output = (DateTime) context[context.OutputKey];
+ Assert.IsNotNull(output, "Expected output");
+
+ try
+ {
+ chain.AddCommand(c1);
+ Assert.Fail("Expected exception when adding command to frozen chain.");
+ }
+ catch (Exception expected)
+ {
+ // FIXME: Exception has to be specific
+ Assert.IsNotNull(expected, "Expected exception");
+ }
+ }
+
+ [Test]
+ public void TestExecute()
+ {
+ chain.AddCommand(new TestInputCommand());
+ chain.AddCommand(new TestModifyCommand());
+ TestContext context = new TestContext();
+ chain.Execute(context);
+ string output = context[context.OutputKey] as string;
+ Assert.IsNotNull(output, "Expected output");
+ string expected = TestInputCommand.VALUE + TestModifyCommand.SUFFIX;
+ Assert.IsTrue(expected.Equals(output), "Expected modified output");
+ }
+
+ [Test]
+ public void TextExecuteReverse()
+ {
+ chain.AddCommand(new TestModifyCommand());
+ chain.AddCommand(new TestInputCommand());
+ TestContext context = new TestContext();
+ chain.Execute(context);
+ string output = context[context.OutputKey] as string;
+ string expected = TestModifyCommand.SUFFIX;
+ Assert.IsTrue(expected.Equals(output), "Expected modified suffix only");
+ }
+
+ [Test]
+ public void TestFilterCommand()
+ {
+ string KEY = "FILTER"; // TestFilterCommand.FILTER_KEY;
+ chain.AddCommand(new TestFilterCommand());
+ chain.AddCommand(new TestNotImplementedCommand());
+ IContext context = new TestContext();
+ try
+ {
+ chain.Execute(context);
+ Assert.Fail("Expected NotImplementedException");
+ }
+ catch (NotImplementedException expected)
+ {
+ Assert.IsNotNull(expected, "Expected exception");
+ }
+ ICommand filter = context[KEY] as ICommand;
+ Assert.IsNull(filter);
+ }
+
+ [Test]
+ public void TestFilterHandler()
+ {
+ string KEY = "FILTER"; // TestFilterCommand.FILTER_KEY;
+ chain.AddCommand(new TestFilterHandler());
+ chain.AddCommand(new TestNotImplementedCommand());
+ IContext context = new TestContext();
+ chain.Execute(context);
+ NotImplementedException filter = context[KEY] as NotImplementedException;
+ Assert.IsNotNull(filter, "Expected Exception to be stored.");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestCommand.cs b/struts-sandbox/overdrive/Agility/Test/TestCommand.cs
new file mode 100644
index 0000000..b75f255
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestCommand.cs
@@ -0,0 +1,14 @@
+namespace Agility.Core
+{
+ /// <summary>
+ /// A do-nothing pass-through command.
+ /// </summary>
+ public class TestCommand : ICommand
+ {
+ public bool Execute(IContext context)
+ {
+ ; // do nothing
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestContext.cs b/struts-sandbox/overdrive/Agility/Test/TestContext.cs
new file mode 100644
index 0000000..5446a77
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestContext.cs
@@ -0,0 +1,25 @@
+namespace Agility.Core
+{
+ /// <summary>
+ /// Summary description for TestContext.
+ /// </summary>
+ public class TestContext : Context
+ {
+ private string _InputKey = "input";
+
+ public string InputKey
+ {
+ get { return _InputKey; }
+ set { _InputKey = value; }
+
+ }
+
+ private string _OutputKey = "output";
+
+ public string OutputKey
+ {
+ get { return _OutputKey; }
+ set { _OutputKey = value; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestFilterCommand.cs b/struts-sandbox/overdrive/Agility/Test/TestFilterCommand.cs
new file mode 100644
index 0000000..0a43342
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestFilterCommand.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A Command that uses a Filter to clean up after itself.
+ /// </summary>
+ public class TestFilterCommand : IFilter
+ {
+ public const string FILTER_KEY = "FILTER";
+
+ #region IFilter Members
+
+ public virtual bool PostProcess(IContext context, Exception exception)
+ {
+ context[FILTER_KEY] = null;
+ return false; // == I took care of my business, but someone
+ // still needs to handle the exception
+ }
+
+ #endregion
+
+ #region ICommand Members
+
+ public bool Execute(IContext context)
+ {
+ context.Add(FILTER_KEY, this);
+ return false;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestFilterHandler.cs b/struts-sandbox/overdrive/Agility/Test/TestFilterHandler.cs
new file mode 100644
index 0000000..e638ce5
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestFilterHandler.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A filter that handles the exception (somehow).
+ /// </summary>
+ public class TestFilterHandler : TestFilterCommand
+ {
+ public override bool PostProcess(IContext context, Exception exception)
+ {
+ context[FILTER_KEY] = exception;
+ return true; // == OK, I handled it!
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestInputCommand.cs b/struts-sandbox/overdrive/Agility/Test/TestInputCommand.cs
new file mode 100644
index 0000000..ef53a51
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestInputCommand.cs
@@ -0,0 +1,18 @@
+namespace Agility.Core
+{
+ /// <summary>
+ /// A Command that adds a value to a TestContext under its InputKey.
+ /// </summary>
+ public class TestInputCommand : ICommand
+ {
+ public const string VALUE = "INPUT";
+
+ public bool Execute(IContext _context)
+ {
+ TestContext context = _context as TestContext;
+ context.Add(context.InputKey, VALUE);
+ return false;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestModifyCommand.cs b/struts-sandbox/overdrive/Agility/Test/TestModifyCommand.cs
new file mode 100644
index 0000000..f58b2a3
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestModifyCommand.cs
@@ -0,0 +1,21 @@
+namespace Agility.Core
+{
+ /// <summary>
+ /// A Command that modifies an input value by adding the
+ /// substring "_MODIFIED" and sets the new value as output,
+ /// without changing the input value.
+ /// </summary>
+ public class TestModifyCommand : ICommand
+ {
+ public const string SUFFIX = "_MODIFIED";
+
+ public bool Execute(IContext _context)
+ {
+ TestContext context = _context as TestContext;
+ string input = context[context.InputKey] as string;
+ string output = input + SUFFIX;
+ context[context.OutputKey] = output;
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestNotImplementedCommand.cs b/struts-sandbox/overdrive/Agility/Test/TestNotImplementedCommand.cs
new file mode 100644
index 0000000..2c7c8ea
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestNotImplementedCommand.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A command that throws a NotImplementedException.
+ /// </summary>
+ public class TestNotImplementedCommand : ICommand
+ {
+ public bool Execute(IContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestNowCommand.cs b/struts-sandbox/overdrive/Agility/Test/TestNowCommand.cs
new file mode 100644
index 0000000..2a64800
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestNowCommand.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Agility.Core
+{
+ /// <summary>
+ /// A Command that sets a new output value to the DateTime for "Now".
+ /// </summary>
+ public class TestNowCommand : ICommand
+ {
+ public bool Execute(IContext _context)
+ {
+ TestContext context = _context as TestContext;
+ context[context.OutputKey] = DateTime.Now;
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/Test/TestRemoveCommand.cs b/struts-sandbox/overdrive/Agility/Test/TestRemoveCommand.cs
new file mode 100644
index 0000000..c89a010
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/Test/TestRemoveCommand.cs
@@ -0,0 +1,18 @@
+namespace Agility.Core
+{
+ /// <summary>
+ /// A Command that sets the input value as the output value,
+ /// and removes the input value.
+ /// </summary>
+ public class TestRemoveCommand : ICommand
+ {
+ public bool Execute(IContext _context)
+ {
+ TestContext context = _context as TestContext;
+ string value = context[context.InputKey] as string;
+ context[context.InputKey] = null;
+ context[context.OutputKey] = value;
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Agility/postbuild.bat b/struts-sandbox/overdrive/Agility/postbuild.bat
new file mode 100644
index 0000000..78e0f9a
--- /dev/null
+++ b/struts-sandbox/overdrive/Agility/postbuild.bat
@@ -0,0 +1,3 @@
+REM %LOCAL_CACHE% doesn't work.
+CD %4
+COPY %1%2.* ..\local-cache\%3
diff --git a/struts-sandbox/overdrive/Nexus/Core/AssemblyInfo.cs b/struts-sandbox/overdrive/Nexus/Core/AssemblyInfo.cs
new file mode 100644
index 0000000..05af947
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Core.csproj b/struts-sandbox/overdrive/Nexus/Core/Core.csproj
new file mode 100644
index 0000000..04740f6
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Core.csproj
@@ -0,0 +1,310 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{7C8CAFD4-1E45-41B4-9963-F51199B12EA7}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "Nexus.Core"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = "$(SolutionDir)postbuild.bat $(TargetDir) $(TargetName) $(SolutionName) $(SolutionDir)"
+ RootNamespace = "Nexus.Core"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = "Nexus.Core.xml"
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = "1591"
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "System.Drawing"
+ AssemblyName = "System.Drawing"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll"
+ />
+ <Reference
+ Name = "System.Windows.Forms"
+ AssemblyName = "System.Windows.Forms"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Windows.Forms.dll"
+ />
+ <Reference
+ Name = "Agility.Core"
+ AssemblyName = "Agility.Core"
+ HintPath = "..\..\local-cache\Agility\Agility.Core.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "EntryDictionary.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IEntryList.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IKeyValue.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IKeyValueList.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IRequestCatalog.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IRequestChain.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IRequestCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IRequestContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "KeyValue.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "KeyValueList.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "RequestChain.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "RequestCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "RequestContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Tokens.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Helpers\FindArgs.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Helpers\IViewHelper.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Helpers\ViewArgs.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Helpers\ViewHelper.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Profile\IProfile.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Profile\UserIdentity.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Profile\UserPrincipal.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Profile\UserProfile.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Tables\FieldContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Tables\FieldTable.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Tables\IFieldContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Tables\IFieldTable.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\ClearContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\CollectionProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\ConvertInput.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\DateTimeProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\EntryListProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\FormatOutput.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\IProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\IProcessorCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\IProcessorContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\KeyValueProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\Processor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\ProcessorCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\ProcessorContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Validators\StringProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/Nexus/Core/EntryDictionary.cs b/struts-sandbox/overdrive/Nexus/Core/EntryDictionary.cs
new file mode 100644
index 0000000..f59e8f7
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/EntryDictionary.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Expose field attributes as public properties.
+ /// </summary>
+ /// <remarks><p>
+ /// The EntryDictionary is used for integration with libraries that
+ /// can use only public properties, such as DataGrid.
+ /// It is also used to pass properties as Event argument,
+ /// in which case it is used like a data transfer object.
+ /// </p><p>
+ /// The values are available both as an IDictionary and
+ /// (optionally) as Properties.
+ /// (The properties should use the IDictionary for storage.)
+ /// To define properties, extend EntryDictionary.
+ /// </p></remarks>
+ public class EntryDictionary
+ {
+ private IDictionary _Value = new Hashtable();
+
+ public EntryDictionary()
+ {
+ // Default contstructor
+ }
+
+ public EntryDictionary(IDictionary sources)
+ {
+ AddAll(sources);
+ }
+
+ /// <summary>
+ /// Provide a string representation of the field values
+ /// in the format "key=value\n".
+ /// </summary>
+ /// <returns>String representation</returns>
+ public override String ToString()
+ {
+ StringBuilder builder = new StringBuilder(128);
+ string tab = "=";
+ string eol = "\n";
+ ICollection keys = _Value.Keys;
+ foreach (string key in keys)
+ {
+ builder.Append(key);
+ builder.Append(tab);
+ builder.Append(Get(key));
+ builder.Append(eol);
+ }
+ return builder.ToString();
+ }
+
+ public void Add(string key, string value)
+ {
+ _Value.Add(key, value);
+ }
+
+ public void AddAll(IDictionary sources)
+ {
+ ICollection keys = sources.Keys;
+ foreach (string key in keys)
+ {
+ object value = sources[key];
+ if (value == null)
+ Add(key, value as string);
+ else
+ Add(key, value.ToString());
+ }
+ }
+
+ protected ICollection Keys
+ {
+ get { return _Value.Keys; }
+ }
+
+ public string Get(string key)
+ {
+ return _Value[key] as string;
+ }
+
+ public void Set(string key, string value)
+ {
+ if (value == null)
+ _Value[key] = null;
+ else _Value[key] = value.Trim();
+ }
+
+ public Boolean Contains(Object key)
+ {
+ return _Value.Contains(key);
+ }
+
+ public IDictionary Criteria
+ {
+ get { return _Value; }
+ }
+
+ /// <summary>
+ /// Call calculated properties so that
+ /// they are cached as entries in the table.
+ /// </summary>
+ /// <remarks>
+ /// <p>Override to provide functionality</p>
+ /// </remarks>
+ ///
+ public virtual void CacheText()
+ {
+ }
+
+ /*
+ public string Property
+ {
+ get { return return Get(App.PROPERTY); }
+ set { Set(App.PROPERTY, value); }
+ }
+ */
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Helpers/FindArgs.cs b/struts-sandbox/overdrive/Nexus/Core/Helpers/FindArgs.cs
new file mode 100644
index 0000000..ecaab81
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Helpers/FindArgs.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+
+namespace WQD.Core.Controls
+{
+ /// <summary>
+ /// Provide an EventArgs type to interace with FindControls
+ /// that can be read or bound via an IDictionary object.
+ /// </summary>
+ ///
+ public class FindArgs : EventArgs
+ {
+ /// <summary>
+ /// A reference to the original arguments for an event, if any.
+ /// </summary>
+ ///
+ public EventArgs OldArgs;
+
+ /// <summary>
+ /// Expose our dictionary instance.
+ /// </summary>
+ ///
+ public IDictionary Criteria;
+
+ /// <summary>
+ /// Create this instance using the given dictionary.
+ /// </summary>
+ ///
+ public FindArgs(IDictionary criteria)
+ {
+ Criteria = criteria;
+ OldArgs = new EventArgs();
+ }
+
+ /// <summary>
+ /// Create a new instance with empty fields.
+ /// </summary>
+ ///
+ public FindArgs()
+ {
+ Criteria = new Hashtable();
+ OldArgs = new EventArgs();
+ }
+
+ /// <summary>
+ /// Create a new instance, setting the old event arguments.
+ /// </summary>
+ /// <param name="oldArgs">Old Event arguments</param>
+ ///
+ public FindArgs(EventArgs oldArgs)
+ {
+ this.OldArgs = oldArgs;
+ Criteria = new Hashtable();
+ }
+
+ public FindArgs(EventArgs e, IDictionary c)
+ {
+ OldArgs = e;
+ Criteria = c;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Helpers/IViewHelper.cs b/struts-sandbox/overdrive/Nexus/Core/Helpers/IViewHelper.cs
new file mode 100644
index 0000000..ccf8f51
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Helpers/IViewHelper.cs
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core.Profile;
+using Nexus.Core.Tables;
+
+namespace Nexus.Core.Helpers
+{
+ /// <summary>
+ /// Provide methods for running a business command and handling the result.
+ /// </summary>
+ /// <remarks><p>
+ /// IViewHelper is a facade for use by a code-behind to simplify access
+ /// to the IRequestContext and IRequestCommand.
+ /// </p><p>
+ /// The helper may also work with the catalog to act as a
+ /// "front controller" by ensuring routine tasks are carried out.
+ /// These tasks can include input validation, data conversion,
+ /// text formatting, command logging, and so forth.
+ /// </p></remarks>
+ ///
+ public interface IViewHelper
+ {
+ /// <summary>
+ /// Perform the Command associated with this Helper.
+ /// </summary>
+ ///
+ void Execute();
+
+ /// <summary>
+ /// Read input into the Criteria from a given Dictionary.
+ /// </summary>
+ /// <param name="criteria">Attributes to add to Critiera</param>
+ /// <param name="nullIfEmpty">Set attributes for empty strings to null</param>
+ ///
+ void Read(IDictionary criteria, bool nullIfEmpty);
+
+ /// <summary>
+ /// Store input and output values.
+ /// </summary>
+ ///
+ IDictionary Criteria { get; }
+
+ /// <summary>
+ /// User profile, which includes user ID and Locale.
+ /// </summary>
+ IProfile Profile { get; set; }
+
+ /// <summary>
+ /// Access result of operation as an IList.
+ /// </summary>
+ /// <remarks><p>
+ /// If the Helper is designed to return a List result,
+ /// this method saves casting the outcome.
+ /// If the Helper is not designed to return the result as a IList,
+ /// this method returns a single-value result as a one-entry list.
+ /// </p><p>
+ /// Note this since this is the Helper Outcome,
+ /// the result is relative to the Criteria,
+ /// rather than the main Context.
+ /// </p></remarks>
+ ///
+ IList Outcome { get; }
+
+ // ----
+
+ /// <summary>
+ /// Record a list of alert (or error) messages,
+ /// keyed by the field causing the message,
+ /// or to a magic global key.
+ /// </summary>
+ /// <remarks>
+ /// When recalling Alerts, by default include the Fault.
+ /// </remarks>
+ ///
+ IDictionary Alerts { get; }
+
+ /// <summary>
+ /// Return the Alerts for the specifiied ID,
+ /// formatted for display by a UI control.
+ /// </summary>
+ /// <remarks>
+ /// If messages are localized or customized,
+ /// the helper will return correct version for the user.
+ /// UI specific implementation may markup the errors as needed.
+ /// </remarks>
+ ///
+ string AlertsFor(string id);
+
+ /// <summary>
+ /// Return the Alerts, including any Fault, formatted for display by a UI control.
+ /// </summary>
+ /// <remarks>
+ /// If messages are localized or customized,
+ /// the helper will return correct version for the user.
+ /// UI specific implementation may markup the errors as needed.
+ /// </remarks>
+ ///
+ string AlertsText { get; }
+
+ /// <summary>
+ /// Indicate if alerts are queued.
+ /// </summary>
+ /// <returns>True if alerts are queued.</returns>
+ ///
+ bool HasAlerts { get; }
+
+ /// <summary>
+ /// Record an Exception, if thrown.
+ /// </summary>
+ /// <remarks>
+ /// By default, the Fault will be included in the list of Alerts.
+ /// </remarks>
+ ///
+ Exception Fault { get; }
+
+ /// <summary>
+ /// Indicate whether an Exception is caught.
+ /// </summary>
+ /// <returns>True if an Exception is caught.</returns>
+ ///
+ bool HasFault { get; }
+
+ /// <summary>
+ /// Indicate if there are no alerts or fault pending.
+ /// </summary>
+ /// <returns>True if all is well.</returns>
+ ///
+ bool IsNominal { get; }
+
+ /// <summary>
+ /// Record a list of hint (or advisory) messages,
+ /// keyed by a field or other identifier,
+ /// or to a magic global key.
+ /// </summary>
+ ///
+ IDictionary Hints { get; }
+
+ /// <summary>
+ /// Return the Hints for the specifiied ID,
+ /// formatted for display by a UI control.
+ /// </summary>
+ /// <remarks>
+ /// If messages are localized or customized,
+ /// the helper will return correct version for the user.
+ /// UI specific implementation may markup the errors as needed.
+ /// </remarks>
+ ///
+ string HintsFor(string id);
+
+ /// <summary>
+ /// Indicate if Hints are queued.
+ /// </summary>
+ /// <returns>True if Hints are queued.</returns>
+ ///
+ bool HasHints { get; }
+
+ /// <summary>
+ /// Return Hints formatted for display by a UI control.
+ /// </summary>
+ /// <remarks>
+ /// If messages are localized or customized,
+ /// the helper will return correct version for the user.
+ /// UI specific implementatiosn may markup the messages as needed.
+ /// </remarks>
+ ///
+ string HintsText { get; }
+
+ /// <summary>
+ /// Provide the Field Table for this Helper.
+ /// </summary>
+ /// <remarks><p>
+ /// The default implementation uses the Catalog to inject the global
+ /// Field Table reference.
+ /// The Context, and members with access to a Context,
+ /// can use the FieldTable to validate and format values,
+ /// and even to create controls that display values.
+ /// </p></remarks>
+ ///
+ IFieldTable FieldTable { get; }
+
+ // ----
+
+ /// <summary>
+ /// Provide the command (or chain of commands) for this helper
+ /// </summary>
+ /// <remarks><p>
+ /// Setting the Command also sets the internal Context for the command.
+ /// </p></remarks>
+ ///
+ IRequestCommand Command { get; set; }
+
+ /// <summary>
+ /// Provide a set of IFieldContext definitions to be used with this helper.
+ /// </summary>
+ /// <remarks><p>
+ /// The FieldSet is usually set by dependency injection.
+ /// Some helpers generate DataGrids or DataForms based on the
+ /// FieldDefinitions
+ /// </p></remarks>
+ ///
+ IList FieldSet { get; set; }
+
+ /// <summary>
+ /// Provide the catalog for this helper,
+ /// usually set by dependency injection.
+ /// </summary>
+ ///
+ IRequestCatalog Catalog { get; set; }
+
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Helpers/ViewArgs.cs b/struts-sandbox/overdrive/Nexus/Core/Helpers/ViewArgs.cs
new file mode 100644
index 0000000..0fc5e7b
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Helpers/ViewArgs.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Nexus.Core.Helpers
+{
+ /// <summary>
+ /// EventArgs type with a IViewHelper property.
+ /// </summary>
+ public class ViewArgs : EventArgs
+ {
+ private IViewHelper _Helper;
+
+ /// <summary>
+ /// Helper instance to encapsulate.
+ /// </summary>
+ public IViewHelper Helper
+ {
+ set { _Helper = value; }
+ get { return _Helper; }
+ }
+
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ public ViewArgs()
+ {
+ }
+
+ /// <summary>
+ /// Convenience constructor to set helper.
+ /// </summary>
+ /// <param name="helper"></param>
+ public ViewArgs(IViewHelper helper)
+ {
+ Helper = helper;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Helpers/ViewHelper.cs b/struts-sandbox/overdrive/Nexus/Core/Helpers/ViewHelper.cs
new file mode 100644
index 0000000..c3cf7aa
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Helpers/ViewHelper.cs
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core.Profile;
+using Nexus.Core.Tables;
+
+namespace Nexus.Core.Helpers
+{
+ /// <summary>
+ /// Standard implementation of IViewHelper.
+ /// </summary>
+ ///
+ public abstract class ViewHelper : IViewHelper
+ {
+ /// <summary>
+ /// Default setting for ListSuffix ["_list"].
+ /// </summary>
+ public const string LIST_SUFFIX = "_list";
+
+ /// <summary>
+ /// Default setting for NullIfEmpty [true].
+ /// </summary>
+ public const bool NULL_IF_EMPTY = true;
+
+ /// <summary>
+ /// Default setting for Prefix [""].
+ /// </summary>
+ public const string PREFIX = "";
+
+ /// <summary>
+ /// Default setting for SelectItemPrompt ["--v--"].
+ /// </summary>
+ public const string SELECT_ITEM_PROMPT = "--v--";
+
+ #region Read and Bind
+
+ public void Execute()
+ {
+ Catalog.ExecuteView(Context);
+ }
+
+ public void Read(IDictionary input, bool nullIfEmpty)
+ {
+ if (input == null) return;
+ ICollection keys = input.Keys;
+ IDictionary criteria = Criteria;
+ foreach (string key in keys)
+ {
+ string s = null;
+ string o = Convert.ToString(input[key]);
+ if (o!=null) s = o.Trim();
+ if ((nullIfEmpty) && (s != null) && (s.Length == 0))
+ criteria.Add(key, null);
+ else
+ criteria.Add(key, s);
+ }
+ }
+
+ public IDictionary Criteria
+ {
+ get { return Context.Criteria; }
+ }
+
+ public virtual IList Outcome
+ {
+ get
+ {
+ IList result;
+ object o = Criteria[Context.Command];
+ if (o == null)
+ {
+ result = new ArrayList(1);
+ result.Add(Criteria);
+ }
+ else
+ {
+ result = o as IList;
+ if (result == null)
+ {
+ result = new ArrayList(1);
+ result.Add(o);
+ }
+ }
+ return result;
+ }
+ }
+
+ #endregion
+
+ #region Messages
+
+ public IDictionary Alerts
+ {
+ get { return Context.Alerts; }
+ }
+
+ public bool HasAlerts
+ {
+ get { return Context.HasAlerts; }
+ }
+
+ public Exception Fault
+ {
+ get { return Context.Fault; }
+ }
+
+ public bool HasFault
+ {
+ get { return Context.HasFault; }
+ }
+
+ public virtual bool IsNominal
+ {
+ get { return (!HasAlerts && !HasFault); }
+ }
+
+
+ public IDictionary Hints
+ {
+ get { return Context.Hints; }
+ }
+
+ public bool HasHints
+ {
+ get { return Context.HasHints; }
+ }
+
+ #endregion
+
+ #region Messages (abstract)
+
+ public abstract string AlertsFor(string id);
+
+ public abstract string AlertsText { get; }
+
+ public abstract string HintsFor(string id);
+
+ public abstract string HintsText { get; }
+
+ #endregion
+
+ #region Tables
+
+ public IFieldTable FieldTable
+ {
+ get { return Context.FieldTable; }
+ }
+
+ private IList _FieldSet;
+
+ public virtual IList FieldSet
+ {
+ get { return _FieldSet; }
+ set { _FieldSet = value; }
+ }
+
+ #endregion
+
+ #region Options
+
+ private string _Prefix = PREFIX;
+
+ public string Prefix
+ {
+ get { return _Prefix; }
+ set { _Prefix = value; }
+ }
+
+ private string _ListSuffix = LIST_SUFFIX;
+
+ public string ListSuffix
+ {
+ get { return _ListSuffix; }
+ set { _ListSuffix = value; }
+ }
+
+ private bool _NullIfEmpty = NULL_IF_EMPTY;
+
+ public bool NullIfEmpty
+ {
+ get { return _NullIfEmpty; }
+ set { _NullIfEmpty = value; }
+ }
+
+ private string _SelectItemPrompt = SELECT_ITEM_PROMPT;
+
+ public string SelectItemPrompt
+ {
+ get { return _SelectItemPrompt; }
+ set { _SelectItemPrompt = value; }
+ }
+
+ #endregion
+
+ #region Properties
+
+ private IRequestCatalog _Catalog;
+
+ /// <summary>
+ /// Provide the application object catalog for this Helper.
+ /// </summary>
+ /// <remarks>
+ /// The Catalog is usually set through dependency injection.
+ /// The Catalog and Command must be set before calling other methods.
+ /// </remarks>
+ ///
+ public IRequestCatalog Catalog
+ {
+ get { return _Catalog; }
+ set { _Catalog = value; }
+ }
+
+ private IRequestCommand _Command;
+
+ /// <summary>
+ /// Provide the command for this Helper.
+ /// </summary>
+ /// <remarks>
+ /// The Command is usually set through dependency injection.
+ /// The Catalog and Command must be set before calling other methods.
+ /// </remarks>
+ ///
+ public IRequestCommand Command
+ {
+ get { return _Command; }
+ set
+ {
+ _Command = value;
+ _Context = Catalog.GetRequestContext(value);
+ }
+ }
+
+ private IRequestContext _Context;
+
+ /// <summary>
+ /// Provide the all-important Context for this Helper.
+ /// </summary>
+ /// <remarks>
+ /// The Context is obtained through reference to the Catalog and Command.
+ /// All other properties and methods of the Helper refer to the Context,
+ /// making Context the cornerstone property.
+ /// </remarks>
+ ///
+ public virtual IRequestContext Context
+ {
+ get
+ {
+ if (_Context == null)
+ {
+ IRequestCommand rc = Command;
+ if (rc == null) throw new ArgumentNullException("Command==null", "ViewHelper.Context");
+ _Context = Catalog.GetRequestContext(rc);
+ }
+ return _Context;
+ }
+ }
+
+ public IProfile Profile
+ {
+ get { return Context.Profile; }
+ set { Context.Profile = value; }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/IEntryList.cs b/struts-sandbox/overdrive/Nexus/Core/IEntryList.cs
new file mode 100644
index 0000000..3c12171
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/IEntryList.cs
@@ -0,0 +1,22 @@
+using System.Collections;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// A list of a set of Fields, such as displayed as the result of a query.
+ /// </summary>
+ public interface IEntryList : IList
+ {
+ /// <summary>
+ /// Create and Insert a new entry object at index 0.
+ /// </summary>
+ object Insert(string key);
+
+ /// <summary>
+ /// Add a entry object based on an IDictionary.
+ /// </summary>
+ /// <param name="row"></param>
+ void AddEntry(IDictionary row);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/IKeyValue.cs b/struts-sandbox/overdrive/Nexus/Core/IKeyValue.cs
new file mode 100644
index 0000000..54e29cb
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/IKeyValue.cs
@@ -0,0 +1,51 @@
+ /*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Represent a key/value pair,
+ /// as stored in an IDictionary or displayed
+ /// by a list in a user interface.
+ /// </summary>
+ /// <remarks>
+ /// The Text method returns the string form of Value,
+ /// which is useful for text-based controls.
+ /// </remarks>
+ ///
+ public interface IKeyValue
+ {
+ /// <summary>
+ /// The Key property under which the Value is stored.
+ /// </summary>
+ ///
+ string Key { get; set; }
+
+ /// <summary>
+ /// The Value stored for the Key.
+ /// </summary>
+ ///
+ object Value { get; set; }
+
+
+ /// <summary>
+ /// The Value in its standard string format.
+ /// </summary>
+ ///
+ string Text { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/IKeyValueList.cs b/struts-sandbox/overdrive/Nexus/Core/IKeyValueList.cs
new file mode 100644
index 0000000..1c584a3
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/IKeyValueList.cs
@@ -0,0 +1,12 @@
+using System.Collections;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// List KeyValue objects.
+ /// </summary>
+ public interface IKeyValueList : IList
+ {
+ string ValueFor(string key);
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/IRequestCatalog.cs b/struts-sandbox/overdrive/Nexus/Core/IRequestCatalog.cs
new file mode 100644
index 0000000..71cc0e6
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/IRequestCatalog.cs
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+using Agility.Core;
+using Nexus.Core.Helpers;
+using Nexus.Core.Tables;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Extend ICatalog to automatically set IFieldTable,
+ /// IMessageTable and provide convenience methods [OVR-8].
+ /// </summary>
+ ///
+ public interface IRequestCatalog : ICatalog
+ {
+ /// <summary>
+ /// Provide the FieldTable for this Catalog.
+ /// </summary>
+ /// <remarks><p>
+ /// The GetRequest methods "stamp" the Context
+ /// with a reference to the FieldTable,
+ /// among other things.
+ /// </p></remarks>
+ IFieldTable FieldTable { get; set; }
+
+ /// <summary>
+ /// Execute before a Command called via ExecuteView.
+ /// </summary>
+ /// <remarks><p>
+ /// Of course, a IRequestChain may be used here too.
+ /// </p></remarks>
+ ///
+ IRequestCommand PreOp { get; set; }
+
+ /// <summary>
+ /// Execute after a Command called via ExecuteView.
+ /// </summary>
+ /// <remarks><p>
+ /// Of course, a IRequestChain may be used here too.
+ /// </p></remarks>
+ ///
+ IRequestCommand PostOp { get; set; }
+
+ /// <summary>
+ /// Default IViewHelper instance for this Catalog.
+ /// </summary>
+ /// <remarks><p>
+ /// Set in catalogs for applications that use ViewHelpers.
+ /// The object should be a non-singleton instance ("protype").
+ /// Used by GetHelperFor.
+ /// </p></remarks>
+ ///
+ IViewHelper ViewHelper { get; set; }
+
+ /// <summary>
+ /// Obtain an object for ID.
+ /// </summary>
+ /// <param name="name">Our object ID</param>
+ /// <returns>object for name</returns>
+ object GetObject(string name);
+
+ /// <summary>
+ /// Obtain a default IViewHelper instance,
+ /// configured for the specified command.
+ /// </summary>
+ /// <param name="command">The Command ID</param>
+ /// <returns>Helper instance for command</returns>
+ IViewHelper GetHelperFor(string command);
+
+ /// <summary>
+ /// Obtain Command and verify that instance is a IRequestCommand.
+ /// </summary>
+ /// <param name="command">Command ID</param>
+ /// <returns>IRequestCommand instance for name</returns>
+ /// <exception cref="Exception">
+ /// Throws Exception if name is null,
+ /// name is not in catalog,
+ /// or if instance for name is not a IRequestCommand
+ /// </exception>
+ IRequestCommand GetRequestCommand(string command);
+
+ /// <summary>
+ /// Obtain a IRequestContext for command ID,
+ /// including embedded resources like the FieldTable,
+ /// </summary>
+ /// <param name="name">Our command ID</param>
+ /// <returns>IRequestContext with embedded resources.</returns>
+ ///
+ IRequestContext GetRequestContext(string name);
+
+ /// <summary>
+ /// Obtain a IRequestContext for command ID,
+ /// including embedded resources like the FieldTable,
+ /// and process string-based input.
+ /// </summary>
+ /// <param name="name">Our command ID</param>
+ /// <param name="input">Our input values</param>
+ /// <returns>IRequestContext with embedded resources.</returns>
+ ///
+ IRequestContext GetRequestContext(string name, IDictionary input);
+
+ /// <summary>
+ /// Obtain a IRequestContext for the command,
+ /// including embedded resources.
+ /// </summary>
+ /// <param name="command">Our command</param>
+ /// <returns>IRequestContext with embedded resources.</returns>
+ ///
+ IRequestContext GetRequestContext(IRequestCommand command);
+
+ /// <summary>
+ /// Obtain and execute a IRequestContext.
+ /// </summary>
+ /// <param name="name">Our command ID</param>
+ /// <returns>Context after execution</returns>
+ ///
+ IRequestContext ExecuteRequest(string name);
+
+ /// <summary>
+ /// Execute a IRequestContext.
+ /// </summary>
+ /// <param name="context">Context to execute</param>
+ ///
+ void ExecuteRequest(IRequestContext context);
+
+ /// <summary>
+ /// Execute a IRequestContext as part of a chain
+ /// created with the PreOp and PostOp commands (if any).
+ /// </summary>
+ /// <remarks><p>
+ /// Among other things, the PreOp/PostOp chain may transfer
+ /// data between the Criteria and the root Context.
+ /// </p><p>
+ /// The PreOp/PostOp chain acts as a Front Controller
+ /// in that it ensures certain tasks are perform
+ /// upon every request.
+ /// </p><p>
+ /// IViewHelper implementations are expected to
+ /// call ExecuteView to "invoke the Helper's command".
+ /// </p></remarks>
+ /// <param name="context">Context to execute</param>
+ ///
+ void ExecuteView(IRequestContext context);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/IRequestChain.cs b/struts-sandbox/overdrive/Nexus/Core/IRequestChain.cs
new file mode 100644
index 0000000..a8e1036
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/IRequestChain.cs
@@ -0,0 +1,11 @@
+using Agility.Core;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Composite IChain and IRequestCommand.
+ /// </summary>
+ public interface IRequestChain : IChain, IRequestCommand
+ {
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/IRequestCommand.cs b/struts-sandbox/overdrive/Nexus/Core/IRequestCommand.cs
new file mode 100644
index 0000000..b1f2699
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/IRequestCommand.cs
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+using Agility.Core;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Extend ICommand to utilize an IRequestContext [OVR-9]
+ /// </summary>
+ /// <remarks><p>
+ /// Rather than have each command cast its context to an
+ /// IRequestContext,
+ /// provide a IRequestCommand with an alternative signature.
+ /// </p></remarks>
+ ///
+ public interface IRequestCommand : ICommand
+ {
+ /// <summary>
+ /// An identifier for this Command.
+ /// </summary>
+ /// <remarks>
+ /// Corresponds to the Command property of IHelperContext.
+ /// </remarks>
+ /// <returns>An identifier for this Command.</returns>
+ ///
+ string ID { get; set; }
+
+ /// <summary>
+ /// An identifier for a Query associated with this Command (if any).
+ /// </summary>
+ /// <remarks>
+ /// If Query is not set, then ID is returned instead.
+ /// (The default QueryID is the command ID.)
+ /// </remarks>
+ /// <returns>An identifier for this Command.</returns>
+ string QueryID { get; set; }
+
+ /// <summary>
+ /// Factory method to provide an empty context that can be used
+ /// with the Command instance.
+ /// </summary>
+ /// <returns>Context instance with Command ID set.</returns>
+ ///
+ IRequestContext NewContext();
+
+ /// <summary>
+ /// Field IDs required by this Command.
+ /// </summary>
+ /// <remarks><p>
+ /// If requisite fields are not present in the main Context,
+ /// appropriate errors should be posted to the Errors property,
+ /// so that the client can correct the oversight and resubmit the request.
+ /// </p><p>
+ /// The RelatedIDs property may be used by the command itself,
+ /// or by a collaborating "conversion" command,
+ /// to confirm that related fields, when present, are in the expected format.
+ /// </p><p>
+ /// The RelatedIDs property may be used by the command itself,
+ /// or by a collaborating "validation" command,
+ /// to confirm that related fields, when present, are in the expected format.
+ /// </p></remarks>
+ IList RequiredIDs { get; set; }
+
+ /// <summary>
+ /// Add a IList of IDs to the list of {@link RequiredIds}.
+ ///</summary>
+ IList AddRequiredIDs { set; }
+
+ /// <summary>
+ /// Record FieldContext IDs related to this Command, including any RequiredIDs.
+ /// </summary>
+ /// <remarks><p>
+ /// If a Field ID is not specified as a RelatedID or a RequiredID,
+ /// than it may not be passed from the Criteria to the main Context,
+ /// and so will not be available to the Command.
+ /// </p><p>
+ /// As the field is passed from the Fieldstate to the main Context,
+ /// it may also be converted to the appropriate DataType or string format.
+ /// A collaborating Command may reference the FieldTable in a INexusContext
+ /// to ascertain the expected type or format for a value and
+ /// to obtain the appropriate error messages for each field.
+ /// </p><p>
+ /// The RelatedIDs property may be used by the command itself,
+ /// or by a collaborating "conversion" command,
+ /// to confirm that related fields, when present, are in the expected format.
+ /// </p><p>
+ /// Since posting errors and messages is a specialized concern,
+ /// it is recommended that collaborating Commands handle validation and confirmation.
+ /// </p><p>
+ /// A collaborating Command may reference the FieldTable in a INexusContext
+ /// to ascertain the expected format for a value and
+ /// to obtain the appropriate error messages for each field.
+ /// </p></remarks>
+ IList RelatedIDs { get; set; }
+
+ /// <summary>
+ /// Add a IList of IDs to the list of {@link RelatedIds}.
+ ///</summary>
+ IList AddRelatedIDs { set; }
+
+ /// <summary>
+ /// Record Field IDs provided during the processing of a Chain.
+ /// </summary>
+ /// <remarks><p>
+ /// When Commands are chained, the output from one Command may be used
+ /// as input for another Command. If a collaborating Command is
+ /// validating the Criteria for required input, prior to processing,
+ /// then Runtime FieldIDs may be excluded from the set of RequiredIDs.
+ /// </p><p>
+ /// The RuntimeIDs are expected to be set on a Chain rather than an individual
+ /// Command. The property is a member of the INexusCommand interface so that
+ /// Command and Chains can observe the substitution principle.
+ /// </p></remarks>
+ IList RuntimeIDs { get; set; }
+
+ /// <summary>
+ /// Add a IList of IDs to the list of {@link RuntimeIds}.
+ ///</summary>
+ IList AddRuntimeIDs { set; }
+
+ /// <summary>
+ /// Invoke the business operation.
+ /// </summary>
+ /// <remarks><p>
+ /// Expected to be called from Execute as a casting convenience.
+ /// </p></remarks>
+ /// <param name="context">Context to process.</param>
+ ///
+ bool RequestExecute(IRequestContext context);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/IRequestContext.cs b/struts-sandbox/overdrive/Nexus/Core/IRequestContext.cs
new file mode 100644
index 0000000..0ec25a8
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/IRequestContext.cs
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Agility.Core;
+using Nexus.Core.Profile;
+using Nexus.Core.Tables;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Exchange data between business and presentation layers [OVR-7].
+ /// </summary>
+ /// <remarks><p>
+ /// An IRequestContext can predefine whatever properties we need for
+ /// storing input, output, messages, and other common attributes,
+ /// including Locale (or Culture) and user credentials.
+ /// </p><p>
+ /// A key member is the FieldTable.
+ /// The FieldTable uses XForms terminology for its members
+ /// and IRequestContext members follow suit.
+ /// For example, "errors" are called "Alerts" and generic
+ /// messages are called "Hints,
+ /// since these are terms used by the FieldTable and XForms.
+ /// </p></remarks>
+ ///
+ public interface IRequestContext : IContext
+ {
+ #region Processing
+
+ /// <summary>
+ /// Identify the top-level Command (or Chain) processing
+ /// this Context.
+ /// </summary>
+ /// <remarks><P>
+ /// The Command property corresponds to ID of INexusCommand
+ /// for the initial Command or Chain.
+ /// </P></remarks>
+ ///
+ string Command { get; set; }
+
+ /// <summary>
+ /// Provide the top-level Command (or Chain) processing this Context.
+ /// </summary>
+ /// <remarks><p>
+ /// Command corresponds to ID of INexusCommand for the
+ /// initial Command or Chain.
+ /// </p></remarks>
+ ///
+ IRequestCommand CommandBin { get; set; }
+
+
+ /// <summary>
+ /// Provide the FieldTable for this Context.
+ /// </summary>
+ /// <remarks><p>
+ /// The default implementation uses the Catalog to inject the global
+ /// Field Table reference.
+ /// The Context, and members with access to a Context,
+ /// can use the FieldTable to validate and format values,
+ /// and even to create controls that display values.
+ /// </p></remarks>
+ ///
+ IFieldTable FieldTable { get; set; }
+
+ /// <summary>
+ /// User profile, which includes user ID and Locale.
+ /// </summary>
+ IProfile Profile { get; set; }
+
+ /// <summary>
+ /// Return true if an Outcome object is present.
+ /// </summary>
+ /// <returns>True if an Outcome context is present.</returns>
+ ///
+ bool HasOutcome { get; }
+
+ /// <summary>
+ /// Return a IList stored under the Command ID, if any.
+ /// </summary>
+ /// <remarks><p>
+ /// Some Commands returns List of values.
+ /// So that Commands can work together as part of a Chain,
+ /// list-based Commands are expected to store the
+ /// list under their own Command ID.
+ /// Outcome is a convenience method to access the
+ /// initial or "outermost" Command or Chain ID.
+ /// </p>
+ /// <p>
+ /// To allow use as subcommands in a Chain,
+ /// IRequestCommand implementations should prefer the idiom
+ /// <code>Context[ID] = object</code>
+ /// to using the Outcome directly.
+ /// Since they might not be the initial Command,
+ /// but rather a subcommand, or link, in a Chain.
+ /// </p><p>
+ /// Outcome is more convenient to presentation layer clients,
+ /// who are looking for the top-level output,
+ /// rather than output of a particular subcommand.
+ /// </p><p>
+ /// As mentioned, both Outcome and the context[ID] idiom
+ /// can be used by Command that return lists of values.
+ /// Commands that return a single set of fields
+ /// can store the result directly in the main Context.
+ /// This strategy allows one Command to obtain field values
+ /// to be used by another Command
+ /// (like piping output between Unix shell commands.)
+ /// </p><p>
+ /// Note that "Outcome" is an "alias" to an entry in
+ /// this context.
+ /// Unlike FieldState, Outcome is not a subcontext
+ /// in its own right.
+ /// </p></remarks>
+ ///
+ object Outcome { get; set; }
+
+ /// <summary>
+ /// Indicate whether a Criteria is present.
+ /// </summary>
+ /// <returns>True if a Criteria is present.</returns>
+ bool HasCriteria();
+
+ /// <summary>
+ /// Provide an optional subcontext containing input or output
+ /// values, usually expressed as display strings.
+ /// </summary>
+ /// <remarks>
+ /// <p>
+ /// Criteria is provided for Commands that accept input
+ /// from other components which may need to be validated,
+ /// converted, or formatted before use.
+ /// If the proposed FieldState is accepted,
+ /// the entries may be merged into the root Context,
+ /// perhaps after type conversion or formatting tasks.
+ /// If the proposed FieldState is not accepted,
+ /// the entries are not merged into the root Context,
+ /// and there should be Errors or a Fault explaining
+ /// why the FieldState (e.g input) cannot be accepted.
+ /// </p>
+ /// <p>
+ /// In practice, it is expected, but not required, that
+ /// all the FieldState entries will contain string values.
+ /// </p>
+ /// <p>
+ /// Commands should only act on the Criteria in order
+ /// to transfer values between the FieldState and the
+ /// root Context.
+ /// Conventional Commands will look to the root Context
+ /// for the state and make any expected changes
+ /// or additions directly to the root context.
+ /// FieldState is not expected to be used by a Commands
+ /// unless input is being submitted from an untrusted or
+ /// naive component, or needs to be transformed for use
+ /// by a display component.
+ /// </p>
+ /// </remarks>
+ IDictionary Criteria { get; set; }
+
+ #endregion
+
+ #region Messaging
+
+ string FormatTemplate(string template, string value);
+
+ /// <summary>
+ /// Record a list of alert (or error) messages,
+ /// keyed by the field causing the message,
+ /// or to a magic global key.
+ /// </summary>
+ /// <remark><p>
+ /// TODO: Refactor as NameValueCollection ?
+ /// </p></remark>
+ ///
+ IDictionary Alerts { get; set; }
+
+ /// <summary>
+ /// Add an alert message under the "global" key.
+ /// </summary>
+ /// <param name="template">Message template.</param>
+ ///
+ void AddAlert(string template);
+
+ /// <summary>
+ /// Add an alert message, creating the context if needed.
+ /// </summary>
+ /// <remarks>
+ /// Multiple messages can be added for a key and retrieved as a List.
+ /// </remarks>
+ /// <param name="template">Message template.</param>
+ /// <param name="message">Message key.</param>
+ void AddAlert(string template, string message);
+
+ /// <summary>
+ /// Add a formatted "Alert" error message
+ /// for the given field key via the FieldTable.
+ /// </summary>
+ /// <param name="key">Key from the FieldTable</param>
+ void AddAlertForField(string key);
+
+ /// <summary>
+ /// Add a formatted "Required" error message
+ /// for the given field key via the FieldTable.
+ /// </summary>
+ /// <param name="key">Key from the FieldTable</param>
+ void AddAlertRequired(string key);
+
+ /// <summary>
+ /// Indicate whether alerts exist.
+ /// </summary>
+ /// <returns>True if there are alerts.</returns>
+ ///
+ bool HasAlerts { get; }
+
+ /// <summary>
+ /// Record an Exception, if thrown.
+ /// </summary>
+ ///
+ Exception Fault { get; set; }
+
+ /// <summary>
+ /// Indicate whether an Exception was caught.
+ /// </summary>
+ /// <returns>True if an Exception was caught.</returns>
+ ///
+ bool HasFault { get; }
+
+ /// <summary>
+ /// Indicate whether context is free of fault and alerts.
+ /// </summary>
+ /// <returns>True if there are no fault or alerts.</returns>
+ ///
+ bool IsNominal { get; }
+
+ /// <summary>
+ /// Record hint (advisory or warning) messages (!errors),
+ /// keyed by the field causing the message,
+ /// or to a magic global key.
+ /// </summary>
+ ///
+ IDictionary Hints { get; set; }
+
+ /// <summary>
+ /// Add a hint, creating the context if needed.
+ /// </summary>
+ /// <remarks><p>
+ /// Multiple hints can be added for a key and
+ /// retrieved as a List.
+ /// </p></remarks>
+ /// <param name="template">Message template.</param>
+ /// <param name="message">Message key.</param>
+ ///
+ void AddHint(string template, string message);
+
+ /// <summary>
+ /// Add a hint under the "global" key.
+ /// </summary>
+ /// <param name="template">Message template.</param>
+ ///
+ void AddHint(string template);
+
+ /// <summary>
+ /// Indicate whether hints exist.
+ /// </summary>
+ /// <returns>True if there are hints.</returns>
+ ///
+ bool HasHints { get; }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/KeyValue.cs b/struts-sandbox/overdrive/Nexus/Core/KeyValue.cs
new file mode 100644
index 0000000..5e5ddf6
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/KeyValue.cs
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Implement IKeyValue.
+ /// </summary>
+ [Serializable]
+ public class KeyValue : IKeyValue
+ {
+
+ /// <summary>
+ /// Expose name of "Key" field.
+ /// </summary>
+ /// <remarks><p>
+ /// Use this field for the DataValueField (sic).
+ /// </p></remarks>
+ public const string KEY = "Key";
+
+ /// <summary>
+ /// Expose name of "Value" field.
+ /// </summary>
+ /// <remarks><p>
+ /// Use this field for the DataTextField (sic).
+ /// </p></remarks>
+ public const string VALUE= "Value";
+
+ public KeyValue()
+ {
+ ;
+ }
+
+ public KeyValue(string aKey, object aValue)
+ {
+ _Key = aKey;
+ _Value = aValue;
+ }
+
+ protected string _Key;
+
+ public virtual string Key
+ {
+ get { return _Key; }
+ set { _Key = value; }
+ }
+
+ protected object _Value;
+
+ public virtual object Value
+ {
+ get { return _Value; }
+ set { _Value = value; }
+ }
+
+ public virtual string Text
+ {
+ get { return _Value as string; }
+ set { _Value = Text; }
+ }
+
+ public override string ToString()
+ {
+ return Text;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/KeyValueList.cs b/struts-sandbox/overdrive/Nexus/Core/KeyValueList.cs
new file mode 100644
index 0000000..c28c9e9
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/KeyValueList.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Implement IKeyValueList.
+ /// </summary>
+ public class KeyValueList : IKeyValueList
+ {
+
+ private IList list;
+
+ /// <summary>
+ /// Construct instance without parameters.
+ /// </summary>
+ public KeyValueList()
+ {
+ list = new ArrayList();
+ }
+
+ public KeyValueList(IList _list)
+ {
+ list = _list;
+ }
+
+ /// <summary>
+ /// Add members of given list to this list.
+ /// </summary>
+ public virtual IList AddAll
+ {
+ set
+ {
+ foreach (object o in value)
+ {
+ list.Add(o);
+ }
+ }
+ }
+
+ public string ValueFor(string key)
+ {
+ if ((key == null) || (key.Equals(String.Empty))) return key;
+ foreach (IKeyValue kv in list)
+ {
+ if (key.Equals(kv.Key)) return kv.Value as string;
+ }
+ return null;
+ }
+
+ public int Add(object value)
+ {
+ return list.Add(value);
+ }
+
+ public bool Contains(object value)
+ {
+ return list.Contains(value);
+ }
+
+ public void Clear()
+ {
+ list.Clear();
+ }
+
+ public int IndexOf(object value)
+ {
+ return list.IndexOf(value);
+ }
+
+ public void Insert(int index, object value)
+ {
+ list.Insert(index,value);
+ }
+
+ public void Remove(object value)
+ {
+ list.Remove(value);
+ }
+
+ public void RemoveAt(int index)
+ {
+ list.RemoveAt(index);
+ }
+
+ public bool IsReadOnly
+ {
+ get { return list.IsReadOnly; }
+ }
+
+ public bool IsFixedSize
+ {
+ get { return list.IsFixedSize; }
+ }
+
+ public object this[int index]
+ {
+ get { return list[index]; }
+ set { list[index] = value; }
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ this.CopyTo(array,index);
+ }
+
+ public int Count
+ {
+ get { return list.Count; }
+ }
+
+ public object SyncRoot
+ {
+ get { return list.SyncRoot; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { return list.IsSynchronized; }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Nexus.Core.xml b/struts-sandbox/overdrive/Nexus/Core/Nexus.Core.xml
new file mode 100644
index 0000000..1763a76
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Nexus.Core.xml
@@ -0,0 +1,1778 @@
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>Nexus.Core</name>
+ </assembly>
+ <members>
+ <member name="T:WQD.Core.Controls.FindArgs">
+ <summary>
+ Provide an EventArgs type to interace with FindControls
+ that can be read or bound via an IDictionary object.
+ </summary>
+
+ </member>
+ <member name="F:WQD.Core.Controls.FindArgs.OldArgs">
+ <summary>
+ A reference to the original arguments for an event, if any.
+ </summary>
+
+ </member>
+ <member name="F:WQD.Core.Controls.FindArgs.Criteria">
+ <summary>
+ Expose our dictionary instance.
+ </summary>
+
+ </member>
+ <member name="M:WQD.Core.Controls.FindArgs.#ctor(System.Collections.IDictionary)">
+ <summary>
+ Create this instance using the given dictionary.
+ </summary>
+
+ </member>
+ <member name="M:WQD.Core.Controls.FindArgs.#ctor">
+ <summary>
+ Create a new instance with empty fields.
+ </summary>
+
+ </member>
+ <member name="M:WQD.Core.Controls.FindArgs.#ctor(System.EventArgs)">
+ <summary>
+ Create a new instance, setting the old event arguments.
+ </summary>
+ <param name="oldArgs">Old Event arguments</param>
+
+ </member>
+ <member name="T:Nexus.Core.Helpers.IViewHelper">
+ <summary>
+ Provide methods for running a business command and handling the result.
+ </summary>
+ <remarks><p>
+ IViewHelper is a facade for use by a code-behind to simplify access
+ to the IRequestContext and IRequestCommand.
+ </p><p>
+ The helper may also work with the catalog to act as a
+ "front controller" by ensuring routine tasks are carried out.
+ These tasks can include input validation, data conversion,
+ text formatting, command logging, and so forth.
+ </p></remarks>
+
+ </member>
+ <member name="M:Nexus.Core.Helpers.IViewHelper.Execute">
+ <summary>
+ Perform the Command associated with this Helper.
+ </summary>
+
+ </member>
+ <member name="M:Nexus.Core.Helpers.IViewHelper.Read(System.Collections.IDictionary,System.Boolean)">
+ <summary>
+ Read input into the Criteria from a given Dictionary.
+ </summary>
+ <param name="criteria">Attributes to add to Critiera</param>
+ <param name="nullIfEmpty">Set attributes for empty strings to null</param>
+
+ </member>
+ <member name="M:Nexus.Core.Helpers.IViewHelper.AlertsFor(System.String)">
+ <summary>
+ Return the Alerts for the specifiied ID,
+ formatted for display by a UI control.
+ </summary>
+ <remarks>
+ If messages are localized or customized,
+ the helper will return correct version for the user.
+ UI specific implementation may markup the errors as needed.
+ </remarks>
+
+ </member>
+ <member name="M:Nexus.Core.Helpers.IViewHelper.HintsFor(System.String)">
+ <summary>
+ Return the Hints for the specifiied ID,
+ formatted for display by a UI control.
+ </summary>
+ <remarks>
+ If messages are localized or customized,
+ the helper will return correct version for the user.
+ UI specific implementation may markup the errors as needed.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Criteria">
+ <summary>
+ Store input and output values.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Profile">
+ <summary>
+ User profile, which includes user ID and Locale.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Outcome">
+ <summary>
+ Access result of operation as an IList.
+ </summary>
+ <remarks><p>
+ If the Helper is designed to return a List result,
+ this method saves casting the outcome.
+ If the Helper is not designed to return the result as a IList,
+ this method returns a single-value result as a one-entry list.
+ </p><p>
+ Note this since this is the Helper Outcome,
+ the result is relative to the Criteria,
+ rather than the main Context.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Alerts">
+ <summary>
+ Record a list of alert (or error) messages,
+ keyed by the field causing the message,
+ or to a magic global key.
+ </summary>
+ <remarks>
+ When recalling Alerts, by default include the Fault.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.AlertsText">
+ <summary>
+ Return the Alerts, including any Fault, formatted for display by a UI control.
+ </summary>
+ <remarks>
+ If messages are localized or customized,
+ the helper will return correct version for the user.
+ UI specific implementation may markup the errors as needed.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.HasAlerts">
+ <summary>
+ Indicate if alerts are queued.
+ </summary>
+ <returns>True if alerts are queued.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Fault">
+ <summary>
+ Record an Exception, if thrown.
+ </summary>
+ <remarks>
+ By default, the Fault will be included in the list of Alerts.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.HasFault">
+ <summary>
+ Indicate whether an Exception is caught.
+ </summary>
+ <returns>True if an Exception is caught.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.IsNominal">
+ <summary>
+ Indicate if there are no alerts or fault pending.
+ </summary>
+ <returns>True if all is well.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Hints">
+ <summary>
+ Record a list of hint (or advisory) messages,
+ keyed by a field or other identifier,
+ or to a magic global key.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.HasHints">
+ <summary>
+ Indicate if Hints are queued.
+ </summary>
+ <returns>True if Hints are queued.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.HintsText">
+ <summary>
+ Return Hints formatted for display by a UI control.
+ </summary>
+ <remarks>
+ If messages are localized or customized,
+ the helper will return correct version for the user.
+ UI specific implementatiosn may markup the messages as needed.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.FieldTable">
+ <summary>
+ Provide the Field Table for this Helper.
+ </summary>
+ <remarks><p>
+ The default implementation uses the Catalog to inject the global
+ Field Table reference.
+ The Context, and members with access to a Context,
+ can use the FieldTable to validate and format values,
+ and even to create controls that display values.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Command">
+ <summary>
+ Provide the command (or chain of commands) for this helper
+ </summary>
+ <remarks><p>
+ Setting the Command also sets the internal Context for the command.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.FieldSet">
+ <summary>
+ Provide a set of IFieldContext definitions to be used with this helper.
+ </summary>
+ <remarks><p>
+ The FieldSet is usually set by dependency injection.
+ Some helpers generate DataGrids or DataForms based on the
+ FieldDefinitions
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.IViewHelper.Catalog">
+ <summary>
+ Provide the catalog for this helper,
+ usually set by dependency injection.
+ </summary>
+
+ </member>
+ <member name="T:Nexus.Core.Helpers.ViewArgs">
+ <summary>
+ EventArgs type with a IViewHelper property.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Helpers.ViewArgs.#ctor">
+ <summary>
+ Default constructor.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Helpers.ViewArgs.#ctor(Nexus.Core.Helpers.IViewHelper)">
+ <summary>
+ Convenience constructor to set helper.
+ </summary>
+ <param name="helper"></param>
+ </member>
+ <member name="P:Nexus.Core.Helpers.ViewArgs.Helper">
+ <summary>
+ Helper instance to encapsulate.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Helpers.ViewHelper">
+ <summary>
+ Standard implementation of IViewHelper.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Helpers.ViewHelper.LIST_SUFFIX">
+ <summary>
+ Default setting for ListSuffix ["_list"].
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Helpers.ViewHelper.NULL_IF_EMPTY">
+ <summary>
+ Default setting for NullIfEmpty [true].
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Helpers.ViewHelper.PREFIX">
+ <summary>
+ Default setting for Prefix [""].
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Helpers.ViewHelper.SELECT_ITEM_PROMPT">
+ <summary>
+ Default setting for SelectItemPrompt ["--v--"].
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.Helpers.ViewHelper.Catalog">
+ <summary>
+ Provide the application object catalog for this Helper.
+ </summary>
+ <remarks>
+ The Catalog is usually set through dependency injection.
+ The Catalog and Command must be set before calling other methods.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.ViewHelper.Command">
+ <summary>
+ Provide the command for this Helper.
+ </summary>
+ <remarks>
+ The Command is usually set through dependency injection.
+ The Catalog and Command must be set before calling other methods.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Helpers.ViewHelper.Context">
+ <summary>
+ Provide the all-important Context for this Helper.
+ </summary>
+ <remarks>
+ The Context is obtained through reference to the Catalog and Command.
+ All other properties and methods of the Helper refer to the Context,
+ making Context the cornerstone property.
+ </remarks>
+
+ </member>
+ <member name="T:Nexus.Core.Profile.IProfile">
+ <summary>
+ Record user settings.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Profile.IProfile.UserId">
+ <summary>
+ Record the User ID.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Profile.IProfile.UserLocale">
+ <summary>
+ Record the User Locale.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Profile.IProfile.Criteria">
+ <summary>
+ Record other default settings.
+ </summary>
+
+ </member>
+ <member name="T:Nexus.Core.Profile.UserIdentity">
+ <summary>
+ Implement IIdentity to capture user's login name.
+ </summary>
+ <remarks><p>
+ An identity object represents the user on whose behalf the code is running).
+ </p><p>
+ For this to work, we must update the Web.config and the server settings.
+ </p><p>
+ Web.config: <authentication mode="Windows" /> <identity impersonate="true"/>
+ </p><p>
+ IIS Admin: Disable Anon Access on the Directory Security tab.
+ </p></remarks>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserIdentity.#ctor">
+ <summary>
+ Instantiate with zero parameters.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserIdentity.#ctor(System.Security.Principal.IIdentity)">
+ <summary>
+ Instantiate with an IIdentity.
+ </summary>
+ <remarks>
+ Essentially, create a shallow copy of the given Identity.
+ </remarks>
+ <param name="id">Identity to copy</param>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserIdentity.#ctor(System.String,System.String,System.Boolean)">
+ <summary>
+ Instantiate from passed values.
+ </summary>
+ <param name="name">Value for user's name</param>
+ <param name="authenticationType">Value for AuthenticationType</param>
+ <param name="isAuthenticated">Value for IsAuthenticated</param>
+ </member>
+ <member name="T:Nexus.Core.Profile.UserPrincipal">
+ <summary>
+ Implement IPrincipal to capture the user's login name.
+ </summary>
+ <remarks><p>
+ IPrincipal - A principal object represents the security context of the
+ user on whose behalf the code is running, including that user's identity
+ (IIdentity) and any roles to which they belong.
+ </p></remarks>
+ </member>
+ <member name="F:Nexus.Core.Profile.UserPrincipal._Roles">
+ <summary>
+ Field for Roles property.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserPrincipal.#ctor">
+ <summary>
+ Instantiate default NexusPrincipal with empty NexusIdentity.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserPrincipal.#ctor(System.Security.Principal.IIdentity)">
+ <summary>
+ Instantiate from an IIdentity.
+ </summary>
+ <remarks>
+ The Roles for this principal will follow
+ those set by the Roles property, regardless of the
+ Identity or Authentication Type.
+ </remarks>
+ <param name="id">Value for user name</param>
+ </member>
+ <member name="P:Nexus.Core.Profile.UserPrincipal.Roles">
+ <summary>
+ The roles for this principal representated as an array.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Profile.UserProfile">
+ <summary>
+ Represent a user.
+ </summary>
+ <remarks><p>
+ The UserProfile includes a standard Principal object for
+ authentification and authorization.
+ Any user-related properties may be added here, along with
+ convenience methods for determining roles, such as
+ IsEngineer, IsManager, et al.
+ </p></remarks>
+ </member>
+ <member name="F:Nexus.Core.Profile.UserProfile.USER_PROFILE">
+ <summary>
+ Identify attribute key for storing a user profile.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Profile.UserProfile.USER_ID">
+ <summary>
+ Identify attribute key for storing a user ID;.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Profile.UserProfile.USER_ID_SEPARATOR">
+ <summary>
+ Identify the character separating a "machine name" from a "user id".
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserProfile.TrimMachineName(System.String)">
+ <summary>
+ Trim any machine name reference from Principal Name.
+ </summary>
+ <param name="name">A Identity Name that may contain a machine name reference</param>
+ <returns>Identity name with machine name removed</returns>
+ </member>
+ <member name="F:Nexus.Core.Profile.UserProfile._UserLocale">
+ <summary>
+ Provide a field for UserLocale property.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Profile.UserProfile._Criteria">
+ <summary>
+ Provide a field for Criteria property.
+ </summary>
+
+ </member>
+ <member name="M:Nexus.Core.Profile.UserProfile.#ctor">
+ <summary>
+ Instantiate a default profile.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserProfile.#ctor(System.Security.Principal.IPrincipal)">
+ <summary>
+ Instantiate from an IPrincipal.
+ </summary>
+ <param name="principal">Principal for this profile.</param>
+ </member>
+ <member name="M:Nexus.Core.Profile.UserProfile.#ctor(System.Security.Principal.IIdentity)">
+ <summary>
+ Instantiate from an IIdentity.
+ </summary>
+ <param name="id">Identity to copy for this profile.</param>
+ </member>
+ <member name="P:Nexus.Core.Profile.UserProfile.Principal">
+ <summary>
+ Provide the Principal object for this user.
+ </summary>
+ <remarks><p>
+ Usually, this is a UserPrincipal,
+ but any IPrincipal instance could be used.
+ </p></remarks>
+ </member>
+ <member name="P:Nexus.Core.Profile.UserProfile.UserId">
+ <summary>
+ Record the user id portion of the Identity Name.
+ </summary>
+ <remarks><p>
+ The UserId can be used to relate staff records to user logins.
+ </p></remarks>
+ </member>
+ <member name="T:Nexus.Core.Tables.FieldContext">
+ <summary>
+ Concrete IFieldContext implementation.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Tables.IFieldContext">
+ <summary>
+ Provide properties common to controls,
+ including Alert, ControlType, and Processor.
+ </summary>
+ <remark><p>
+ The FieldContext entries are made available through a FieldTable.
+ The FieldContext members follow XForms terminology.
+ </p><p>
+ XForms [http://www.w3.org/MarkUp/Forms/].
+ XForms Controls [http://www.orbeon.com/ops/doc/processors-xforms].
+ XPath 2.0 for .NET [http://sourceforge.net/projects/saxondotnet/].
+ </p><p>
+ To globalize an application,
+ utilize a IFieldContext implementation that supports localization.
+ A localized implementation can access a message resource to obtain text and messages,
+ rather than a simple property.
+ Localized implementations should also dissallow setting the text properties,
+ since those values would be provided through a message resource.
+ </p><p>
+ For a localized implementation, see Nexus.Core.Extras.Spring.FieldContext.
+ </p></remark>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.Alert">
+ <summary>
+ Provide a message to display when input validation fails.
+ </summary>
+ <remarks>
+ If the Processor also provides an Alert,
+ the Processor's Alert should be returned instead.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.ControlTypeName">
+ <summary>
+ Identify name of the default Control Type.
+ </summary>
+ <remarks><p>
+ Standard control types are: input, secret, textarea, select1, select, submit, upload.
+ </p><p>
+ XForms distinguishes between Lists, Radio Buttons, and CheckBoxes through additional
+ parameters. For now, all three can be identified as select1 or select.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.Help">
+ <summary>
+ Provide text to display for a context-sensitive help screen.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.Hint">
+ <summary>
+ Record an onscreen or hover hint.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.ID">
+ <summary>
+ Identify this field with a unique name.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.Label">
+ <summary>
+ Provide a label for the control.
+ </summary>
+ <remarks><p>
+ If the Label is null, the ID should be returned instead.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.Processor">
+ <summary>
+ Provide the processor for this field context.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldContext.Required">
+ <summary>
+ Provide a message to display when required input is missing.
+ </summary>
+
+ </member>
+ <member name="T:Nexus.Core.Tables.FieldTable">
+ <summary>
+ Implement IFieldTable.
+ </summary>
+ <remarks><p>
+ Validator
+ * Needs configurable nullvalue support
+ ** String, nullValue=""
+ ** Double, nullValue=0.0"
+ ** DataType, allowNull
+ * If they give us something, and it fails conversion, then validation fails.
+ * If they give us null or an empty string, and the property has a nullValue, then the nullValue is used.
+ * If they give us null or an empty string, or the nullValue, and the property is required, then validation fails.
+ </p></remarks>
+ </member>
+ <member name="T:Nexus.Core.Tables.IFieldTable">
+ <summary>
+ Inventory of fields and processors used by the application.
+ </summary>
+
+ </member>
+ <member name="M:Nexus.Core.Tables.IFieldTable.NewFieldContext(System.String)">
+ <summary>
+ Factory method to create a stub context
+ when field is required and Strict is false.
+ </summary>
+ <remarks><p>
+ The IFieldContext instance should provide a default for Required.
+ </p></remarks>
+ <param name="id">The fieldname</param>
+ <returns>New default context for ID</returns>
+ </member>
+ <member name="M:Nexus.Core.Tables.IFieldTable.GetFieldContext(System.String)">
+ <summary>
+ Obtain the FieldContext for the given ID, observing Strict setting.
+ </summary>
+ <param name="id">FieldContext ID</param>
+ <returns>FieldContext for ID</returns>
+
+ </member>
+ <member name="M:Nexus.Core.Tables.IFieldTable.Alert(System.String)">
+ <summary>
+ Provide the Alert message for a given field id.
+ </summary>
+ <param name="id">FieldContext ID</param>
+ <returns>Alert message for FieldContext ID</returns>
+
+ </member>
+ <member name="M:Nexus.Core.Tables.IFieldTable.Label(System.String)">
+ <summary>
+ Provide the Label message for a given field id.
+ </summary>
+ <param name="id">FieldContext ID</param>
+ <returns>Alert message for FieldContext ID</returns>
+
+ </member>
+ <member name="M:Nexus.Core.Tables.IFieldTable.Required(System.String)">
+ <summary>
+ Provide the Required message for a given field id.
+ </summary>
+ <param name="id">FieldContext ID</param>
+ <returns>Required message for FieldContext ID</returns>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldTable.Strict">
+ <summary>
+ Indicate whether this FieldTable must include all fields,
+ including strings fields [FALSE].
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldTable.AddFieldContext">
+ <summary>
+ Add a field to the set.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldTable.AddFieldContexts">
+ <summary>
+ Add a list of fields to the set.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldTable.AddProcessor">
+ <summary>
+ Add a Processor to the set.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.Tables.IFieldTable.AddProcessors">
+ <summary>
+ Add a list of Processors to the set.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Tables.FieldTable.#ctor">
+ <summary>
+ Create instance with zero paramters.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.Tables.FieldTable.Field">
+ <summary>
+ Internal storage for the FieldContexts.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.Tables.FieldTable.Processor">
+ <summary>
+ Internal storage for the Processors.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Validators.ClearContext">
+ <summary>
+ Clear from the Context any keys present in the Criteria,
+ so that, if the context is re-used, values from a prior request do not linger.
+ </summary>
+ <remarks><p>
+ Once the values are output from the Context to the Criteria,
+ they can be safely removed from the Context.
+ </p><p>This command can be used as part of a post-opt chain to ensure that
+ Context values are not retained if a Context object is used for multiple
+ business requests.
+ </p></remarks>
+ </member>
+ <member name="T:Nexus.Core.RequestCommand">
+ <summary>
+ Implement IRequestCommand, leaving RequestExecute abstract.
+ </summary>
+
+ </member>
+ <member name="T:Nexus.Core.IRequestCommand">
+ <summary>
+ Extend ICommand to utilize an IRequestContext [OVR-9]
+ </summary>
+ <remarks><p>
+ Rather than have each command cast its context to an
+ IRequestContext,
+ provide a IRequestCommand with an alternative signature.
+ </p></remarks>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCommand.NewContext">
+ <summary>
+ Factory method to provide an empty context that can be used
+ with the Command instance.
+ </summary>
+ <returns>Context instance with Command ID set.</returns>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCommand.RequestExecute(Nexus.Core.IRequestContext)">
+ <summary>
+ Invoke the business operation.
+ </summary>
+ <remarks><p>
+ Expected to be called from Execute as a casting convenience.
+ </p></remarks>
+ <param name="context">Context to process.</param>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.ID">
+ <summary>
+ An identifier for this Command.
+ </summary>
+ <remarks>
+ Corresponds to the Command property of IHelperContext.
+ </remarks>
+ <returns>An identifier for this Command.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.QueryID">
+ <summary>
+ An identifier for a Query associated with this Command (if any).
+ </summary>
+ <remarks>
+ If Query is not set, then ID is returned instead.
+ (The default QueryID is the command ID.)
+ </remarks>
+ <returns>An identifier for this Command.</returns>
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.RequiredIDs">
+ <summary>
+ Field IDs required by this Command.
+ </summary>
+ <remarks><p>
+ If requisite fields are not present in the main Context,
+ appropriate errors should be posted to the Errors property,
+ so that the client can correct the oversight and resubmit the request.
+ </p><p>
+ The RelatedIDs property may be used by the command itself,
+ or by a collaborating "conversion" command,
+ to confirm that related fields, when present, are in the expected format.
+ </p><p>
+ The RelatedIDs property may be used by the command itself,
+ or by a collaborating "validation" command,
+ to confirm that related fields, when present, are in the expected format.
+ </p></remarks>
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.AddRequiredIDs">
+ <summary>
+ Add a IList of IDs to the list of {@link RequiredIds}.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.RelatedIDs">
+ <summary>
+ Record FieldContext IDs related to this Command, including any RequiredIDs.
+ </summary>
+ <remarks><p>
+ If a Field ID is not specified as a RelatedID or a RequiredID,
+ than it may not be passed from the Criteria to the main Context,
+ and so will not be available to the Command.
+ </p><p>
+ As the field is passed from the Fieldstate to the main Context,
+ it may also be converted to the appropriate DataType or string format.
+ A collaborating Command may reference the FieldTable in a INexusContext
+ to ascertain the expected type or format for a value and
+ to obtain the appropriate error messages for each field.
+ </p><p>
+ The RelatedIDs property may be used by the command itself,
+ or by a collaborating "conversion" command,
+ to confirm that related fields, when present, are in the expected format.
+ </p><p>
+ Since posting errors and messages is a specialized concern,
+ it is recommended that collaborating Commands handle validation and confirmation.
+ </p><p>
+ A collaborating Command may reference the FieldTable in a INexusContext
+ to ascertain the expected format for a value and
+ to obtain the appropriate error messages for each field.
+ </p></remarks>
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.AddRelatedIDs">
+ <summary>
+ Add a IList of IDs to the list of {@link RelatedIds}.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.RuntimeIDs">
+ <summary>
+ Record Field IDs provided during the processing of a Chain.
+ </summary>
+ <remarks><p>
+ When Commands are chained, the output from one Command may be used
+ as input for another Command. If a collaborating Command is
+ validating the Criteria for required input, prior to processing,
+ then Runtime FieldIDs may be excluded from the set of RequiredIDs.
+ </p><p>
+ The RuntimeIDs are expected to be set on a Chain rather than an individual
+ Command. The property is a member of the INexusCommand interface so that
+ Command and Chains can observe the substitution principle.
+ </p></remarks>
+ </member>
+ <member name="P:Nexus.Core.IRequestCommand.AddRuntimeIDs">
+ <summary>
+ Add a IList of IDs to the list of {@link RuntimeIds}.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.RequestCommand.STOP">
+ <summary>
+ Execute should return STOP if problem occurs,
+ so that a Chain can exit processing on error.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.RequestCommand.CONTINUE">
+ <summary>
+ Return CONTINUE if another Command could run.
+ </summary>
+
+ </member>
+ <member name="M:Nexus.Core.Validators.ClearContext.RequestExecute(Nexus.Core.IRequestContext)">
+ <summary>
+ Clear from the Context any keys present in the Criteria.
+ </summary>
+ <param name="context">Context after attributes have been output to Criteria</param>
+ <returns>CONTINUE</returns>
+ </member>
+ <member name="T:Nexus.Core.Validators.Processor">
+ <summary>
+ Implement common properties.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Validators.IProcessor">
+ <summary>
+ Convert or Format a standard or custom DataType.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Validators.ConvertInput">
+ <summary>
+ Convert related fields from Criteria to the main context,
+ adding an Alert message to Errors if a conversion fails.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Validators.ProcessorCommand">
+ <summary>
+ Provide a base class to use when implementating Validators.
+ </summary>
+ <remarks>
+ Subclasses must provide a NexusExecute method.
+ </remarks>
+ </member>
+ <member name="T:Nexus.Core.Validators.IProcessorCommand">
+ <summary>
+ Transform values from one data type or format to another. [OVR-13].
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Validators.IProcessorCommand.ExecuteProcess(Nexus.Core.Validators.IProcessorContext)">
+ <summary>
+ Transform the value indicated by the context FieldKey, if present.
+ </summary>
+ <param name="context">The context we are processing</param>
+ <returns>True if nominal</returns>
+ </member>
+ <member name="M:Nexus.Core.Validators.IProcessorCommand.ExecuteConvert(Nexus.Core.Validators.IProcessorContext)">
+ <summary>
+ Convert a field value, utlitizing the field table and processor.
+ </summary>
+ <param name="context">The context we are processing</param>
+ <returns>True if nominal</returns>
+ </member>
+ <member name="M:Nexus.Core.Validators.IProcessorCommand.ExecuteFormat(Nexus.Core.Validators.IProcessorContext)">
+ <summary>
+ Format a field value, utlitizing the field table and processor.
+ </summary>
+ <param name="context">The context we are processing</param>
+ <returns>True if nominal</returns>
+ </member>
+ <member name="P:Nexus.Core.Validators.IProcessorCommand.Required">
+ <summary>
+ Provide a message template to use when a required field is missing.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.Validators.ProcessorCommand.ConvertInput(Nexus.Core.Validators.IProcessorContext)">
+ <summary>
+ Convert input for fields that do not have a Processor.
+ </summary>
+ <remarks>
+ The default behavior is to pass through the objects, verbatim.
+ </remarks>
+ <param name="context">The IProcessorContext</param>
+ </member>
+ <member name="M:Nexus.Core.Validators.ProcessorCommand.FormatOutput(Nexus.Core.Validators.IProcessorContext)">
+ <summary>
+ Format output for fields that do not have a Processor.
+ </summary>
+ <remarks>
+ The default behavior is to pass through nulls and ICollection types
+ and to call ToString on everything else.
+ </remarks>
+ <param name="context">The IProcessorContext</param>
+ </member>
+ <member name="T:Nexus.Core.Validators.DateTimeProcessor">
+ <summary>
+ Convert and format DateTime fields.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Validators.EntryListProcessor">
+ <summary>
+ Transform IDictionary entries into formatted entries on a IEntryList instances.
+ </summary>
+ <remarks><p>
+ To implement, override NewEntryList to provide an instances of the desired type.
+ This will usually be an IEntryList that creates the entry objects used by your application.
+ The entry objects can be conventional property objects,
+ or objects that expose properties backed by an IDictionary, as you prefer.
+ </p></remarks>
+
+ </member>
+ <member name="M:Nexus.Core.Validators.EntryListProcessor.NewEntryList">
+ <summary>
+ Override to return an instance of the desired IEntryList type.
+ </summary>
+ <returns>An IEntryList instance</returns>
+ </member>
+ <member name="T:Nexus.Core.Validators.FormatOutput">
+ <summary>
+ Format related fields from the main context to Criteria,
+ adding an error message to Alerts if formatting fails.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Validators.IProcessorContext">
+ <summary>
+ Encapsulate values needed by standard IProcessorCommands [OVR-13].
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Validators.IProcessorContext.FieldKey">
+ <summary>
+ Identify the field under validation.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Validators.IProcessorContext.Source">
+ <summary>
+ Record the source value to process.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Validators.IProcessorContext.Target">
+ <summary>
+ Record the target value after conversion or formatting.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.Validators.IProcessorContext.Context">
+ <summary>
+ Identify the main IRequestContext being processed.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.Validators.IProcessorContext.Criteria">
+ <summary>
+ Identify the set of input/output fields being processed.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.Validators.IProcessorContext.FieldTable">
+ <summary>
+ Identify the FieldTable being utilized.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.Validators.KeyValueProcessor">
+ <summary>
+ Process the value of a KeyValue list
+ by setting the Key property to the Field's ID.
+ </summary>
+ </member>
+ <member name="T:Agility.Nexus.Validators.ProcessorContext">
+ <summary>
+ Implement IProcessorContext.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.IEntryList">
+ <summary>
+ A list of a set of Fields, such as displayed as the result of a query.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.IEntryList.Insert(System.String)">
+ <summary>
+ Create and Insert a new entry object at index 0.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.IEntryList.AddEntry(System.Collections.IDictionary)">
+ <summary>
+ Add a entry object based on an IDictionary.
+ </summary>
+ <param name="row"></param>
+ </member>
+ <member name="T:Nexus.Core.IKeyValue">
+ <summary>
+ Represent a key/value pair,
+ as stored in an IDictionary or displayed
+ by a list in a user interface.
+ </summary>
+ <remarks>
+ The Text method returns the string form of Value,
+ which is useful for text-based controls.
+ </remarks>
+
+ </member>
+ <member name="P:Nexus.Core.IKeyValue.Key">
+ <summary>
+ The Key property under which the Value is stored.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.IKeyValue.Value">
+ <summary>
+ The Value stored for the Key.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.IKeyValue.Text">
+ <summary>
+ The Value in its standard string format.
+ </summary>
+
+ </member>
+ <member name="T:Nexus.Core.IKeyValueList">
+ <summary>
+ List KeyValue objects.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.IRequestCatalog">
+ <summary>
+ Extend ICatalog to automatically set IFieldTable,
+ IMessageTable and provide convenience methods [OVR-8].
+ </summary>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.GetObject(System.String)">
+ <summary>
+ Obtain an object for ID.
+ </summary>
+ <param name="name">Our object ID</param>
+ <returns>object for name</returns>
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.GetHelperFor(System.String)">
+ <summary>
+ Obtain a default IViewHelper instance,
+ configured for the specified command.
+ </summary>
+ <param name="command">The Command ID</param>
+ <returns>Helper instance for command</returns>
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.GetRequestCommand(System.String)">
+ <summary>
+ Obtain Command and verify that instance is a IRequestCommand.
+ </summary>
+ <param name="command">Command ID</param>
+ <returns>IRequestCommand instance for name</returns>
+ <exception cref="!:Exception">
+ Throws Exception if name is null,
+ name is not in catalog,
+ or if instance for name is not a IRequestCommand
+ </exception>
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.GetRequestContext(System.String)">
+ <summary>
+ Obtain a IRequestContext for command ID,
+ including embedded resources like the FieldTable,
+ </summary>
+ <param name="name">Our command ID</param>
+ <returns>IRequestContext with embedded resources.</returns>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.GetRequestContext(System.String,System.Collections.IDictionary)">
+ <summary>
+ Obtain a IRequestContext for command ID,
+ including embedded resources like the FieldTable,
+ and process string-based input.
+ </summary>
+ <param name="name">Our command ID</param>
+ <param name="input">Our input values</param>
+ <returns>IRequestContext with embedded resources.</returns>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.GetRequestContext(Nexus.Core.IRequestCommand)">
+ <summary>
+ Obtain a IRequestContext for the command,
+ including embedded resources.
+ </summary>
+ <param name="command">Our command</param>
+ <returns>IRequestContext with embedded resources.</returns>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.ExecuteRequest(System.String)">
+ <summary>
+ Obtain and execute a IRequestContext.
+ </summary>
+ <param name="name">Our command ID</param>
+ <returns>Context after execution</returns>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.ExecuteRequest(Nexus.Core.IRequestContext)">
+ <summary>
+ Execute a IRequestContext.
+ </summary>
+ <param name="context">Context to execute</param>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestCatalog.ExecuteView(Nexus.Core.IRequestContext)">
+ <summary>
+ Execute a IRequestContext as part of a chain
+ created with the PreOp and PostOp commands (if any).
+ </summary>
+ <remarks><p>
+ Among other things, the PreOp/PostOp chain may transfer
+ data between the Criteria and the root Context.
+ </p><p>
+ The PreOp/PostOp chain acts as a Front Controller
+ in that it ensures certain tasks are perform
+ upon every request.
+ </p><p>
+ IViewHelper implementations are expected to
+ call ExecuteView to "invoke the Helper's command".
+ </p></remarks>
+ <param name="context">Context to execute</param>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestCatalog.FieldTable">
+ <summary>
+ Provide the FieldTable for this Catalog.
+ </summary>
+ <remarks><p>
+ The GetRequest methods "stamp" the Context
+ with a reference to the FieldTable,
+ among other things.
+ </p></remarks>
+ </member>
+ <member name="P:Nexus.Core.IRequestCatalog.PreOp">
+ <summary>
+ Execute before a Command called via ExecuteView.
+ </summary>
+ <remarks><p>
+ Of course, a IRequestChain may be used here too.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestCatalog.PostOp">
+ <summary>
+ Execute after a Command called via ExecuteView.
+ </summary>
+ <remarks><p>
+ Of course, a IRequestChain may be used here too.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestCatalog.ViewHelper">
+ <summary>
+ Default IViewHelper instance for this Catalog.
+ </summary>
+ <remarks><p>
+ Set in catalogs for applications that use ViewHelpers.
+ The object should be a non-singleton instance ("protype").
+ Used by GetHelperFor.
+ </p></remarks>
+
+ </member>
+ <member name="T:Nexus.Core.IRequestChain">
+ <summary>
+ Composite IChain and IRequestCommand.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.IRequestContext">
+ <summary>
+ Exchange data between business and presentation layers [OVR-7].
+ </summary>
+ <remarks><p>
+ An IRequestContext can predefine whatever properties we need for
+ storing input, output, messages, and other common attributes,
+ including Locale (or Culture) and user credentials.
+ </p><p>
+ A key member is the FieldTable.
+ The FieldTable uses XForms terminology for its members
+ and IRequestContext members follow suit.
+ For example, "errors" are called "Alerts" and generic
+ messages are called "Hints,
+ since these are terms used by the FieldTable and XForms.
+ </p></remarks>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestContext.HasCriteria">
+ <summary>
+ Indicate whether a Criteria is present.
+ </summary>
+ <returns>True if a Criteria is present.</returns>
+ </member>
+ <member name="M:Nexus.Core.IRequestContext.AddAlert(System.String)">
+ <summary>
+ Add an alert message under the "global" key.
+ </summary>
+ <param name="template">Message template.</param>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestContext.AddAlert(System.String,System.String)">
+ <summary>
+ Add an alert message, creating the context if needed.
+ </summary>
+ <remarks>
+ Multiple messages can be added for a key and retrieved as a List.
+ </remarks>
+ <param name="template">Message template.</param>
+ <param name="message">Message key.</param>
+ </member>
+ <member name="M:Nexus.Core.IRequestContext.AddAlertForField(System.String)">
+ <summary>
+ Add a formatted "Alert" error message
+ for the given field key via the FieldTable.
+ </summary>
+ <param name="key">Key from the FieldTable</param>
+ </member>
+ <member name="M:Nexus.Core.IRequestContext.AddAlertRequired(System.String)">
+ <summary>
+ Add a formatted "Required" error message
+ for the given field key via the FieldTable.
+ </summary>
+ <param name="key">Key from the FieldTable</param>
+ </member>
+ <member name="M:Nexus.Core.IRequestContext.AddHint(System.String,System.String)">
+ <summary>
+ Add a hint, creating the context if needed.
+ </summary>
+ <remarks><p>
+ Multiple hints can be added for a key and
+ retrieved as a List.
+ </p></remarks>
+ <param name="template">Message template.</param>
+ <param name="message">Message key.</param>
+
+ </member>
+ <member name="M:Nexus.Core.IRequestContext.AddHint(System.String)">
+ <summary>
+ Add a hint under the "global" key.
+ </summary>
+ <param name="template">Message template.</param>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.Command">
+ <summary>
+ Identify the top-level Command (or Chain) processing
+ this Context.
+ </summary>
+ <remarks><P>
+ The Command property corresponds to ID of INexusCommand
+ for the initial Command or Chain.
+ </P></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.CommandBin">
+ <summary>
+ Provide the top-level Command (or Chain) processing this Context.
+ </summary>
+ <remarks><p>
+ Command corresponds to ID of INexusCommand for the
+ initial Command or Chain.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.FieldTable">
+ <summary>
+ Provide the FieldTable for this Context.
+ </summary>
+ <remarks><p>
+ The default implementation uses the Catalog to inject the global
+ Field Table reference.
+ The Context, and members with access to a Context,
+ can use the FieldTable to validate and format values,
+ and even to create controls that display values.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.Profile">
+ <summary>
+ User profile, which includes user ID and Locale.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.HasOutcome">
+ <summary>
+ Return true if an Outcome object is present.
+ </summary>
+ <returns>True if an Outcome context is present.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.Outcome">
+ <summary>
+ Return a IList stored under the Command ID, if any.
+ </summary>
+ <remarks><p>
+ Some Commands returns List of values.
+ So that Commands can work together as part of a Chain,
+ list-based Commands are expected to store the
+ list under their own Command ID.
+ Outcome is a convenience method to access the
+ initial or "outermost" Command or Chain ID.
+ </p>
+ <p>
+ To allow use as subcommands in a Chain,
+ IRequestCommand implementations should prefer the idiom
+ <code>Context[ID] = object</code>
+ to using the Outcome directly.
+ Since they might not be the initial Command,
+ but rather a subcommand, or link, in a Chain.
+ </p><p>
+ Outcome is more convenient to presentation layer clients,
+ who are looking for the top-level output,
+ rather than output of a particular subcommand.
+ </p><p>
+ As mentioned, both Outcome and the context[ID] idiom
+ can be used by Command that return lists of values.
+ Commands that return a single set of fields
+ can store the result directly in the main Context.
+ This strategy allows one Command to obtain field values
+ to be used by another Command
+ (like piping output between Unix shell commands.)
+ </p><p>
+ Note that "Outcome" is an "alias" to an entry in
+ this context.
+ Unlike FieldState, Outcome is not a subcontext
+ in its own right.
+ </p></remarks>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.Criteria">
+ <summary>
+ Provide an optional subcontext containing input or output
+ values, usually expressed as display strings.
+ </summary>
+ <remarks>
+ <p>
+ Criteria is provided for Commands that accept input
+ from other components which may need to be validated,
+ converted, or formatted before use.
+ If the proposed FieldState is accepted,
+ the entries may be merged into the root Context,
+ perhaps after type conversion or formatting tasks.
+ If the proposed FieldState is not accepted,
+ the entries are not merged into the root Context,
+ and there should be Errors or a Fault explaining
+ why the FieldState (e.g input) cannot be accepted.
+ </p>
+ <p>
+ In practice, it is expected, but not required, that
+ all the FieldState entries will contain string values.
+ </p>
+ <p>
+ Commands should only act on the Criteria in order
+ to transfer values between the FieldState and the
+ root Context.
+ Conventional Commands will look to the root Context
+ for the state and make any expected changes
+ or additions directly to the root context.
+ FieldState is not expected to be used by a Commands
+ unless input is being submitted from an untrusted or
+ naive component, or needs to be transformed for use
+ by a display component.
+ </p>
+ </remarks>
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.Alerts">
+ <summary>
+ Record a list of alert (or error) messages,
+ keyed by the field causing the message,
+ or to a magic global key.
+ </summary>
+ <remark><p>
+ TODO: Refactor as NameValueCollection ?
+ </p></remark>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.HasAlerts">
+ <summary>
+ Indicate whether alerts exist.
+ </summary>
+ <returns>True if there are alerts.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.Fault">
+ <summary>
+ Record an Exception, if thrown.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.HasFault">
+ <summary>
+ Indicate whether an Exception was caught.
+ </summary>
+ <returns>True if an Exception was caught.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.IsNominal">
+ <summary>
+ Indicate whether context is free of fault and alerts.
+ </summary>
+ <returns>True if there are no fault or alerts.</returns>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.Hints">
+ <summary>
+ Record hint (advisory or warning) messages (!errors),
+ keyed by the field causing the message,
+ or to a magic global key.
+ </summary>
+
+ </member>
+ <member name="P:Nexus.Core.IRequestContext.HasHints">
+ <summary>
+ Indicate whether hints exist.
+ </summary>
+ <returns>True if there are hints.</returns>
+
+ </member>
+ <member name="T:Nexus.Core.KeyValue">
+ <summary>
+ Implement IKeyValue.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.KeyValue.KEY">
+ <summary>
+ Expose name of "Key" field.
+ </summary>
+ <remarks><p>
+ Use this field for the DataValueField (sic).
+ </p></remarks>
+ </member>
+ <member name="F:Nexus.Core.KeyValue.VALUE">
+ <summary>
+ Expose name of "Value" field.
+ </summary>
+ <remarks><p>
+ Use this field for the DataTextField (sic).
+ </p></remarks>
+ </member>
+ <member name="T:Nexus.Core.KeyValueList">
+ <summary>
+ Implement IKeyValueList.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.KeyValueList.#ctor">
+ <summary>
+ Construct instance without parameters.
+ </summary>
+ </member>
+ <member name="P:Nexus.Core.KeyValueList.AddAll">
+ <summary>
+ Add members of given list to this list.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.RequestChain">
+ <summary>
+ Implement IRequestChain.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.RequestContext">
+ <summary>
+ Implement IRequestContext.
+ </summary>
+
+ </member>
+ <member name="M:Nexus.Core.RequestContext.ToString">
+ <summary>
+ Express state as a key=value list.
+ </summary>
+ <returns>Formatted string representing state.</returns>
+ </member>
+ <member name="M:Nexus.Core.RequestContext.#ctor(System.String)">
+ <summary>
+ Convenience constructor to set Command on instantiation.
+ </summary>
+ <param name="command">Name of Command processing this Context.</param>
+
+ </member>
+ <member name="M:Nexus.Core.RequestContext.#ctor">
+ <summary>
+ Default, no argument constructor.
+ </summary>
+
+ </member>
+ <member name="M:Nexus.Core.RequestContext.LazyCriteria">
+ <summary>
+ Instantiate Criteria, if needed.
+ </summary>
+ </member>
+ <member name="M:Nexus.Core.RequestContext.AddStore(System.String,System.String,System.String)">
+ <summary>
+ Convenience method to lazily instantiate a message store.
+ </summary>
+ <param name="template">Message template to add to the queue.</param>
+ <param name="queue">Token for queue of messages within the
+ store.</param>
+ <param name="key">Token for message store.</param>
+
+ </member>
+ <member name="T:Nexus.Core.Tokens">
+ <summary>
+ Provide tokens representing context keys.
+ </summary>
+ <remarks><p>
+ The common convention of using CAPITALS for constants
+ is not followed for properties because using the same
+ case as the Property simplifies the use of a simple
+ template to create new members.
+ </p></remarks>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Alert">
+ <summary>
+ Token for Alert property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Alerts">
+ <summary>
+ Token for Alerts property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Command">
+ <summary>
+ Token for Command property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.CommandBin">
+ <summary>
+ Token for CommandBin property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.ControlTypeName">
+ <summary>
+ Token for ControlTypeName ControlTypeName.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Context">
+ <summary>
+ Token for Context property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Criteria">
+ <summary>
+ Token for Criteria property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Processor">
+ <summary>
+ Token for Processor property.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.DataFormat">
+ <summary>
+ Token for DataFormat DataFormat.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.DataType">
+ <summary>
+ Token for DataType DataType.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.DataTypeID">
+ <summary>
+ Token for DataTypeName DataTypeName.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Fault">
+ <summary>
+ Token for Fault property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.FieldKey">
+ <summary>
+ Token for FieldKey property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.FieldTable">
+ <summary>
+ Token for FieldTable property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Field">
+ <summary>
+ Token for Field property.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.GenericMessage">
+ <summary>
+ Token for a generic message property.
+ </summary>
+ <remarks><p>
+ A dot is used to communicate the idea
+ that the message catagory has no name
+ and to avoid using a language constant
+ in a language-neutral content.
+ </p></remarks>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Hint">
+ <summary>
+ Token for Hint property.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.Hints">
+ <summary>
+ Token for Hints property.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.Help">
+ <summary>
+ Token for Help property.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.ID">
+ <summary>
+ Token for ID ID.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Label">
+ <summary>
+ Token for Label property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Required">
+ <summary>
+ Token for Required property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Source">
+ <summary>
+ Token for Source property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.Target">
+ <summary>
+ Token for Target property.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.ID_FIELD_TABLE">
+ <summary>
+ Token for FieldTable command element.
+ </summary>
+
+ </member>
+ <member name="F:Nexus.Core.Tokens.CONTROL_INPUT">
+ <summary>
+ Token for input Control Type Name.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.HINT_EDIT">
+ <summary>
+ Token for Edit hint.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.HINT_SUCCESS_ADD">
+ <summary>
+ Token for Add Succeess hint.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.HINT_SUCCESS_EDIT">
+ <summary>
+ Token for Edit Success hint.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.HINT_SUCCESS_QUIT">
+ <summary>
+ Token for Quit Success hint.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.ENTRY_EDIT_COMMAND">
+ <summary>
+ Token for Entry Edit command.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.ENTRY_QUIT_COMMAND">
+ <summary>
+ Token for Entry Quit command.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.ENTRY_SAVE_COMMAND">
+ <summary>
+ Token for Entry Save command.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.ENTRY_ITEM_COMMAND">
+ <summary>
+ Token for Entry Item command.
+ </summary>
+ </member>
+ <member name="F:Nexus.Core.Tokens.ENTRY_ITEM_COMMAND_NAME">
+ <summary>
+ Token for Entry Item command name.
+ </summary>
+ </member>
+ <member name="T:Nexus.Core.EntryDictionary">
+ <summary>
+ Expose field attributes as public properties.
+ </summary>
+ <remarks><p>
+ The EntryDictionary is used for integration with libraries that
+ can use only public properties, such as DataGrid.
+ It is also used to pass properties as Event argument,
+ in which case it is used like a data transfer object.
+ </p><p>
+ The values are available both as an IDictionary and
+ (optionally) as Properties.
+ (The properties should use the IDictionary for storage.)
+ To define properties, extend EntryDictionary.
+ </p></remarks>
+ </member>
+ <member name="M:Nexus.Core.EntryDictionary.ToString">
+ <summary>
+ Provide a string representation of the field values
+ in the format "key=value\n".
+ </summary>
+ <returns>String representation</returns>
+ </member>
+ <member name="M:Nexus.Core.EntryDictionary.CacheText">
+ <summary>
+ Call calculated properties so that
+ they are cached as entries in the table.
+ </summary>
+ <remarks>
+ <p>Override to provide functionality</p>
+ </remarks>
+
+ </member>
+ </members>
+</doc>
diff --git a/struts-sandbox/overdrive/Nexus/Core/Profile/IProfile.cs b/struts-sandbox/overdrive/Nexus/Core/Profile/IProfile.cs
new file mode 100644
index 0000000..a912fa2
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Profile/IProfile.cs
@@ -0,0 +1,30 @@
+using System.Collections;
+using System.Globalization;
+
+namespace Nexus.Core.Profile
+{
+ /// <summary>
+ /// Record user settings.
+ /// </summary>
+ ///
+ public interface IProfile
+ {
+ /// <summary>
+ /// Record the User ID.
+ /// </summary>
+ ///
+ string UserId { get; set; }
+
+ /// <summary>
+ /// Record the User Locale.
+ /// </summary>
+ ///
+ CultureInfo UserLocale { get; set; }
+
+ /// <summary>
+ /// Record other default settings.
+ /// </summary>
+ ///
+ IDictionary Criteria { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Profile/UserIdentity.cs b/struts-sandbox/overdrive/Nexus/Core/Profile/UserIdentity.cs
new file mode 100644
index 0000000..3e6ee71
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Profile/UserIdentity.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Security.Principal;
+
+namespace Nexus.Core.Profile
+{
+ /// <summary>
+ /// Implement IIdentity to capture user's login name.
+ /// </summary>
+ /// <remarks><p>
+ /// An identity object represents the user on whose behalf the code is running).
+ /// </p><p>
+ /// For this to work, we must update the Web.config and the server settings.
+ /// </p><p>
+ /// Web.config: <authentication mode="Windows" /> <identity impersonate="true"/>
+ /// </p><p>
+ /// IIS Admin: Disable Anon Access on the Directory Security tab.
+ /// </p></remarks>
+ [Serializable]
+ public class UserIdentity : IIdentity
+ {
+ private string _Name;
+
+ public string Name
+ {
+ get { return _Name; }
+ }
+
+ private string _AuthenticationType;
+
+ public string AuthenticationType
+ {
+ get { return _AuthenticationType; }
+ set { _AuthenticationType = value; }
+ }
+
+ private bool _IsAuthenticated = false;
+
+ public bool IsAuthenticated
+ {
+ get { return _IsAuthenticated; }
+ set { _IsAuthenticated = value; }
+ }
+
+ /// <summary>
+ /// Instantiate with zero parameters.
+ /// </summary>
+ public UserIdentity()
+ {
+ }
+
+ /// <summary>
+ /// Instantiate with an IIdentity.
+ /// </summary>
+ /// <remarks>
+ /// Essentially, create a shallow copy of the given Identity.
+ /// </remarks>
+ /// <param name="id">Identity to copy</param>
+ public UserIdentity(IIdentity id)
+ {
+ if (null != id)
+ {
+ _Name = id.Name;
+ AuthenticationType = id.AuthenticationType;
+ IsAuthenticated = id.IsAuthenticated;
+ }
+ }
+
+ /// <summary>
+ /// Instantiate from passed values.
+ /// </summary>
+ /// <param name="name">Value for user's name</param>
+ /// <param name="authenticationType">Value for AuthenticationType</param>
+ /// <param name="isAuthenticated">Value for IsAuthenticated</param>
+ public UserIdentity(string name, string authenticationType, bool isAuthenticated)
+ {
+ _Name = name;
+ _AuthenticationType = authenticationType;
+ _IsAuthenticated = isAuthenticated;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Profile/UserPrincipal.cs b/struts-sandbox/overdrive/Nexus/Core/Profile/UserPrincipal.cs
new file mode 100644
index 0000000..d1f71b0
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Profile/UserPrincipal.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Security.Principal;
+
+namespace Nexus.Core.Profile
+{
+ /// <summary>
+ /// Implement IPrincipal to capture the user's login name.
+ /// </summary>
+ /// <remarks><p>
+ /// IPrincipal - A principal object represents the security context of the
+ /// user on whose behalf the code is running, including that user's identity
+ /// (IIdentity) and any roles to which they belong.
+ /// </p></remarks>
+ [Serializable]
+ public class UserPrincipal : IPrincipal
+ {
+ private IIdentity _Identity;
+
+ public IIdentity Identity
+ {
+ get { return _Identity; }
+ set { _Identity = value; }
+ }
+
+ public bool IsInRole(string role)
+ {
+ if ((null == _Roles) || (0 == _Roles.Length)) return false;
+ if ((null == role) || (0 == role.Length)) return false;
+ bool found = false;
+ for (int i = 0; i < _Roles.Length; i++)
+ found = found || role.Equals(_Roles[i]);
+ return found;
+ }
+
+ /// <summary>
+ /// Field for Roles property.
+ /// </summary>
+ private string[] _Roles;
+
+ /// <summary>
+ /// The roles for this principal representated as an array.
+ /// </summary>
+ public string[] Roles
+ {
+ get { return _Roles; }
+ set { _Roles = value; }
+ }
+
+ /// <summary>
+ /// Instantiate default NexusPrincipal with empty NexusIdentity.
+ /// </summary>
+ public UserPrincipal()
+ {
+ Identity = new UserIdentity(); // FIXME: Spring?
+ }
+
+ /// <summary>
+ /// Instantiate from an IIdentity.
+ /// </summary>
+ /// <remarks>
+ /// The Roles for this principal will follow
+ /// those set by the Roles property, regardless of the
+ /// Identity or Authentication Type.
+ /// </remarks>
+ /// <param name="id">Value for user name</param>
+ public UserPrincipal(IIdentity id)
+ {
+ Identity = new UserIdentity(id); // FIXME: Spring?
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Profile/UserProfile.cs b/struts-sandbox/overdrive/Nexus/Core/Profile/UserProfile.cs
new file mode 100644
index 0000000..f4051ac
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Profile/UserProfile.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Security.Principal;
+
+namespace Nexus.Core.Profile
+{
+ /// <summary>
+ /// Represent a user.
+ /// </summary>
+ /// <remarks><p>
+ /// The UserProfile includes a standard Principal object for
+ /// authentification and authorization.
+ /// Any user-related properties may be added here, along with
+ /// convenience methods for determining roles, such as
+ /// IsEngineer, IsManager, et al.
+ /// </p></remarks>
+ [Serializable]
+ public class UserProfile : IProfile
+ {
+ /// <summary>
+ /// Identify attribute key for storing a user profile.
+ /// </summary>
+ public const string USER_PROFILE = "USER_PROFILE";
+
+ /// <summary>
+ /// Identify attribute key for storing a user ID;.
+ /// </summary>
+ public const string USER_ID = "USER_ID";
+
+ private IPrincipal _Principal;
+
+ /// <summary>
+ /// Provide the Principal object for this user.
+ /// </summary>
+ /// <remarks><p>
+ /// Usually, this is a UserPrincipal,
+ /// but any IPrincipal instance could be used.
+ /// </p></remarks>
+ public IPrincipal Principal
+ {
+ get { return _Principal; }
+ set { _Principal = value; }
+ }
+
+ #region UserId
+
+ /// <summary>
+ /// Identify the character separating a "machine name" from a "user id".
+ /// </summary>
+ public static char[] USER_ID_SEPARATOR = {'\\'}; // Backslash is the quote character, so you need to escape it.
+
+ /// <summary>
+ /// Trim any machine name reference from Principal Name.
+ /// </summary>
+ /// <param name="name">A Identity Name that may contain a machine name reference</param>
+ /// <returns>Identity name with machine name removed</returns>
+ protected string TrimMachineName(string name)
+ {
+ if (null == name) return String.Empty;
+ string[] logon = name.Split(USER_ID_SEPARATOR);
+ if (logon.Length > 1) return logon[1];
+ return logon[0];
+ }
+
+ private string _UserId;
+
+ /// <summary>
+ /// Record the user id portion of the Identity Name.
+ /// </summary>
+ /// <remarks><p>
+ /// The UserId can be used to relate staff records to user logins.
+ /// </p></remarks>
+ public string UserId
+ {
+ get
+ {
+ if (null == _UserId)
+ _UserId = TrimMachineName(Principal.Identity.Name);
+ return (null == _UserId) ? String.Empty : _UserId;
+ }
+ set { _UserId = value; }
+ }
+
+ #endregion
+
+ #region UserLocale
+
+ /// <summary>
+ /// Provide a field for UserLocale property.
+ /// </summary>
+ private CultureInfo _UserLocale;
+
+ public CultureInfo UserLocale
+ {
+ get { return _UserLocale; }
+ set { _UserLocale = value; }
+ }
+
+ #endregion
+
+ #region Criteria
+
+ /// <summary>
+ /// Provide a field for Criteria property.
+ /// </summary>
+ ///
+ private IDictionary _Criteria;
+
+ public IDictionary Criteria
+ {
+ get
+ {
+ if (_Criteria == null)
+ _Criteria = new Hashtable();
+ return _Criteria;
+ }
+ set { _Criteria = value; }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Instantiate a default profile.
+ /// </summary>
+ public UserProfile()
+ {
+ Principal = new UserPrincipal(); // FIXME: Spring?
+ }
+
+ /// <summary>
+ /// Instantiate from an IPrincipal.
+ /// </summary>
+ /// <param name="principal">Principal for this profile.</param>
+ public UserProfile(IPrincipal principal)
+ {
+ Principal = principal;
+ }
+
+ /// <summary>
+ /// Instantiate from an IIdentity.
+ /// </summary>
+ /// <param name="id">Identity to copy for this profile.</param>
+ public UserProfile(IIdentity id)
+ {
+ Principal = new UserPrincipal(id);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/RequestChain.cs b/struts-sandbox/overdrive/Nexus/Core/RequestChain.cs
new file mode 100644
index 0000000..ac5c3da
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/RequestChain.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections;
+using Agility.Core;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Implement IRequestChain.
+ /// </summary>
+ public class RequestChain : RequestCommand, IRequestChain
+ {
+ private Chain chain = new Chain();
+
+ public void AddCommand(ICommand _command)
+ {
+ IRequestCommand command = _command as IRequestCommand;
+ if (null == command)
+ throw new ArgumentNullException("RequestChain.AddCommand", "_command");
+
+ chain.AddCommand(command);
+
+ // Composite Required and Related
+ IList _RequiredIDs = command.RequiredIDs;
+ if (null != _RequiredIDs) AddRequiredIDs = _RequiredIDs;
+
+ IList _RelatedIDs = command.RelatedIDs;
+ if (null != _RelatedIDs) AddRelatedIDs = _RelatedIDs;
+ }
+
+ public IList AddCommands
+ {
+ set
+ {
+ foreach (ICommand command in value)
+ {
+ AddCommand(command);
+ }
+ }
+ }
+
+ public override bool Execute(IContext context)
+ {
+ return chain.Execute(context);
+ }
+
+ public ICommand[] GetCommands()
+ {
+ return (chain.GetCommands());
+
+ }
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ return Execute(context);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/RequestCommand.cs b/struts-sandbox/overdrive/Nexus/Core/RequestCommand.cs
new file mode 100644
index 0000000..f13cadb
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/RequestCommand.cs
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Agility.Core;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Implement IRequestCommand, leaving RequestExecute abstract.
+ /// </summary>
+ ///
+ public abstract class RequestCommand : IRequestCommand
+ {
+ /// <summary>
+ /// Execute should return STOP if problem occurs,
+ /// so that a Chain can exit processing on error.
+ /// </summary>
+ ///
+ public const bool STOP = true;
+
+ /// <summary>
+ /// Return CONTINUE if another Command could run.
+ /// </summary>
+ ///
+ public const bool CONTINUE = false;
+
+ private string _ID = null;
+
+ public virtual string ID
+ {
+ get { return _ID; }
+ set { _ID = value; }
+ }
+
+ private string _QueryID = null;
+
+ public virtual string QueryID
+ {
+ get
+ {
+ if (null == _QueryID) return ID;
+ else return _QueryID;
+ }
+ set { _QueryID = value; }
+ }
+
+ public virtual IRequestContext NewContext()
+ {
+ // Return a new instance on each call.
+ // ISSUE: Spring?
+ return new RequestContext(ID);
+ }
+
+ private IList _RequiredIDs = null;
+
+ public virtual IList RequiredIDs
+ {
+ get
+ {
+ return _RequiredIDs;
+ }
+ set { _RequiredIDs = value; }
+ }
+
+ public IList AddRequiredIDs
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("BaseNexusCommand.AddRequiredIDs", "value");
+ IList list = RequiredIDs;
+ if (null == list)
+ RequiredIDs = value;
+ else
+ {
+ IEnumerator elements = value.GetEnumerator();
+ while (elements.MoveNext())
+ {
+ string i = elements.Current as string;
+ bool need = (list.IndexOf(i) < 0);
+ if (need) list.Add(i);
+ }
+ }
+ }
+ }
+
+ private IList _RelatedIDs = null;
+
+ public virtual IList RelatedIDs
+ {
+ get
+ {
+ if (_RelatedIDs==null)
+ _RelatedIDs = new ArrayList();
+ return _RelatedIDs;
+ }
+ set { _RelatedIDs = value; }
+ }
+
+ public IList AddRelatedIDs
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("BaseNexusCommand.AddRelatedIDs", "value");
+ IList list = RelatedIDs;
+ if (null == list)
+ RelatedIDs = value;
+ else
+ {
+ IEnumerator elements = value.GetEnumerator();
+ while (elements.MoveNext())
+ {
+ string i = elements.Current as string;
+ bool need = (list.IndexOf(i) < 0);
+ if (need) list.Add(i);
+ }
+ }
+ }
+ }
+
+ private IList _RuntimeIDs = null;
+
+ public virtual IList RuntimeIDs
+ {
+ get { return _RuntimeIDs; }
+ set { _RuntimeIDs = value; }
+ }
+
+ public IList AddRuntimeIDs
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("BaseNexusCommand.AddRuntimeIDs", "value");
+ IList list = RuntimeIDs;
+ if (null == list)
+ RuntimeIDs = value;
+ else
+ {
+ IEnumerator elements = value.GetEnumerator();
+ while (elements.MoveNext())
+ {
+ string i = elements.Current as string;
+ bool need = (list.IndexOf(i) < 0);
+ if (need) list.Add(i);
+ }
+ }
+ }
+ }
+
+ public abstract bool RequestExecute(IRequestContext context);
+
+ public virtual bool Execute(IContext _context)
+ {
+ IRequestContext context = _context as IRequestContext;
+ return RequestExecute(context);
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/RequestContext.cs b/struts-sandbox/overdrive/Nexus/Core/RequestContext.cs
new file mode 100644
index 0000000..82cc161
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/RequestContext.cs
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using System.Text;
+using Agility.Core;
+using Nexus.Core.Profile;
+using Nexus.Core.Tables;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Implement IRequestContext.
+ /// </summary>
+ ///
+ public class RequestContext : Context, IRequestContext
+ {
+ /// <summary>
+ /// Express state as a key=value list.
+ /// </summary>
+ /// <returns>Formatted string representing state.</returns>
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (DictionaryEntry e in this)
+ {
+ sb.Append("[");
+ sb.Append(e.Key);
+ sb.Append("=");
+ sb.Append(e.Value.ToString());
+ sb.Append("], ");
+ }
+ return sb.ToString();
+ }
+
+ /// <summary>
+ /// Convenience constructor to set Command on instantiation.
+ /// </summary>
+ /// <param name="command">Name of Command processing this Context.</param>
+ ///
+ public RequestContext(string command)
+ {
+ Command = command;
+ }
+
+ public RequestContext(IDictionary entries)
+ {
+ foreach (DictionaryEntry entry in entries)
+ {
+ base.Add(entry.Key, entry.Value);
+ }
+ }
+
+ /// <summary>
+ /// Default, no argument constructor.
+ /// </summary>
+ ///
+ public RequestContext()
+ {
+ }
+
+ public string Command
+ {
+ get { return this[Tokens.Command] as string; }
+ set { this[Tokens.Command] = value; }
+ }
+
+ public IRequestCommand CommandBin
+ {
+ get { return this[Tokens.CommandBin] as IRequestCommand; }
+ set { this[Tokens.CommandBin] = value; }
+ }
+
+ public IFieldTable FieldTable
+ {
+ get { return this[Tokens.FieldTable] as IFieldTable; }
+ set { this[Tokens.FieldTable] = value; }
+ }
+
+ public IProfile Profile
+ {
+ get { return this[UserProfile.USER_PROFILE] as IProfile; }
+ set
+ {
+ this[UserProfile.USER_PROFILE] = value;
+ IProfile profile = value;
+ if (null != profile)
+ this[UserProfile.USER_ID] = profile.UserId;
+ }
+ }
+
+ public bool HasOutcome
+ {
+ get { return Contains(Command); }
+ }
+
+ public object Outcome
+ {
+ get { return this[Command]; }
+ set { this[Command] = value; }
+ }
+
+ /// <summary>
+ /// Instantiate Criteria, if needed.
+ /// </summary>
+ private void LazyCriteria()
+ {
+ // Naive, but we expect a Context instance to be single-threaded.
+ if (this[Tokens.Criteria] == null)
+ this[Tokens.Criteria] = new Hashtable(); // TODO: Spring?
+ }
+
+ public IDictionary Criteria
+ {
+ get
+ {
+ LazyCriteria();
+ return this[Tokens.Criteria] as IDictionary;
+ }
+ set { this[Tokens.Criteria] = value; }
+ }
+
+ public bool HasCriteria()
+ {
+ return ContainsKey(Tokens.Criteria);
+ }
+
+
+ /// <summary>
+ /// Convenience method to lazily instantiate a message store.
+ /// </summary>
+ /// <param name="template">Message template to add to the queue.</param>
+ /// <param name="queue">Token for queue of messages within the
+ /// store.</param>
+ /// <param name="key">Token for message store.</param>
+ ///
+ private void AddStore(string template, string queue, string key)
+ {
+ IDictionary store = this[key] as IDictionary;
+ if (null == store)
+ {
+ store = new Hashtable(); // ISSUE: Spring?
+ this[key] = store;
+ }
+ IList list;
+ if (store.Contains(queue))
+ list = store[queue] as IList;
+ else
+ {
+ list = new ArrayList(); // ISSUE: Spring?
+ store[queue] = list;
+ }
+ list.Add(template);
+ }
+
+ public string FormatTemplate(string template, string value)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat(template, value);
+ return sb.ToString();
+ }
+
+ public IDictionary Alerts
+ {
+ get { return this[Tokens.Alerts] as IDictionary; }
+ set { this[Tokens.Alerts] = value; }
+ }
+
+ public void AddAlert(string template)
+ {
+ AddStore(template, Tokens.GenericMessage, Tokens.Alerts);
+ }
+
+ public void AddAlert(string template, string queue)
+ {
+ AddStore(template, queue, Tokens.Alerts);
+ }
+
+ public void AddAlertForField(string key)
+ {
+ string message = FormatTemplate(FieldTable.Alert(key), FieldTable.Label(key));
+ AddAlert(message, key);
+ }
+
+ public void AddAlertRequired(string key)
+ {
+ string message = FormatTemplate(FieldTable.Required(key), FieldTable.Label(key));
+ AddAlert(message, key);
+ }
+
+ public bool HasAlerts
+ {
+ get { return ContainsKey(Tokens.Alerts); }
+ }
+
+ public Exception Fault
+ {
+ get { return this[Tokens.Fault] as Exception; }
+ set
+ {
+ Exception e = value;
+ this[Tokens.Fault] = e;
+ AddAlert(e.Message);
+ }
+ }
+
+ public bool HasFault
+ {
+ get { return ContainsKey(Tokens.Fault); }
+ }
+
+ public bool IsNominal
+ {
+ get { return (!HasAlerts && !HasFault); }
+ }
+
+ public IDictionary Hints
+ {
+ get { return this[Tokens.Hints] as IDictionary; }
+ set { this[Tokens.Hints] = value; }
+ }
+
+ public void AddHint(string template)
+ {
+ AddStore(template, Tokens.GenericMessage, Tokens.Hints);
+ }
+
+ public void AddHint(string template, string queue)
+ {
+ AddStore(template, queue, Tokens.Hints);
+ }
+
+ public bool HasHints
+ {
+ get { return ContainsKey(Tokens.Hints); }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Tables/FieldContext.cs b/struts-sandbox/overdrive/Nexus/Core/Tables/FieldContext.cs
new file mode 100644
index 0000000..04e33ac
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Tables/FieldContext.cs
@@ -0,0 +1,80 @@
+using System;
+using Agility.Core;
+using Nexus.Core.Validators;
+
+namespace Nexus.Core.Tables
+{
+ /// <summary>
+ /// Concrete IFieldContext implementation.
+ /// </summary>
+ [Serializable]
+ public class FieldContext : Context, IFieldContext
+ {
+ public FieldContext() : base()
+ {
+ ControlTypeName = Tokens.CONTROL_INPUT; // Default
+ }
+
+ public string Alert
+ {
+ get
+ {
+ string alert = null;
+ IProcessor processor = Processor;
+ if (processor != null) alert = processor.Alert;
+ if (alert == null) alert = this[Tokens.Alert] as string;
+ if (alert == null) alert = this[Tokens.Alert] as string;
+ return alert;
+ }
+ set { this[Tokens.Alert] = value; }
+ }
+
+ public string ControlTypeName
+ {
+ get { return this[Tokens.ControlTypeName] as string; }
+ set { this[Tokens.ControlTypeName] = value; }
+ }
+
+ public string Hint
+ {
+ get { return this[Tokens.Hint] as string; }
+ set { this[Tokens.Hint] = value; }
+ }
+
+ public string Help
+ {
+ get { return this[Tokens.Help] as string; }
+ set { this[Tokens.Help] = value; }
+ }
+
+ public string ID
+ {
+ get { return this[Tokens.ID] as string; }
+ set { this[Tokens.ID] = value; }
+ }
+
+ public string Label
+ {
+ get
+ {
+ string label = this[Tokens.Label] as string;
+ if (label == null) label = ID;
+ return label;
+ }
+ set { this[Tokens.Label] = value; }
+ }
+
+ public IProcessor Processor
+ {
+ get { return this[Tokens.Processor] as IProcessor; }
+ set { this[Tokens.Processor] = value; }
+ }
+
+ public string Required
+ {
+ get { return this[Tokens.Required] as string; }
+ set { this[Tokens.Required] = value; }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Tables/FieldTable.cs b/struts-sandbox/overdrive/Nexus/Core/Tables/FieldTable.cs
new file mode 100644
index 0000000..897d34a
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Tables/FieldTable.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections;
+using Agility.Core;
+using Nexus.Core.Validators;
+
+namespace Nexus.Core.Tables
+{
+ /// <summary>
+ /// Implement IFieldTable.
+ /// </summary>
+ /// <remarks><p>
+ /// Validator
+ /// * Needs configurable nullvalue support
+ /// ** String, nullValue=""
+ /// ** Double, nullValue=0.0"
+ /// ** DataType, allowNull
+ /// * If they give us something, and it fails conversion, then validation fails.
+ /// * If they give us null or an empty string, and the property has a nullValue, then the nullValue is used.
+ /// * If they give us null or an empty string, or the nullValue, and the property is required, then validation fails.
+ /// </p></remarks>
+ [Serializable]
+ public class FieldTable : Context, IFieldTable
+ {
+ #region IFieldTable
+
+ #region Field
+
+ private bool _Strict = false;
+
+ public virtual bool Strict
+ {
+ get { return _Strict; }
+ set { _Strict = value; }
+ }
+
+ public virtual IFieldContext NewFieldContext(string id)
+ {
+ IFieldContext field = new FieldContext();
+ field.ID = id;
+ return field;
+ }
+
+ public virtual IFieldContext AddFieldContext
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("(value==null) || (Type!=IFieldContext)", "Nexus.Core.Tables.FieldTable.AddFieldContext");
+ Field[value.ID] = value;
+ }
+ }
+
+ public virtual IList AddFieldContexts
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("(value==null) || (Type!=IFieldContext)", "Nexus.Core.Tables.FieldTable.AddFieldContexts");
+ IEnumerator elements = value.GetEnumerator();
+ while (elements.MoveNext()) AddFieldContext = elements.Current as IFieldContext;
+ }
+ }
+
+ public virtual IFieldContext GetFieldContext(string id)
+ {
+ if (id == null) throw new ArgumentNullException("id==null", "Nexus.Core.Tables.FieldTable.GetFieldContext");
+ IFieldContext fieldContext = Field[id] as IFieldContext;
+ bool missing = (fieldContext == null);
+ if (missing)
+ if (Strict)
+ throw new ArgumentNullException(id, "Nexus.Core.Tables.FieldTable.GetFieldContext");
+ else
+ {
+ Object lockThis = new Object();
+ lock (lockThis)
+ {
+ fieldContext = NewFieldContext(id);
+ AddFieldContext = fieldContext;
+ }
+ }
+ return fieldContext;
+ }
+
+ #endregion
+
+ #region Processor
+
+ public virtual IProcessor AddProcessor
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value==null", "Nexus.Core.Tables.FieldTable.AddProcessor");
+ Processor[value.ID] = value;
+ }
+ }
+
+ public virtual IList AddProcessors
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value==null", "Nexus.Core.Tables.FieldTable.AddProcessors");
+ IEnumerator elements = value.GetEnumerator();
+ while (elements.MoveNext()) AddProcessor = elements.Current as IProcessor;
+ }
+ }
+
+ #endregion
+
+ #region Text
+
+ public virtual string Alert(string id)
+ {
+ return GetFieldContext(id).Alert;
+ }
+
+ public virtual string Label(string id)
+ {
+ return GetFieldContext(id).Label;
+ }
+
+ public virtual string Required(string id)
+ {
+ return GetFieldContext(id).Required;
+ }
+
+ #endregion
+
+ #endregion
+
+ /// <summary>
+ /// Create instance with zero paramters.
+ /// </summary>
+ public FieldTable()
+ {
+ this[Tokens.Field] = new Hashtable();
+ this[Tokens.Processor] = new Hashtable();
+ }
+
+ /// <summary>
+ /// Internal storage for the FieldContexts.
+ /// </summary>
+ private IDictionary Field
+ {
+ get { return this[Tokens.Field] as IDictionary; }
+ }
+
+ /// <summary>
+ /// Internal storage for the Processors.
+ /// </summary>
+ private IDictionary Processor
+ {
+ get { return this[Tokens.Processor] as IDictionary; }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Tables/IFieldContext.cs b/struts-sandbox/overdrive/Nexus/Core/Tables/IFieldContext.cs
new file mode 100644
index 0000000..99de231
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Tables/IFieldContext.cs
@@ -0,0 +1,92 @@
+using System.Runtime.Serialization;
+using Nexus.Core.Validators;
+
+namespace Nexus.Core.Tables
+{
+ /// <summary>
+ /// Provide properties common to controls,
+ /// including Alert, ControlType, and Processor.
+ /// </summary>
+ /// <remark><p>
+ /// The FieldContext entries are made available through a FieldTable.
+ /// The FieldContext members follow XForms terminology.
+ /// </p><p>
+ /// XForms [http://www.w3.org/MarkUp/Forms/].
+ /// XForms Controls [http://www.orbeon.com/ops/doc/processors-xforms].
+ /// XPath 2.0 for .NET [http://sourceforge.net/projects/saxondotnet/].
+ /// </p><p>
+ /// To globalize an application,
+ /// utilize a IFieldContext implementation that supports localization.
+ /// A localized implementation can access a message resource to obtain text and messages,
+ /// rather than a simple property.
+ /// Localized implementations should also dissallow setting the text properties,
+ /// since those values would be provided through a message resource.
+ /// </p><p>
+ /// For a localized implementation, see Nexus.Core.Extras.Spring.FieldContext.
+ /// </p></remark>
+ ///
+ public interface IFieldContext : ISerializable
+ {
+ /// <summary>
+ /// Provide a message to display when input validation fails.
+ /// </summary>
+ /// <remarks>
+ /// If the Processor also provides an Alert,
+ /// the Processor's Alert should be returned instead.
+ /// </remarks>
+ ///
+ string Alert { get; set; }
+
+ /// <summary>
+ /// Identify name of the default Control Type.
+ /// </summary>
+ /// <remarks><p>
+ /// Standard control types are: input, secret, textarea, select1, select, submit, upload.
+ /// </p><p>
+ /// XForms distinguishes between Lists, Radio Buttons, and CheckBoxes through additional
+ /// parameters. For now, all three can be identified as select1 or select.
+ /// </p></remarks>
+ ///
+ string ControlTypeName { get; set; }
+
+ /// <summary>
+ /// Provide text to display for a context-sensitive help screen.
+ /// </summary>
+ ///
+ string Help { get; set; }
+
+ /// <summary>
+ /// Record an onscreen or hover hint.
+ /// </summary>
+ ///
+ string Hint { get; set; }
+
+ /// <summary>
+ /// Identify this field with a unique name.
+ /// </summary>
+ ///
+ string ID { get; set; }
+
+ /// <summary>
+ /// Provide a label for the control.
+ /// </summary>
+ /// <remarks><p>
+ /// If the Label is null, the ID should be returned instead.
+ /// </p></remarks>
+ ///
+ string Label { get; set; }
+
+ /// <summary>
+ /// Provide the processor for this field context.
+ /// </summary>
+ ///
+ IProcessor Processor { get; set; }
+
+ /// <summary>
+ /// Provide a message to display when required input is missing.
+ /// </summary>
+ ///
+ string Required { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Tables/IFieldTable.cs b/struts-sandbox/overdrive/Nexus/Core/Tables/IFieldTable.cs
new file mode 100644
index 0000000..f0792a1
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Tables/IFieldTable.cs
@@ -0,0 +1,87 @@
+using System.Collections;
+using System.Runtime.Serialization;
+using Agility.Core;
+using Nexus.Core.Validators;
+
+namespace Nexus.Core.Tables
+{
+ /// <summary>
+ /// Inventory of fields and processors used by the application.
+ /// </summary>
+ ///
+ public interface IFieldTable : IContext, ISerializable
+ {
+ /// <summary>
+ /// Indicate whether this FieldTable must include all fields,
+ /// including strings fields [FALSE].
+ /// </summary>
+ ///
+ bool Strict { set; get; }
+
+ /// <summary>
+ /// Factory method to create a stub context
+ /// when field is required and Strict is false.
+ /// </summary>
+ /// <remarks><p>
+ /// The IFieldContext instance should provide a default for Required.
+ /// </p></remarks>
+ /// <param name="id">The fieldname</param>
+ /// <returns>New default context for ID</returns>
+ IFieldContext NewFieldContext(string id);
+
+ /// <summary>
+ /// Add a field to the set.
+ /// </summary>
+ ///
+ IFieldContext AddFieldContext { set; }
+
+ /// <summary>
+ /// Add a list of fields to the set.
+ /// </summary>
+ ///
+ IList AddFieldContexts { set; }
+
+ /// <summary>
+ /// Obtain the FieldContext for the given ID, observing Strict setting.
+ /// </summary>
+ /// <param name="id">FieldContext ID</param>
+ /// <returns>FieldContext for ID</returns>
+ ///
+ IFieldContext GetFieldContext(string id);
+
+ /// <summary>
+ /// Add a Processor to the set.
+ /// </summary>
+ IProcessor AddProcessor { set; }
+
+ /// <summary>
+ /// Add a list of Processors to the set.
+ /// </summary>
+ IList AddProcessors { set; }
+
+ /// <summary>
+ /// Provide the Alert message for a given field id.
+ /// </summary>
+ /// <param name="id">FieldContext ID</param>
+ /// <returns>Alert message for FieldContext ID</returns>
+ ///
+ string Alert(string id);
+
+ /// <summary>
+ /// Provide the Label message for a given field id.
+ /// </summary>
+ /// <param name="id">FieldContext ID</param>
+ /// <returns>Alert message for FieldContext ID</returns>
+ ///
+ string Label(string id);
+
+ /// <summary>
+ /// Provide the Required message for a given field id.
+ /// </summary>
+ /// <param name="id">FieldContext ID</param>
+ /// <returns>Required message for FieldContext ID</returns>
+ ///
+ string Required(string id);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Tokens.cs b/struts-sandbox/overdrive/Nexus/Core/Tokens.cs
new file mode 100644
index 0000000..19b0bd3
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Tokens.cs
@@ -0,0 +1,264 @@
+ /*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Provide tokens representing context keys.
+ /// </summary>
+ /// <remarks><p>
+ /// The common convention of using CAPITALS for constants
+ /// is not followed for properties because using the same
+ /// case as the Property simplifies the use of a simple
+ /// template to create new members.
+ /// </p></remarks>
+ ///
+ public class Tokens
+ {
+ private Tokens()
+ {
+ // No need to construct static helper class
+ }
+
+ #region Properties
+
+ /*
+ get { return Context[Tokens.Property] as string; }
+ set { Context[Tokens.Property] = value; }
+
+ /// <summary>
+ /// Token for Property property.
+ /// </summary>
+ ///
+ public const string Property = "_Property";
+ */
+
+ /// <summary>
+ /// Token for Alert property.
+ /// </summary>
+ ///
+ public const string Alert = "_Alert";
+
+ /// <summary>
+ /// Token for Alerts property.
+ /// </summary>
+ ///
+ public const string Alerts = "_Alerts";
+
+ /// <summary>
+ /// Token for Command property.
+ /// </summary>
+ ///
+ public const string Command = "_Command";
+
+ /// <summary>
+ /// Token for CommandBin property.
+ /// </summary>
+ ///
+ public const string CommandBin = "_CommandBin";
+
+ /// <summary>
+ /// Token for ControlTypeName ControlTypeName.
+ /// </summary>
+ ///
+ public const string ControlTypeName = "_ControlTypeName";
+
+ /// <summary>
+ /// Token for Context property.
+ /// </summary>
+ ///
+ public const string Context = "_Context";
+
+ /// <summary>
+ /// Token for Criteria property.
+ /// </summary>
+ ///
+ public const string Criteria = "_Criteria";
+
+ /// <summary>
+ /// Token for Processor property.
+ /// </summary>
+ public const string Processor = "_Processor";
+
+ /// <summary>
+ /// Token for DataFormat DataFormat.
+ /// </summary>
+ ///
+ public const string DataFormat = "_DataFormat";
+
+ /// <summary>
+ /// Token for DataType DataType.
+ /// </summary>
+ ///
+ public const string DataType = "_DataType";
+
+ /// <summary>
+ /// Token for DataTypeName DataTypeName.
+ /// </summary>
+ ///
+ public const string DataTypeID = "_DataTypeID";
+
+ /// <summary>
+ /// Token for Fault property.
+ /// </summary>
+ ///
+ public const string Fault = "_Fault";
+
+ /// <summary>
+ /// Token for FieldKey property.
+ /// </summary>
+ ///
+ public const string FieldKey = "_FieldKey";
+
+ /// <summary>
+ /// Token for FieldTable property.
+ /// </summary>
+ ///
+ public const string FieldTable = "_FieldTable";
+
+ /// <summary>
+ /// Token for Field property.
+ /// </summary>
+ public const string Field = "_Field";
+
+ /// <summary>
+ /// Token for a generic message property.
+ /// </summary>
+ /// <remarks><p>
+ /// A dot is used to communicate the idea
+ /// that the message catagory has no name
+ /// and to avoid using a language constant
+ /// in a language-neutral content.
+ /// </p></remarks>
+ ///
+ public const string GenericMessage = ".";
+
+ /// <summary>
+ /// Token for Hint property.
+ /// </summary>
+ public const string Hint = "_Hint";
+
+ /// <summary>
+ /// Token for Hints property.
+ /// </summary>
+ public const string Hints = "_Hints";
+
+ /// <summary>
+ /// Token for Help property.
+ /// </summary>
+ public const string Help = "_Help";
+
+ /// <summary>
+ /// Token for ID ID.
+ /// </summary>
+ ///
+ public const string ID = "_ID";
+
+ /// <summary>
+ /// Token for Label property.
+ /// </summary>
+ ///
+ public const string Label = "_Label";
+
+ /// <summary>
+ /// Token for Required property.
+ /// </summary>
+ ///
+ public const string Required = "_Required";
+
+ /// <summary>
+ /// Token for Source property.
+ /// </summary>
+ ///
+ public const string Source = "_Source";
+
+ /// <summary>
+ /// Token for Target property.
+ /// </summary>
+ ///
+ public const string Target = "_Target";
+
+ #endregion
+
+ #region Command elements
+
+ /// <summary>
+ /// Token for FieldTable command element.
+ /// </summary>
+ ///
+ public const string ID_FIELD_TABLE = "FieldTable";
+
+ #endregion
+
+ #region Control Type Names
+
+ /// <summary>
+ /// Token for input Control Type Name.
+ /// </summary>
+ public const string CONTROL_INPUT = "input";
+
+ #endregion
+
+ #region Message keys (GridViewHelper)
+
+ /// <summary>
+ /// Token for Edit hint.
+ /// </summary>
+ public const string HINT_EDIT = "hint_edit";
+
+ /// <summary>
+ /// Token for Add Succeess hint.
+ /// </summary>
+ public const string HINT_SUCCESS_ADD = "hint_success_add";
+
+ /// <summary>
+ /// Token for Edit Success hint.
+ /// </summary>
+ public const string HINT_SUCCESS_EDIT = "hint_success_edit";
+
+ /// <summary>
+ /// Token for Quit Success hint.
+ /// </summary>
+ public const string HINT_SUCCESS_QUIT = "hint_success_quit";
+
+ /// <summary>
+ /// Token for Entry Edit command.
+ /// </summary>
+ public const string ENTRY_EDIT_COMMAND = "entry_edit_command";
+
+ /// <summary>
+ /// Token for Entry Quit command.
+ /// </summary>
+ public const string ENTRY_QUIT_COMMAND = "entry_quit_command";
+
+ /// <summary>
+ /// Token for Entry Save command.
+ /// </summary>
+ public const string ENTRY_SAVE_COMMAND = "entry_save_command";
+
+ /// <summary>
+ /// Token for Entry Item command.
+ /// </summary>
+ public const string ENTRY_ITEM_COMMAND = "entry_item_command";
+
+ /// <summary>
+ /// Token for Entry Item command name.
+ /// </summary>
+ public const string ENTRY_ITEM_COMMAND_NAME = "entry_item_command_name";
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/ClearContext.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/ClearContext.cs
new file mode 100644
index 0000000..b2fc96d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/ClearContext.cs
@@ -0,0 +1,34 @@
+using System.Collections;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Clear from the Context any keys present in the Criteria,
+ /// so that, if the context is re-used, values from a prior request do not linger.
+ /// </summary>
+ /// <remarks><p>
+ /// Once the values are output from the Context to the Criteria,
+ /// they can be safely removed from the Context.
+ /// </p><p>This command can be used as part of a post-opt chain to ensure that
+ /// Context values are not retained if a Context object is used for multiple
+ /// business requests.
+ /// </p></remarks>
+ public class ClearContext : RequestCommand
+ {
+ /// <summary>
+ /// Clear from the Context any keys present in the Criteria.
+ /// </summary>
+ /// <param name="context">Context after attributes have been output to Criteria</param>
+ /// <returns>CONTINUE</returns>
+ public override bool RequestExecute(IRequestContext context)
+ {
+ ICollection keys = context.Criteria.Keys;
+ foreach (string key in keys)
+ {
+ context.Remove(key);
+ }
+
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/CollectionProcessor.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/CollectionProcessor.cs
new file mode 100644
index 0000000..d73fd30
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/CollectionProcessor.cs
@@ -0,0 +1,66 @@
+namespace Nexus.Core.Validators
+{
+ public class CollectionProcessor : Processor
+ {
+ public override bool ConvertInput(IProcessorContext incoming)
+ {
+ incoming.Target = incoming.Source;
+ return true;
+ }
+
+ public override bool FormatOutput(IProcessorContext outgoing)
+ {
+ outgoing.Target = outgoing.Source;
+ return true;
+ }
+
+ }
+
+ #region Notes
+
+ /*
+ /// <summary>
+ /// Instantiate from an IDictionary,
+ /// formatting each entry using the FieldTable from a INexusContext,
+ /// and reporting any conversion or formatting errors in the INexusContext.
+ /// </summary>
+ /// <remarks><p>
+ /// The result of a query will come back as a list of IDictionaries,
+ /// using native, unformatted data types.
+ /// This constructor can be used to loop through a list of IDictionaires,
+ /// create a AppContext for each entry, and formatting any values
+ /// along the way. (Dates being the best example.)
+ /// The result is a AppContextList that can be used as a DataGrid
+ /// DataSource (or whatever).
+ /// </p></remarks>
+ /// <param name="dictionary">Values for new object</param>
+ /// <param name="context">Context with FieldTable and error handler</param>
+ public AppContext (IDictionary dictionary, IRequestContext context)
+ {
+ #region Assert parameters
+
+ if (null == dictionary) throw new ArgumentNullException ("dictionary", "AppContext(IDictionary,INexusContext");
+ if (null == context) throw new ArgumentNullException ("context", "AppContext(IDictionary,INexusContext");
+ IFieldTable table = context.FieldTable;
+ if (null == table) throw new ArgumentNullException ("FieldTable", "AppContext(IDictionary,INexusContext");
+
+ #endregion
+
+ IEnumerator keys = dictionary.Keys.GetEnumerator ();
+ while (keys.MoveNext ())
+ {
+ string key = keys.Current as string;
+ IValidatorContext input = new ValidatorContext (); // ISSUE: Spring? [WNE-63]
+ input.FieldKey = key;
+ input.Source = dictionary [key];
+ bool okay = table.Format (input);
+ if (!okay)
+ // OR, do we just want to push convert/format(id) up?
+ context.AddAlertForField (key);
+ this.Add (key, input.Target);
+ }
+ }
+ */
+
+ #endregion
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/ConvertInput.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/ConvertInput.cs
new file mode 100644
index 0000000..cb2eea9
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/ConvertInput.cs
@@ -0,0 +1,32 @@
+using System.Collections;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Convert related fields from Criteria to the main context,
+ /// adding an Alert message to Errors if a conversion fails.
+ /// </summary>
+ public class ConvertInput : ProcessorCommand
+ {
+ public override bool ExecuteProcess(IProcessorContext incoming)
+ {
+ string key = incoming.FieldKey;
+ IRequestContext context = incoming.Context;
+ IDictionary criteria = incoming.Criteria;
+
+ bool have = (criteria.Contains(key));
+ if (have)
+ {
+ incoming.Source = criteria[key];
+ bool okay = ExecuteConvert(incoming);
+ if (okay)
+ // set to main context
+ context[key] = incoming.Target;
+ else context.AddAlertForField(key);
+ return STOP;
+ }
+
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/DateTimeProcessor.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/DateTimeProcessor.cs
new file mode 100644
index 0000000..95919a3
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/DateTimeProcessor.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Convert and format DateTime fields.
+ /// </summary>
+ public class DateTimeProcessor : Processor
+ {
+ #region IProcessor
+
+ public override bool ConvertInput(IProcessorContext incoming)
+ {
+ bool okay = false;
+ string source = incoming.Source as string;
+
+ if (IsInput(source))
+ {
+ DateTime t = DateTime_Convert(source);
+ bool isDateTimeEmpty = DateTime_Empty.Equals(t);
+ okay = !isDateTimeEmpty;
+ incoming.Target = t;
+ }
+ else
+ {
+ incoming.Target = null; // FIXME: We could use DateTime_Empty here,
+ okay = true; // but there was an issue with iBATIS (is there still?)
+ }
+
+ return okay;
+ }
+
+ public override bool FormatOutput(IProcessorContext outgoing)
+ {
+ bool okay = false;
+ object source = outgoing.Source;
+
+ if (IsEmpty(source))
+ {
+ outgoing.Target = String.Empty;
+ okay = true;
+ }
+ else
+ {
+ string target = DateTime_Format(source);
+ outgoing.Target = target;
+ okay = IsInput(target);
+ }
+ return okay;
+ }
+
+ #endregion
+
+ private bool IsInput(string v)
+ {
+ return ((v != null) && (!String.Empty.Equals(v)));
+ }
+
+ private DateTime DateTime_Empty = DateTime.MinValue;
+
+ private bool IsEmpty(object source)
+ {
+ SByte dbNull = 0;
+ return ((null == source) || (DBNull.Value.Equals(source)) || (dbNull.Equals(source) || String.Empty.Equals(source)));
+ }
+
+ private DateTime DateTime_Convert(string source)
+ {
+ DateTime t = DateTime_Empty;
+ try
+ {
+ t = Convert.ToDateTime(source);
+ }
+ catch (InvalidCastException e)
+ {
+ e = e; // silly assignment
+ }
+ catch (FormatException e)
+ {
+ e = e; // silly assignment
+ }
+ return t;
+
+ }
+
+ private string DateTime_Format(object source)
+ {
+ DateTime t = DateTime_Empty;
+ try
+ {
+ t = (DateTime) source;
+ }
+ catch (InvalidCastException e)
+ {
+ e = e;
+ }
+ if (DateTime_Empty.Equals(t)) return String.Empty;
+ else return t.ToString(DataFormat);
+ }
+
+
+ /*
+ public bool IsMyType (Type dataType)
+ {
+ bool v = (typeof (DateTime)).IsAssignableFrom (dataType);
+ return v;
+ }
+
+ public bool IsMyField(IFieldContext field)
+ {
+ bool v = (field.ProcessorID.Equals(ID));
+ return v;
+ }
+ */
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/EntryListProcessor.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/EntryListProcessor.cs
new file mode 100644
index 0000000..a968e3d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/EntryListProcessor.cs
@@ -0,0 +1,53 @@
+using System.Collections;
+using Agility.Nexus.Validators;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Transform IDictionary entries into formatted entries on a IEntryList instances.
+ /// </summary>
+ /// <remarks><p>
+ /// To implement, override NewEntryList to provide an instances of the desired type.
+ /// This will usually be an IEntryList that creates the entry objects used by your application.
+ /// The entry objects can be conventional property objects,
+ /// or objects that expose properties backed by an IDictionary, as you prefer.
+ /// </p></remarks>
+ ///
+ public abstract class EntryListProcessor : Processor
+ {
+ public override bool ConvertInput(IProcessorContext incoming)
+ {
+ incoming.Target = incoming.Source;
+ return true;
+ }
+
+ public override bool FormatOutput(IProcessorContext outgoing)
+ {
+ ProcessorCommand formatter = new FormatOutput();
+ IList source = outgoing.Source as IList;
+
+ IEntryList target = NewEntryList();
+
+ foreach (IDictionary row in source)
+ {
+ IRequestContext context = new RequestContext(row);
+ context.FieldTable = outgoing.FieldTable;
+ ICollection keys = row.Keys;
+ foreach (string key in keys)
+ {
+ IProcessorContext _context = new ProcessorContext(key, context);
+ formatter.ExecuteProcess(_context);
+ }
+ target.AddEntry(context.Criteria);
+ }
+ outgoing.Target = target;
+ return true;
+ }
+
+ /// <summary>
+ /// Override to return an instance of the desired IEntryList type.
+ /// </summary>
+ /// <returns>An IEntryList instance</returns>
+ public abstract IEntryList NewEntryList();
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/FormatOutput.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/FormatOutput.cs
new file mode 100644
index 0000000..ef7b6ac
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/FormatOutput.cs
@@ -0,0 +1,32 @@
+using System.Collections;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Format related fields from the main context to Criteria,
+ /// adding an error message to Alerts if formatting fails.
+ /// </summary>
+ public class FormatOutput : ProcessorCommand
+ {
+ public override bool ExecuteProcess(IProcessorContext outgoing)
+ {
+ string key = outgoing.FieldKey;
+ IRequestContext context = outgoing.Context;
+ IDictionary criteria = outgoing.Criteria;
+
+ bool have = (context.Contains(key));
+ if (have)
+ {
+ outgoing.Source = context[key];
+ bool okay = ExecuteFormat(outgoing);
+ if (okay)
+ // set to field buffer
+ criteria[key] = outgoing.Target;
+ else context.AddAlertForField(key);
+ return STOP;
+ }
+
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessor.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessor.cs
new file mode 100644
index 0000000..29664e9
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessor.cs
@@ -0,0 +1,15 @@
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Convert or Format a standard or custom DataType.
+ /// </summary>
+ public interface IProcessor
+ {
+ string Alert { get; set; }
+ string DataFormat { get; set; }
+ string ID { get; set; }
+
+ bool ConvertInput(IProcessorContext incoming);
+ bool FormatOutput(IProcessorContext outgoing);
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessorCommand.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessorCommand.cs
new file mode 100644
index 0000000..8a5ee5c
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessorCommand.cs
@@ -0,0 +1,35 @@
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Transform values from one data type or format to another. [OVR-13].
+ /// </summary>
+ public interface IProcessorCommand : IRequestCommand
+ {
+ /// <summary>
+ /// Provide a message template to use when a required field is missing.
+ /// </summary>
+ string Required { get; set; }
+
+ /// <summary>
+ /// Transform the value indicated by the context FieldKey, if present.
+ /// </summary>
+ /// <param name="context">The context we are processing</param>
+ /// <returns>True if nominal</returns>
+ bool ExecuteProcess(IProcessorContext context);
+
+ /// <summary>
+ /// Convert a field value, utlitizing the field table and processor.
+ /// </summary>
+ /// <param name="context">The context we are processing</param>
+ /// <returns>True if nominal</returns>
+ bool ExecuteConvert(IProcessorContext context);
+
+ /// <summary>
+ /// Format a field value, utlitizing the field table and processor.
+ /// </summary>
+ /// <param name="context">The context we are processing</param>
+ /// <returns>True if nominal</returns>
+ bool ExecuteFormat(IProcessorContext context);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessorContext.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessorContext.cs
new file mode 100644
index 0000000..439b293
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/IProcessorContext.cs
@@ -0,0 +1,46 @@
+using System.Collections;
+using Agility.Core;
+using Nexus.Core.Tables;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Encapsulate values needed by standard IProcessorCommands [OVR-13].
+ /// </summary>
+ ///
+ public interface IProcessorContext : IContext
+ {
+ /// <summary>
+ /// Identify the field under validation.
+ /// </summary>
+ ///
+ string FieldKey { get; set; }
+
+ /// <summary>
+ /// Record the source value to process.
+ /// </summary>
+ ///
+ object Source { get; set; }
+
+ /// <summary>
+ /// Record the target value after conversion or formatting.
+ /// </summary>
+ ///
+ object Target { get; set; }
+
+ /// <summary>
+ /// Identify the main IRequestContext being processed.
+ /// </summary>
+ IRequestContext Context { get; }
+
+ /// <summary>
+ /// Identify the set of input/output fields being processed.
+ /// </summary>
+ IDictionary Criteria { get; }
+
+ /// <summary>
+ /// Identify the FieldTable being utilized.
+ /// </summary>
+ IFieldTable FieldTable { get; }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/KeyValueProcessor.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/KeyValueProcessor.cs
new file mode 100644
index 0000000..ca7f671
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/KeyValueProcessor.cs
@@ -0,0 +1,44 @@
+using System.Collections;
+using Agility.Nexus.Validators;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Process the value of a KeyValue list
+ /// by setting the Key property to the Field's ID.
+ /// </summary>
+ public class KeyValueProcessor : Processor
+ {
+ private string _Key;
+
+ public string Key
+ {
+ set { _Key = value; }
+ get { return _Key; }
+ }
+
+ public override bool ConvertInput(IProcessorContext incoming)
+ {
+ incoming.Target = incoming.Source;
+ return true;
+ }
+
+ public override bool FormatOutput(IProcessorContext outgoing)
+ {
+ ProcessorCommand formatter = new FormatOutput();
+ IList source = outgoing.Source as IList;
+ foreach (IKeyValue row in source)
+ {
+ string key = Key;
+ IRequestContext context = new RequestContext();
+ context[key] = row.Value;
+ context.FieldTable = outgoing.FieldTable;
+ IProcessorContext _context = new ProcessorContext(key, context);
+ formatter.ExecuteProcess(_context);
+ row.Value = _context.Target;
+ }
+ outgoing.Target = outgoing.Source;
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/Processor.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/Processor.cs
new file mode 100644
index 0000000..74c174c
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/Processor.cs
@@ -0,0 +1,36 @@
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Implement common properties.
+ /// </summary>
+ public abstract class Processor : IProcessor
+ {
+ private string _Alert;
+
+ public string Alert
+ {
+ get { return _Alert; }
+ set { _Alert = value; }
+ }
+
+ private string _DataFormat;
+
+ public string DataFormat
+ {
+ get { return _DataFormat; }
+ set { _DataFormat = value; }
+ }
+
+ private string _ID;
+
+ public string ID
+ {
+ get { return _ID; }
+ set { _ID = value; }
+ }
+
+ public abstract bool ConvertInput(IProcessorContext incoming);
+
+ public abstract bool FormatOutput(IProcessorContext outgoing);
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/ProcessorCommand.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/ProcessorCommand.cs
new file mode 100644
index 0000000..52c0fd7
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/ProcessorCommand.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections;
+using Agility.Nexus.Validators;
+using Nexus.Core.Tables;
+
+namespace Nexus.Core.Validators
+{
+ /// <summary>
+ /// Provide a base class to use when implementating Validators.
+ /// </summary>
+ /// <remarks>
+ /// Subclasses must provide a NexusExecute method.
+ /// </remarks>
+ public abstract class ProcessorCommand : RequestCommand, IProcessorCommand
+ {
+ #region IRequestCommand
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ ProcessRelated(context);
+ ProcessRequired(context);
+ return context.HasAlerts;
+ }
+
+ #endregion
+
+ #region IProcessorCommand
+
+ private string _Template = null;
+
+ public virtual string Required
+ {
+ get { return _Template; }
+ set { _Template = value; }
+ }
+
+ /// <summary>
+ /// Convert input for fields that do not have a Processor.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to pass through the objects, verbatim.
+ /// </remarks>
+ /// <param name="context">The IProcessorContext</param>
+ public virtual bool ConvertInput(IProcessorContext context)
+ {
+ context.Target = context.Source;
+ return true;
+ }
+
+ public virtual bool ExecuteConvert(IProcessorContext context)
+ {
+ bool okay;
+ string id = context.FieldKey;
+ IFieldTable table = context.FieldTable;
+ IFieldContext fieldContext = table.GetFieldContext(id); // enforces Strict
+
+ if ((fieldContext == null))
+ {
+ ConvertInput(context);
+ return true;
+ }
+
+ IProcessor processor = fieldContext.Processor;
+ if (processor == null)
+ okay = ConvertInput(context);
+ else
+ {
+ okay = processor.ConvertInput(context);
+ }
+ return okay;
+ }
+
+ /// <summary>
+ /// Format output for fields that do not have a Processor.
+ /// </summary>
+ /// <remarks>
+ /// The default behavior is to pass through nulls and ICollection types
+ /// and to call ToString on everything else.
+ /// </remarks>
+ /// <param name="context">The IProcessorContext</param>
+ public virtual bool FormatOutput(IProcessorContext context)
+ {
+ if (context.Source != null)
+ {
+ Type sourceType = context.Source.GetType();
+ if (IsCollectionType(sourceType)) context.Target = context.Source;
+ else context.Target = context.Source.ToString();
+ }
+ return true;
+ }
+
+ public virtual bool ExecuteFormat(IProcessorContext context)
+ {
+ bool okay = false;
+ string id = context.FieldKey;
+ object source = context.Source;
+ IFieldTable table = context.FieldTable;
+ IFieldContext fieldContext = table.GetFieldContext(id); // Enforces Strict
+
+ if ((fieldContext == null))
+ {
+ if (source == null)
+ context.Target = null;
+ else okay = FormatOutput(context);
+ return okay;
+ }
+
+ IProcessor processor = fieldContext.Processor;
+ if (processor == null)
+ okay = FormatOutput(context);
+ else
+ {
+ okay = processor.FormatOutput(context);
+ }
+ return okay;
+ }
+
+ private bool IsCollectionType(Type dataType)
+ {
+ bool v = (typeof (ICollection)).IsAssignableFrom(dataType);
+ return (v);
+ }
+
+ public abstract bool ExecuteProcess(IProcessorContext context);
+
+ #endregion
+
+ #region ProcessRequired
+
+ private void AssertProcessRequired(IRequestContext context)
+ {
+ IDictionary criteria = context.Criteria;
+ if (null == criteria)
+ throw new ArgumentNullException("Criteria==null", "BaseValidator.NexusExecute.AssertProcessRequired");
+ }
+
+ private void ProcessRequired(IRequestContext context)
+ {
+ IList requiredIDs = context.CommandBin.RequiredIDs; // inner list
+ if (requiredIDs == null) return;
+
+ IList runtimeIDs = context.CommandBin.RuntimeIDs; // inner list
+ if (runtimeIDs != null)
+ {
+ IEnumerator runtime = runtimeIDs.GetEnumerator();
+ while (runtime.MoveNext())
+ {
+ string id = runtime.Current as string;
+ requiredIDs.Remove(id);
+ }
+ }
+
+ IEnumerator required = requiredIDs.GetEnumerator();
+ while (required.MoveNext())
+ {
+ string id = required.Current as string;
+ bool okay = (context.Contains(id) && (null != context[id]) && (!String.Empty.Equals(context[id].ToString())));
+ if (!okay)
+ {
+ context.AddAlertRequired(id);
+ }
+ }
+ }
+
+ #endregion
+
+ #region ProcessRelated
+
+ private void AssertProcessRelated(IRequestContext context)
+ {
+ AssertProcessRequired(context);
+
+ IFieldTable table = context.FieldTable;
+ if (null == table)
+ throw new ArgumentNullException("FieldTable==null", "BaseValidator.NexusExecute.AssertProcessRelated");
+ }
+
+ private void ProcessRelated(IRequestContext context)
+ {
+ AssertProcessRelated(context);
+
+ ICollection related = CombinedIDs(context);
+ foreach (string key in related)
+ {
+ IProcessorContext _context = new ProcessorContext(key, context);
+ ExecuteProcess(_context);
+ }
+ }
+
+ private ICollection CombinedIDs(IRequestContext context)
+ {
+ IDictionary combined = new Hashtable();
+ IList relatedIDs = context.CommandBin.RelatedIDs; // outer list
+ // Add Command ID to related list (since we store outcome under our own ID)
+ // This code relies on RelatedIDs being lazily instantiated.
+ string id = context.CommandBin.ID;
+ bool found_self = relatedIDs.Contains(id);
+ if (!found_self) relatedIDs.Add(id);
+ foreach (string i in relatedIDs) combined[i] = i;
+ IList requiredIDs = context.CommandBin.RequiredIDs; // inner list
+ if (requiredIDs != null) foreach (string i in requiredIDs) combined[i] = i;
+ return combined.Keys;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/ProcessorContext.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/ProcessorContext.cs
new file mode 100644
index 0000000..79edf2d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/ProcessorContext.cs
@@ -0,0 +1,63 @@
+using System.Collections;
+using Agility.Core;
+using Nexus.Core;
+using Nexus.Core.Tables;
+using Nexus.Core.Validators;
+
+namespace Agility.Nexus.Validators
+{
+ /// <summary>
+ /// Implement IProcessorContext.
+ /// </summary>
+ public class ProcessorContext : Context, IProcessorContext
+ {
+ public ProcessorContext()
+ {
+ }
+
+ public ProcessorContext(string key, object source)
+ {
+ FieldKey = key;
+ Source = source;
+ }
+
+ public ProcessorContext(string key, IRequestContext context)
+ {
+ FieldKey = key;
+ this[Tokens.Context] = context;
+ }
+
+ public string FieldKey
+ {
+ get { return this[Tokens.FieldKey] as string; }
+ set { this[Tokens.FieldKey] = value; }
+ }
+
+ public object Source
+ {
+ get { return this[Tokens.Source]; }
+ set { this[Tokens.Source] = value; }
+ }
+
+ public object Target
+ {
+ get { return this[Tokens.Target]; }
+ set { this[Tokens.Target] = value; }
+ }
+
+ public IRequestContext Context
+ {
+ get { return this[Tokens.Context] as IRequestContext; }
+ }
+
+ public IDictionary Criteria
+ {
+ get { return Context.Criteria; }
+ }
+
+ public IFieldTable FieldTable
+ {
+ get { return Context.FieldTable; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Core/Validators/StringProcessor.cs b/struts-sandbox/overdrive/Nexus/Core/Validators/StringProcessor.cs
new file mode 100644
index 0000000..5335b81
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Core/Validators/StringProcessor.cs
@@ -0,0 +1,53 @@
+using System;
+
+namespace Nexus.Core.Validators
+{
+ public class StringProcessor : Processor
+ {
+ #region IProcessor
+
+ public override bool ConvertInput(IProcessorContext incoming)
+ {
+ string source = incoming.Source as string;
+ incoming.Target = String_Convert(source);
+ return true;
+ }
+
+ public override bool FormatOutput(IProcessorContext outgoing)
+ {
+ object source = outgoing.Source;
+ outgoing.Target = String_Format(source);
+ return true;
+ }
+
+ #endregion
+
+ private string String_Empty = String.Empty;
+
+ private string String_Convert(string source)
+ {
+ bool isNull = (source == null);
+ return isNull ? String_Empty : source;
+ // If null, return empty string rather than null
+ }
+
+ private string String_Format(object source)
+ {
+ string t = String_Empty;
+ if (source == null) return t;
+ string format = (DataFormat == null) ? t : DataFormat;
+ if (format.Equals(t)) return source.ToString();
+ return String.Format(format, source);
+ }
+
+ /*
+ private bool IsMyType (Type dataType)
+ {
+ bool v = (typeof (string).IsAssignableFrom (dataType));
+ return v;
+ }
+ */
+
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Extras/AssemblyInfo.cs b/struts-sandbox/overdrive/Nexus/Extras/AssemblyInfo.cs
new file mode 100644
index 0000000..05af947
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Extras/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Extras/Extras.csproj b/struts-sandbox/overdrive/Nexus/Extras/Extras.csproj
new file mode 100644
index 0000000..37e813d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Extras/Extras.csproj
@@ -0,0 +1,130 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{7931CACD-0E73-4DD2-A373-FF6A01CE6186}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "Nexus.Extras"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = "$(SolutionDir)postbuild.bat $(TargetDir) $(TargetName) $(SolutionName) $(SolutionDir)"
+ RootNamespace = "Nexus.Extras"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = "Nexus.Extras.xml"
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = "1591"
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "Core"
+ Project = "{7C8CAFD4-1E45-41B4-9963-F51199B12EA7}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ <Reference
+ Name = "Agility.Core"
+ AssemblyName = "Agility.Core"
+ HintPath = "..\..\local-cache\Agility\Agility.Core.dll"
+ />
+ <Reference
+ Name = "Spring.Core"
+ AssemblyName = "Spring.Core"
+ HintPath = "..\..\local-cache\SpringNet\Spring.Core.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Spring\Catalog.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Spring\FieldContext.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Spring\FieldTable.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Spring\Objects.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/Nexus/Extras/Spring/Catalog.cs b/struts-sandbox/overdrive/Nexus/Extras/Spring/Catalog.cs
new file mode 100644
index 0000000..1d4c9c4
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Extras/Spring/Catalog.cs
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Agility.Core;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using Nexus.Core.Tables;
+using Spring.Context;
+
+namespace Nexus.Extras.Spring
+{
+ /// <summary>
+ /// Implement IRequestCatalog
+ /// using Spring as an IOC container [OVR-8].
+ /// </summary>
+ ///
+ public class Catalog : IRequestCatalog, IApplicationContextAware
+ {
+ #region Messages
+
+ private const string msg_ADD_COMMAND = "This catalog instance is created through dependency injection.";
+ private const string msg_MISSING = "Object is not found in Factory.";
+ private const string msg_NULL = "Object ID cannot be null.";
+ private const string msg_TYPE = "Command is not a IRequestCommand or IRequestChain.";
+ private const string msg_CATALOG_CONTEXT_NULL = "Catalog: Context cannot be null!";
+ private const string msg_CATALOG_COMMAND_NULL = "Catalog: Command within Context cannot be null! -- Was Context retrieved from Catalog?";
+
+ #endregion
+
+ #region IApplicationContextAware
+
+ private IApplicationContext _Factory = null;
+
+ public IApplicationContext ApplicationContext
+ {
+ get { return _Factory; }
+ set { _Factory = value; }
+ }
+
+ #endregion
+
+ #region IRequestCatalog
+
+ public object GetObject(string name)
+ {
+ if (null == name)
+ {
+ Exception e = new Exception(msg_NULL);
+ throw(e);
+ }
+ object o = Factory().GetObject(name);
+ if (o == null)
+ {
+ Exception e = new Exception(msg_MISSING);
+ throw(e);
+ }
+ return o;
+ }
+
+ public IViewHelper GetHelperFor(string command)
+ {
+ IViewHelper helper = ViewHelper;
+ helper.Catalog = this;
+ helper.Command = GetRequestCommand(command);
+ return helper;
+ }
+
+ /// <summary>
+ /// Not implemented as Catalog is expected to be created by an IOC framework.
+ /// </summary>
+ /// <param name="name">ID for command</param>
+ /// <param name="command">Command instance</param>
+ public void AddCommand(string name, ICommand command)
+ {
+ throw new NotImplementedException(msg_ADD_COMMAND); // OK
+ }
+
+ public ICommand GetCommand(string name)
+ {
+ object o = GetObject(name);
+ return o as ICommand;
+ }
+
+ public IRequestCommand GetRequestCommand(string name)
+ {
+ ICommand c = GetCommand(name);
+ IRequestCommand command = c as IRequestCommand;
+ if (command == null)
+ {
+ Exception e = new Exception(msg_TYPE);
+ throw(e);
+ }
+ return command;
+ }
+
+ public IEnumerator GetNames()
+ {
+ string[] names = _Factory.GetObjectDefinitionNames();
+ IEnumerator enu = names.GetEnumerator();
+ return enu;
+ }
+
+ #endregion
+
+ #region IRequestCatalog
+
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ public Catalog()
+ {
+ }
+
+ /// <summary>
+ /// Construct object and set ApplicationContext.
+ /// </summary>
+ /// <param name="value">Our ApplicationContext</param>
+ public Catalog(IApplicationContext value)
+ {
+ ApplicationContext = value;
+ }
+
+ /// <summary>
+ /// Provide the IApplicationContext instance.
+ /// </summary>
+ /// <returns>IApplicationContext instance</returns>
+ public IApplicationContext Factory()
+ {
+ return _Factory;
+ }
+
+ private IFieldTable _FieldTable;
+
+ public IFieldTable FieldTable
+ {
+ get { return _FieldTable; }
+ set { _FieldTable = value; }
+ }
+
+ private IRequestCommand _PreOp;
+
+ public IRequestCommand PreOp
+ {
+ get { return _PreOp; }
+ set { _PreOp = value; }
+ }
+
+ private IRequestCommand _PostOp;
+
+ public IRequestCommand PostOp
+ {
+ get { return _PostOp; }
+ set { _PostOp = value; }
+ }
+
+ private IViewHelper _ViewHelper;
+
+ public IViewHelper ViewHelper
+ {
+ get { return _ViewHelper; }
+ set { _ViewHelper = value; }
+ }
+
+ public IRequestContext GetRequestContext(string name)
+ {
+ ICommand _command = GetCommand(name);
+ IRequestCommand _rc = _command as IRequestCommand;
+ return GetRequestContext(_rc);
+ }
+
+ public IRequestContext GetRequestContext(IRequestCommand command)
+ {
+ IRequestContext context;
+ try
+ {
+ context = command.NewContext();
+ context[Tokens.CommandBin] = command;
+ context[Tokens.FieldTable] = FieldTable;
+ // TODO: MessageTable
+ }
+ catch (Exception e)
+ {
+ context = new RequestContext();
+ context.Fault = e;
+ // ISSUE: Log exception(faults) (Log all errors in verbose mode?)
+ // ISSUE: Provide an alternate location on fault? -- Declarative exception handing
+ }
+ return context;
+
+ }
+
+ public IRequestContext GetRequestContext(string name, IDictionary input)
+ {
+ IRequestContext context = GetRequestContext(name);
+ context.Criteria = input;
+ return context;
+ }
+
+ /// <summary>
+ /// Confirm that the Context is not null, and the Context's Command is not null.
+ /// </summary>
+ /// <param name="context">IRequestContext to verify</param>
+ /// <returns>The non-null Command for this Context</returns>
+ private IRequestCommand VerifyRequest(IRequestContext context)
+ {
+ if (null == context)
+ {
+ context = new RequestContext();
+ context.AddAlert(msg_CATALOG_CONTEXT_NULL);
+ }
+
+ IRequestCommand command = context[Tokens.CommandBin] as IRequestCommand;
+
+ if (null == command)
+ context.AddAlert(msg_CATALOG_COMMAND_NULL);
+
+ return command;
+ }
+
+ public IRequestContext ExecuteRequest(string name)
+ {
+ IRequestContext context = GetRequestContext(name);
+ ExecuteRequest(context);
+ return context;
+ }
+
+ public void ExecuteRequest(IRequestContext context)
+ {
+ IRequestCommand command = VerifyRequest(context);
+ if (context.IsNominal)
+ {
+ try
+ {
+ command.Execute(context);
+ }
+ catch (Exception e)
+ {
+ context.Fault = e;
+ }
+ }
+
+ // ISSUE: Log exception(faults) (Log all errors in verbose mode?)
+ // ISSUE: Provide an alternate location on fault? -- Declarative exception handing?
+ }
+
+ public void ExecuteView(IRequestContext context)
+ {
+ IRequestCommand command = VerifyRequest(context);
+ if (context.IsNominal)
+ {
+ IChain chain = new Chain();
+ if (_PreOp != null) chain.AddCommand(_PreOp);
+ chain.AddCommand(command);
+ if (_PostOp != null) chain.AddCommand(_PostOp);
+ try
+ {
+ chain.Execute(context);
+ }
+ catch (Exception e)
+ {
+ context.Fault = e;
+ }
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Extras/Spring/FieldContext.cs b/struts-sandbox/overdrive/Nexus/Extras/Spring/FieldContext.cs
new file mode 100644
index 0000000..d1ca660
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Extras/Spring/FieldContext.cs
@@ -0,0 +1,183 @@
+using System;
+using Agility.Core;
+using Nexus.Core;
+using Nexus.Core.Tables;
+using Nexus.Core.Validators;
+using Spring.Context;
+
+namespace Nexus.Extras.Spring
+{
+ /// <summary>
+ /// Concrete IFieldContext implementation that uses Spring MessageSource to resolve text .
+ /// </summary>
+ /// <remarks><p>
+ /// This implementation *requires* that a Spring MessageSource be exposed to each the FieldContext member.
+ /// The simplest way to do that is by using a base FieldContext in the Spring configuration file.
+ /// The MessageSource property can be set once in the base and inherited by the others.
+ /// </p><p>
+ /// In this implementation,
+ /// the text properties -- Alert, Hint, Help, Label, and Required -- are read-only
+ /// and cannot be accessed with a MessageSource property.
+ /// When the property is read,
+ /// the method looks for a message resource that shares the same ID as the FieldContext,
+ /// but with a "_property" suffix (_alert, _hint, _help, _label, _required).
+ /// So, if the FieldContext ID is LastName, then reading its Alert will look for a message
+ /// resource named "LastName_alert".
+ /// </p><p>
+ /// In the case of an Alert, a message may also be provided by the Processor.
+ /// If so, then the Processor message supercedes the default message.
+ /// In this way, you can set a default for all the controls,
+ /// and then override the default for specific processors.
+ /// </p><p>
+ /// To provide a default Alert or Required to use when no other is provided,
+ /// provide a Message Resource entry in the form: "_alert" or "_required".
+ /// </p><p>
+ /// If a Label message is not found, the FieldContext ID is returned instead.
+ /// Otherwise, if no message is found,
+ /// then the FieldContext ID and property tag (e.g. "LastName_required")
+ /// is returned.
+ /// </p></remarks>
+ ///
+ [Serializable]
+ public class FieldContext : Context, IFieldContext
+ {
+ public FieldContext() : base()
+ {
+ ControlTypeName = Tokens.CONTROL_INPUT; // Default
+ }
+
+ public string ControlTypeName
+ {
+ get { return this[Tokens.ControlTypeName] as string; }
+ set { this[Tokens.ControlTypeName] = value; }
+ }
+
+ public string ID
+ {
+ get { return this[Tokens.ID] as string; }
+ set { this[Tokens.ID] = value; }
+ }
+
+ public IProcessor Processor
+ {
+ get { return this[Tokens.Processor] as IProcessor; }
+ set { this[Tokens.Processor] = value; }
+ }
+
+ #region text properties
+
+ private IMessageSource _MessageSource;
+
+ /// <summary>
+ /// Identify the message source for this FieldContext.
+ /// </summary>
+ /// <exception cref="System.InvalidOperationException">
+ /// If the context has not been initialized yet.
+ /// </exception>
+ public IMessageSource MessageSource
+ {
+ get { return _MessageSource; }
+ set { _MessageSource = value; }
+ }
+
+ /// <summary>
+ /// Resolve the message.
+ /// </summary>
+ /// <param name="name">The name of the resource to get.</param>
+ /// <returns>
+ /// The resolved message if the lookup was successful. Otherwise, it either throws
+ /// an exception or returns the resource name, depending on the implementation.
+ /// </returns>
+ private string GetMessage(string name)
+ {
+ return MessageSource.GetMessage(name);
+ }
+
+ /// <summary>
+ /// Resolve the message or return null.
+ /// </summary>
+ /// <param name="name">The name of the resource to get.</param>
+ /// <returns>A resolved message or null if the message could not be located for any reason.</returns>
+ private string GetMessageOrNull(string name)
+ {
+ string _name = null;
+ try
+ {
+ _name = GetMessage(name);
+ }
+ catch (Exception e)
+ {
+ e = e; // silly assignment
+ _name = null;
+ }
+ return _name;
+ }
+
+ /// <summary>
+ /// Return the message for the Processor,
+ /// or the message for the FieldContext,
+ /// or the message for the suffix,
+ /// or the FieldContext ID and suffix verbatim,
+ /// if all else fails.
+ /// </summary>
+ /// <param name="root">FieldContext ID</param>
+ /// <param name="suffix">Message type</param>
+ /// <returns>A message or the root+suffix</returns>
+ private string GetText(string root, string suffix)
+ {
+ string text = null;
+ IProcessor processor = Processor;
+ string id = null;
+ if (processor != null) id = processor.ID;
+ if (id != null) text = GetMessageOrNull(id + suffix);
+ if (text == null)
+ {
+ text = GetMessageOrNull(root + suffix);
+ }
+ if (text == null)
+ {
+ text = GetMessageOrNull(suffix);
+ }
+ if (text == null) text = root + suffix;
+
+ return text;
+ }
+
+ public string Alert
+ {
+ get { return GetText(this.ID, "_alert"); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public string Hint
+ {
+ get { return GetText(this.ID, "_hint"); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public string Help
+ {
+ get { return GetText(this.ID, "_help"); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public string Label
+ {
+ get
+ {
+ string label = GetMessageOrNull(this.ID + "_label");
+ if (label == null) label = ID;
+ return label;
+ }
+ set { throw new NotSupportedException(); }
+ }
+
+ public string Required
+ {
+ get { return GetText(this.ID, "_required"); }
+ set { throw new NotSupportedException(); }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Extras/Spring/FieldTable.cs b/struts-sandbox/overdrive/Nexus/Extras/Spring/FieldTable.cs
new file mode 100644
index 0000000..525c0b2
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Extras/Spring/FieldTable.cs
@@ -0,0 +1,34 @@
+using Nexus.Core.Tables;
+using Spring.Context;
+
+namespace Nexus.Extras.Spring
+{
+ /// <summary>
+ /// Companion to Nexus.Extras.Spring.FieldContext.
+ /// </summary>
+ public class FieldTable : Core.Tables.FieldTable
+ {
+ private IMessageSource _MessageSource;
+
+ /// <summary>
+ /// Identify the message source for this FieldTable.
+ /// </summary>
+ /// <exception cref="System.InvalidOperationException">
+ /// If the context has not been initialized yet.
+ /// </exception>
+ public IMessageSource MessageSource
+ {
+ get { return _MessageSource; }
+ set { _MessageSource = value; }
+ }
+
+ public override IFieldContext NewFieldContext(string id)
+ {
+ FieldContext field = new FieldContext();
+ field.ID = id;
+ field.MessageSource = this.MessageSource;
+ return field;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Extras/Spring/Objects.cs b/struts-sandbox/overdrive/Nexus/Extras/Spring/Objects.cs
new file mode 100644
index 0000000..801f35a
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Extras/Spring/Objects.cs
@@ -0,0 +1,51 @@
+using System;
+using Spring.Context;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Xml;
+
+namespace Agility.Extras.Spring
+{
+ /// <summary>
+ /// A singleton implementation of the IHelper protocol,
+ /// using static methods and the Spring object factory.
+ /// </summary>
+ /// <remarks><p>
+ /// Since static methods are used here, as a convenience,
+ /// it is not possible to implement IHelper.
+ /// However, the same method signatures are otherwise used.
+ /// </p><p>
+ /// Of course, an alternative is to provide the Factory
+ /// method a singlton, and then obtain the Helpers
+ /// class from the Factory, but implementing the
+ /// IHelpers interface as a singleton seems simpler.
+ /// </p></remarks>
+ public class Objects
+ {
+ private static string FILE = "/Objects.xml";
+
+ private Objects()
+ {
+ // private constructor prevents instantiation.
+ }
+
+ // ISSUE: Remove this kludge and adopt latest iBATIS approach.
+ private static string _rootDirectory =
+ AppDomain.CurrentDomain.BaseDirectory.Replace(@"\bin", "").Replace(@"\Debug", "").Replace(@"\Release", "");
+
+ private static volatile IApplicationContext _Factory = null;
+
+ public static IApplicationContext Factory()
+ {
+ if (_Factory == null)
+ {
+ lock (typeof (XmlObjectFactory))
+ {
+ string foo = "file://" + _rootDirectory + FILE;
+ if (_Factory == null) // double-check
+ _Factory = new XmlApplicationContext(foo);
+ }
+ }
+ return _Factory;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/LICENSE.txt b/struts-sandbox/overdrive/Nexus/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/struts-sandbox/overdrive/Nexus/NOTICE.txt b/struts-sandbox/overdrive/Nexus/NOTICE.txt
new file mode 100644
index 0000000..73c4637
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/NOTICE.txt
@@ -0,0 +1,6 @@
+NOTICE
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the Apache Software Foundation and was
+originally based, in part, on public domain software written by the
+Oklahoma Department of Environmental Quality, Oklahoma City OK US.
diff --git a/struts-sandbox/overdrive/Nexus/Nexus.sln b/struts-sandbox/overdrive/Nexus/Nexus.sln
new file mode 100644
index 0000000..926ad3b
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Nexus.sln
@@ -0,0 +1,48 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{7C8CAFD4-1E45-41B4-9963-F51199B12EA7}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{C533FFAA-CB2B-40CD-B3C2-77394E4D9222}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7C8CAFD4-1E45-41B4-9963-F51199B12EA7} = {7C8CAFD4-1E45-41B4-9963-F51199B12EA7}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Extras", "Extras\Extras.csproj", "{7931CACD-0E73-4DD2-A373-FF6A01CE6186}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "http://localhost/Nexus/Web.csproj", "{2BD7CDE0-01F7-4CC5-9AE9-2F9470FB7007}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {7C8CAFD4-1E45-41B4-9963-F51199B12EA7}.Debug.ActiveCfg = Debug|.NET
+ {7C8CAFD4-1E45-41B4-9963-F51199B12EA7}.Debug.Build.0 = Debug|.NET
+ {7C8CAFD4-1E45-41B4-9963-F51199B12EA7}.Release.ActiveCfg = Release|.NET
+ {7C8CAFD4-1E45-41B4-9963-F51199B12EA7}.Release.Build.0 = Release|.NET
+ {C533FFAA-CB2B-40CD-B3C2-77394E4D9222}.Debug.ActiveCfg = Debug|.NET
+ {C533FFAA-CB2B-40CD-B3C2-77394E4D9222}.Debug.Build.0 = Debug|.NET
+ {C533FFAA-CB2B-40CD-B3C2-77394E4D9222}.Release.ActiveCfg = Release|.NET
+ {C533FFAA-CB2B-40CD-B3C2-77394E4D9222}.Release.Build.0 = Release|.NET
+ {7931CACD-0E73-4DD2-A373-FF6A01CE6186}.Debug.ActiveCfg = Debug|.NET
+ {7931CACD-0E73-4DD2-A373-FF6A01CE6186}.Debug.Build.0 = Debug|.NET
+ {7931CACD-0E73-4DD2-A373-FF6A01CE6186}.Release.ActiveCfg = Release|.NET
+ {7931CACD-0E73-4DD2-A373-FF6A01CE6186}.Release.Build.0 = Release|.NET
+ {2BD7CDE0-01F7-4CC5-9AE9-2F9470FB7007}.Debug.ActiveCfg = Debug|.NET
+ {2BD7CDE0-01F7-4CC5-9AE9-2F9470FB7007}.Debug.Build.0 = Debug|.NET
+ {2BD7CDE0-01F7-4CC5-9AE9-2F9470FB7007}.Release.ActiveCfg = Release|.NET
+ {2BD7CDE0-01F7-4CC5-9AE9-2F9470FB7007}.Release.Build.0 = Release|.NET
+ EndGlobalSection
+ GlobalSection(SolutionItems) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/struts-sandbox/overdrive/Nexus/Test/AssemblyInfo.cs b/struts-sandbox/overdrive/Nexus/Test/AssemblyInfo.cs
new file mode 100644
index 0000000..05af947
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/BaseNexusTest.cs b/struts-sandbox/overdrive/Nexus/Test/BaseNexusTest.cs
new file mode 100644
index 0000000..926c4a5
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/BaseNexusTest.cs
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using System.Text;
+using Agility.Core;
+using Agility.Extras.Spring;
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+using Spring.Context;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Provide base SetUp method and convenience methods
+ /// for tests that use a IRequestCatalog.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class CatalogBaseTest
+ {
+ /// <summary>
+ /// Catalog instance that tests can use.
+ /// </summary>
+ protected IRequestCatalog catalog;
+
+ /// <summary>
+ /// Setup catalog between tests.
+ /// </summary>
+ ///
+ [SetUp]
+ public virtual void SetUp()
+ {
+ IApplicationContext factory = Objects.Factory();
+ catalog = factory.GetObject("Catalog") as IRequestCatalog;
+ }
+
+ /// <summary>
+ /// Exercise Setup method.
+ /// </summary>
+ ///
+ [Test]
+ public void AssertSetUp()
+ {
+ Assert.IsTrue(catalog != null, "Expected non-null catalog.");
+ }
+
+ #region IRequestContext tests
+
+ /// <summary>
+ /// Determine if the context contains each key in keys.
+ /// </summary>
+ /// <param name="context">Context to process</param>
+ /// <param name="keys">Keys to verify</param>
+ /// <returns>True if contact contains each key in keys</returns>
+ protected bool ContainsKeys(IContext context, string[] keys)
+ {
+ bool found = true;
+ foreach (string key in keys)
+ {
+ found = found && context.Contains(key);
+ }
+ return found;
+ }
+
+ /// <summary>
+ /// Determine if the Criteria for context contains each key in keys.
+ /// </summary>
+ /// <param name="context">Context to process</param>
+ /// <param name="keys">Keys to verify</param>
+ /// <returns>True if Criteria for contact contains each key in keys</returns>
+ public bool ContainsCriteriaKeys(IRequestContext context, string[] keys)
+ {
+ if (!context.HasCriteria()) return false;
+
+ IDictionary criteria = context.Criteria;
+ bool found = true;
+ foreach (string v in keys)
+ {
+ found = found && criteria.Contains(v);
+ }
+ return found;
+ }
+
+ protected void FaultText(Exception fault)
+ {
+ StringBuilder text = new StringBuilder("[");
+ text.Append(fault.Message);
+ text.Append("] ");
+ text.Append(fault.Source);
+ text.Append(fault.StackTrace);
+ Assert.Fail(text.ToString());
+ }
+
+ /// <summary>
+ /// Convenience method to confirm that no Exception was caught.
+ /// </summary>
+ /// <param name="context">Context under test</param>
+ ///
+ public void AssertNoFault(IRequestContext context)
+ {
+ if (context.HasFault)
+ {
+ FaultText(context.Fault);
+ }
+ }
+
+ /// <summary>
+ /// Convenience method to confirm that no Exception was caught.
+ /// </summary>
+ /// <param name="helper">Helper under test</param>
+ ///
+ public void AssertNoFault(IViewHelper helper )
+ {
+ if (helper.HasFault) FaultText(helper.Fault) ;
+ }
+
+ /// <summary>
+ /// Convenience method to confirm
+ /// that there are no alerts or fault.
+ /// </summary>
+ /// <param name="context">Context under test</param>
+ ///
+ public void AssertNominal(IRequestContext context)
+ {
+ AssertNoFault(context);
+ bool hasAlerts = context.HasAlerts;
+ if (hasAlerts)
+ {
+ // TODO: Use new TextOnly method here.
+ StringBuilder outer = new StringBuilder();
+ IDictionary store = context.Alerts;
+ ICollection keys = store.Keys;
+ foreach (string key in keys)
+ {
+ StringBuilder inner = new StringBuilder();
+ inner.Append(key);
+ inner.Append(": ");
+ IList messages = store[key] as IList;
+ foreach (string message in messages)
+ {
+ inner.Append(message);
+ inner.Append(";");
+ }
+ outer.Append(inner.ToString());
+ outer.Append("/n");
+ }
+ Assert.Fail(outer.ToString());
+ }
+ }
+
+ /// <summary>
+ /// Convenience method to confirm
+ /// that there are no alerts or fault.
+ /// </summary>
+ /// <param name="helper">Helper under test</param>
+ ///
+ public void AssertNominal(IViewHelper helper)
+ {
+ AssertNoFault(helper);
+
+ bool hasAlerts = helper.HasAlerts;
+ if (hasAlerts)
+ {
+ Assert.Fail(helper.AlertsText);
+ }
+ }
+
+ /// <summary>
+ /// Confirm that the value is stored in the context under the key.
+ /// </summary>
+ /// <param name="context">The context to check</param>
+ /// <param name="key">The key</param>
+ /// <param name="value">The value</param>
+ protected void AssertKey(IDictionary context, string key, string value)
+ {
+ Assert.IsNotNull(value, "Value is null");
+ Assert.IsNotNull(key, "Key is null");
+ Assert.IsTrue(value.Equals(context[key]), "Key:Value mismatch: " + key + ":" + value);
+ }
+
+ /// <summary>
+ /// Confirm that the given context contains the given keys.
+ /// </summary>
+ /// <param name="context">The context to check</param>
+ /// <param name="keys">The keys to check</param>
+ protected void AssertKeys(IRequestContext context, string[] keys)
+ {
+ Assert.IsTrue(ContainsKeys(context, keys), "Missing keys.");
+ }
+
+ /// <summary>
+ /// Confirm that the context contains the keys,
+ /// that each key represents an non-null IList,
+ /// and that each IList is not empty.
+ /// </summary>
+ /// <param name="context">The context to check</param>
+ /// <param name="keys">The list keys</param>
+ protected void AssertListKeys(IRequestContext context, string[] keys)
+ {
+ AssertKeys(context, keys);
+ foreach (string key in keys)
+ {
+ IList list = context[key] as IList;
+ Assert.IsNotNull(list, "List is null: " + key);
+ Assert.IsTrue(list.Count > 0, "List is empty");
+ }
+ }
+
+ /// <summary>
+ /// Call AssertList(string,int) with no minimum.
+ /// </summary>
+ /// <param name="id"></param>
+ protected IRequestContext AssertList(string id)
+ {
+ return AssertList(id, 0);
+ }
+
+ /// <summary>
+ /// Execute the Command for the given id,
+ /// and confirm that the return state is Nominal,
+ /// has an Outcome,
+ /// that the Outcome is an non-null IList,
+ /// and that the IList containes at list minCount items.
+ /// </summary>
+ /// <param name="id">The List Command to check</param>
+ /// <param name="minCount">The minimum number of items</param>
+ protected IRequestContext AssertList(string id, int minCount)
+ {
+ IRequestContext context = catalog.GetRequestContext(id);
+ catalog.ExecuteRequest(context);
+ AssertNominal(context);
+ Assert.IsTrue(context.HasOutcome, "Expected outcome");
+ IList list = context.Outcome as IList;
+ Assert.IsNotNull(list, "Expected outcome as IList");
+ Assert.IsTrue(list.Count >= minCount, "Expected list entries");
+ return context;
+ }
+
+ #endregion
+
+ #region data access tests
+
+ /// <summary>
+ /// Virtual method for populating a context
+ /// for use with other routine tests.
+ /// </summary>
+ /// <param name="context"></param>
+ protected virtual void Populate(IDictionary context)
+ {
+ // override to populate context
+ throw new NotImplementedException("CatalogBaseTest.Populate must be overridden.");
+ }
+
+ /// <summary>
+ /// Virtual method for populating a context
+ /// for an insert test.
+ /// </summary>
+ /// <param name="context"></param>
+ protected virtual void PopulateInsert(IDictionary context)
+ {
+ Populate(context);
+ }
+
+ /// <summary>
+ /// Insert and then delete a new record,
+ /// calling the Populate method to fill the context with the appropriate values.
+ /// </summary>
+ /// <param name="insertId">The "save" command name</param>
+ /// <param name="keyId">The name of the primary key field</param>
+ /// <param name="keyValue">The primary key value initially set by Populate</param>
+ /// <param name="deleteId">The "delete" command name</param>
+ protected IRequestContext AssertInsertDelete(string insertId, string keyId, string keyValue, string deleteId)
+ {
+ IRequestContext context = catalog.GetRequestContext(insertId);
+ PopulateInsert(context);
+ context[keyId] = String.Empty;
+
+ catalog.ExecuteRequest(context);
+ AssertNominal(context);
+ Assert.IsFalse(keyValue.Equals(context[keyId]), "Expected new primary key");
+
+ ICommand delete = catalog.GetCommand(deleteId);
+ delete.Execute(context);
+ AssertNominal(context);
+ return context;
+ }
+
+ protected IRequestContext AssertEdit(string editId, string keyId, string keyValue, string[] keys)
+ {
+ IRequestContext context = catalog.GetRequestContext(editId);
+ context[keyId] = keyValue;
+ catalog.ExecuteRequest(context);
+ AssertNominal(context);
+ Assert.IsTrue(ContainsKeys(context, keys), "Missing fields");
+ return context;
+ }
+
+ /// <summary>
+ /// Update the given record (usually to the same values).
+ /// </summary>
+ /// <param name="updateId">The "save" command</param>
+ /// <param name="keyId">The name of the primary key</param>
+ /// <param name="keyValue">The value of the primary key</param>
+ protected IRequestContext AssertUpdate(string updateId, string keyId, string keyValue)
+ {
+ IRequestContext context = catalog.GetRequestContext(updateId);
+ Populate(context);
+ catalog.ExecuteRequest(context);
+ AssertNominal(context);
+ Assert.IsTrue(keyValue.Equals(context[keyId]));
+ return context;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Commands/ListAll.cs b/struts-sandbox/overdrive/Nexus/Test/Commands/ListAll.cs
new file mode 100644
index 0000000..4f96ac5
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Commands/ListAll.cs
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+
+namespace Nexus.Core.Commands
+{
+ /// <summary>
+ /// Return a list as the outcome.
+ /// </summary>
+ ///
+ public class ListAll : RequestCommand
+ {
+ /// <summary>
+ /// Test ID for Command.
+ /// </summary>
+ ///
+ public const string LIST_ALL = "ListAll";
+
+ /// <summary>
+ /// Fake name for test data.
+ /// </summary>
+ ///
+ private const string DATA = "data";
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ // IList list = Mapper.Get ().QueryForList (ID, context);
+ // Fake it:
+ IList list = new ArrayList();
+ list.Add(DATA);
+ context.Outcome = list;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Commands/ObjectByKey.cs b/struts-sandbox/overdrive/Nexus/Test/Commands/ObjectByKey.cs
new file mode 100644
index 0000000..53c4cc7
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Commands/ObjectByKey.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Nexus.Core.Commands
+{
+ /// <summary>
+ /// Sample model command that adds a result object into the context
+ /// if the correct key is passed.
+ /// </summary>
+ public class ObjectByKey : RequestCommand
+ {
+ public const string PK_SOMETHING = "pk_something";
+ public const string PK_SOMETHING_VALUE = "12345678-1234-1234-1234-123456789ABC";
+ public const string PK_SOMETHING_RESULT = "SomethingResult";
+ public const string PK_SOME_DATE = "SomeDate";
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ string value = context[PK_SOMETHING] as string;
+ // IList list = Mapper.Get ().QueryForObject (ID, key);
+ if (PK_SOMETHING_VALUE.Equals(value))
+ {
+ context[PK_SOMETHING_RESULT] = PK_SOMETHING_RESULT;
+ context[PK_SOME_DATE] = DateTime.Now;
+ }
+ return CONTINUE;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/ControllerTest.cs b/struts-sandbox/overdrive/Nexus/Test/ControllerTest.cs
new file mode 100644
index 0000000..0e88017
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/ControllerTest.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using Nexus.Core.Commands;
+using NUnit.Framework;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Exercise IRequestCatalog per [OVR-8].
+ /// </summary>
+ ///
+ [TestFixture]
+ public class CatalogTest : CatalogBaseTest
+ {
+ /// <summary>
+ /// A simple "list all" command should return nominal with an outcome.
+ /// </summary>
+ ///
+ [Test]
+ public void ExecuteRequest()
+ {
+ IRequestContext context = catalog.ExecuteRequest(ListAll.LIST_ALL);
+ AssertNominal(context);
+ Assert.IsTrue(context.IsNominal, "Expected nominal result.");
+ Assert.IsTrue(context.HasOutcome, "Expected outcome from command.");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Helpers/ViewHelperTest.cs b/struts-sandbox/overdrive/Nexus/Test/Helpers/ViewHelperTest.cs
new file mode 100644
index 0000000..9b6a67c
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Helpers/ViewHelperTest.cs
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Agility.Core;
+using Nexus.Web;
+using NUnit.Framework;
+
+namespace Nexus.Core.Helpers
+{
+ /// <summary>
+ /// Exercise methods of standard IViewHelper implementation.
+ /// </summary>
+ [TestFixture]
+ public class ViewHelperTest
+ {
+ private IViewHelper helper;
+
+ /// <summary>
+ /// Create a command in between test runs.
+ /// </summary>
+ [SetUp]
+ public void SetUp ()
+ {
+ helper = new ViewHelper ();
+ }
+
+ /// <summary>
+ /// An error message will be returned surrounded by markup.
+ /// </summary>
+ [Test]
+ public void HtmlErrorBuilder ()
+ {
+ string ERROR = "Global error!";
+ helper.Context.AddError (ERROR);
+ string errors = ViewHelper.HtmlErrorBuilder (helper);
+ Assert.IsNotNull (errors, "Expected markup string.");
+ Assert.IsTrue (errors.Length > ERROR.Length);
+ Assert.IsTrue (errors.IndexOf (ERROR) > 0, "Expected error within markup.");
+ }
+
+
+ /// <summary>
+ /// A ViewHelper will have a non-null Context.
+ /// </summary>
+ [Test]
+ public void Context ()
+ {
+ Assert.IsNotNull (helper.Context, "Expected default Context instance.");
+ }
+
+ /// <summary>
+ /// Errors added to the underlying Context pass through to ViewHelper Errors.
+ /// </summary>
+ [Test]
+ public void Errors ()
+ {
+ Assert.IsNull (helper.Errors, "Expected no errors yet.");
+ IContext errors = new Context ();
+ errors.Add ("ERROR", "Error Message");
+ helper.Context.Errors = errors;
+ IContext _errors = helper.Errors;
+ Assert.IsNotNull (_errors, "Expected errors to pass through.");
+ Assert.IsTrue (_errors.Count == 1, "Expeced one error.");
+ Assert.AreEqual (errors [0], _errors [0]);
+ }
+
+ /// <summary>
+ /// Errors added to the underlying Context register with HasErrors.
+ /// </summary>
+ [Test]
+ public void HasErrors ()
+ {
+ Assert.IsFalse (helper.HasErrors, "Expected no errors.");
+ string ERROR = "I have an error!";
+ helper.Context.AddError (ERROR);
+ Assert.IsTrue (helper.HasErrors, "Expected to have errors.");
+ }
+
+ /// <summary>
+ /// An Exception added to the underlying Context passes through to the ViewHelper Fault.
+ /// </summary>
+ public void Fault ()
+ {
+ Assert.IsNull (helper.Fault, "Expected null fault.");
+ Exception fault = new Exception ();
+ helper.Context.Fault = fault;
+ Assert.IsNotNull (helper.Fault, "Expected non-null fault.");
+ }
+
+ /// <summary>
+ /// An Exception added to the underlying Context registers with ViewContext HasFault.
+ /// </summary>
+ [Test]
+ public void HasFault ()
+ {
+ Assert.IsFalse (helper.HasFault, "Expected no fault.");
+ helper.Context.Fault = new Exception ();
+ Assert.IsTrue (helper.HasFault, "Expected a fault");
+ }
+
+ /// <summary>
+ /// An Exception or error added to the underlying Context registers with IsNominal.
+ /// </summary>
+ [Test]
+ public void IsNominal ()
+ {
+ Assert.IsTrue (helper.IsNominal, "Expected nominal state.");
+ helper.Context.AddError ("Yet another error message.");
+ Assert.IsFalse (helper.IsNominal, "Expected error state");
+ helper.Context.Fault = new Exception ();
+ Assert.IsTrue (helper.HasFault, "Expected a fault");
+ Assert.IsFalse (helper.IsNominal, "Expected error state");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/ObjectByKeyTest.cs b/struts-sandbox/overdrive/Nexus/Test/ObjectByKeyTest.cs
new file mode 100644
index 0000000..0c1572a
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/ObjectByKeyTest.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using Nexus.Core.Commands;
+using NUnit.Framework;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Prove that a single object can be returned by Execute, without error.
+ /// </summary>
+ [TestFixture]
+ public class ObjectByKeyTest : CatalogBaseTest
+ {
+ public const string OBJECT_BY_KEY = "ObjectByKey";
+ public const string OBJECT_BY_KEY_WITH_VALIDATE = "ObjectByKeyWithValidate";
+ public const string OBJECT_BY_KEY_WITH_REQUIRED = "ObjectByKeyWithRequired";
+
+ private string PK_SOMETHING = ObjectByKey.PK_SOMETHING;
+ private string PK_SOMETHING_VALUE = ObjectByKey.PK_SOMETHING_VALUE;
+ private const string PK_SOMETHING_RESULT = ObjectByKey.PK_SOMETHING_RESULT;
+ private const string PK_SOME_DATE = ObjectByKey.PK_SOME_DATE;
+
+ public void AssertSomething(IRequestContext context)
+ {
+ AssertNominal(context);
+ Assert.IsNotNull(context[PK_SOMETHING_RESULT], "Expected result");
+ Assert.IsFalse(context.HasOutcome, "Unexpected Outcome.");
+ }
+
+ public void AssertInvalid(IRequestContext context)
+ {
+ AssertNoFault(context);
+ Assert.IsTrue(context.HasAlerts, "Expected error");
+ Assert.IsNull(context[PK_SOMETHING_RESULT], "Unexpected result");
+ Assert.IsFalse(context.HasOutcome, "Unexpected Outcome.");
+ }
+
+ [Test]
+ public void ObjectByKey_Trusted()
+ {
+ IRequestContext context = catalog.GetRequestContext(OBJECT_BY_KEY);
+ context[PK_SOMETHING] = PK_SOMETHING_VALUE;
+
+ catalog.ExecuteRequest(context); // do the actual work
+
+ AssertSomething(context);
+ }
+
+ [Test]
+ public void ObjectByKey_UnTrusted()
+ {
+ IDictionary fields = new Hashtable();
+ fields[PK_SOMETHING] = PK_SOMETHING_VALUE;
+ IRequestContext context = catalog.GetRequestContext(OBJECT_BY_KEY_WITH_REQUIRED, fields);
+
+ catalog.ExecuteRequest(context); // do the actual work
+
+ AssertSomething(context);
+ }
+
+ [Test]
+ public void ObjectByKey_UnTrusted_Fail()
+ {
+ IDictionary fields = new Hashtable();
+ IRequestContext context = catalog.GetRequestContext(OBJECT_BY_KEY_WITH_REQUIRED, fields);
+
+ catalog.ExecuteRequest(context); // do the actual work
+
+ AssertInvalid(context);
+ }
+
+
+ [Test]
+ public void ObjectByKey_Process()
+ {
+ IDictionary fields = new Hashtable();
+ fields[PK_SOMETHING] = PK_SOMETHING_VALUE;
+ // fields [PK_SOME_DATE] = DateTime.Now.ToShortDateString ();
+ IRequestContext context = catalog.GetRequestContext(OBJECT_BY_KEY_WITH_VALIDATE, fields);
+
+ catalog.ExecuteRequest(context); // do the actual work
+
+ AssertSomething(context);
+
+ try
+ {
+ DateTime output = (DateTime) context[PK_SOME_DATE];
+ output = output;
+ }
+ catch (Exception e)
+ {
+ Assert.IsTrue(e != null);
+ Assert.Fail("Expected date as binary in the main context");
+ }
+
+ string shortDate = context.Criteria[PK_SOME_DATE] as string;
+ Assert.IsNotNull(shortDate, "Expected date as a string in criteria");
+
+ DateTime now = DateTime.Now;
+ // http://www.microsoft.com/globaldev/getWR/steps/wrg_date.mspx
+ // Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
+ string expect = now.ToString("d");
+ Assert.AreEqual(expect, shortDate);
+ }
+
+ [Test]
+ public void ObjectByKey_Format_Date()
+ {
+ IDictionary fields = new Hashtable();
+ fields[PK_SOMETHING] = PK_SOMETHING_VALUE;
+ fields[PK_SOME_DATE] = DateTime.Now.ToShortDateString();
+ IRequestContext context = catalog.GetRequestContext(OBJECT_BY_KEY_WITH_VALIDATE, fields);
+
+ catalog.ExecuteRequest(context); // do the actual work
+
+ AssertSomething(context);
+
+ try
+ {
+ DateTime output = (DateTime) context[PK_SOME_DATE];
+ output = output;
+ }
+ catch (Exception e)
+ {
+ Assert.IsTrue(e != null);
+ Assert.Fail("Expected date as binary in the main context");
+ }
+
+ string formatted = context.Criteria[PK_SOME_DATE] as string;
+ Assert.IsNotNull(formatted, "Expected date as a string in criteria");
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Objects.xml b/struts-sandbox/overdrive/Nexus/Test/Objects.xml
new file mode 100644
index 0000000..4498d84
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Objects.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <object id="Base" />
+
+ <import resource="Resources/Command/AppConfig.xml"/>
+ <import resource="Resources/Command/Catalog.xml"/>
+
+</objects>
diff --git a/struts-sandbox/overdrive/Nexus/Test/RequestCommandTest.cs b/struts-sandbox/overdrive/Nexus/Test/RequestCommandTest.cs
new file mode 100644
index 0000000..e74c419
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/RequestCommandTest.cs
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using Nexus.Core.Commands;
+using NUnit.Framework;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Exercise methods of standard IRequestCommand implementation [OVR-9].
+ /// </summary>
+ ///
+ [TestFixture]
+ public class RequestCommandTest
+ {
+ private IRequestCommand command;
+
+ /// <summary>
+ /// Create a default command between test runs.
+ /// </summary>
+ ///
+ [SetUp]
+ public void SetUp()
+ {
+ command = new ListAll();
+ }
+
+ /// <summary>
+ /// A NewContext is not null.
+ /// </summary>
+ ///
+ [Test]
+ public void NewRequestContext()
+ {
+ IRequestContext context = command.NewContext();
+ Assert.IsNotNull(context, "Expected default context instance.");
+ }
+
+ /// <summary>
+ /// A successful command returns a nominal result.
+ /// </summary>
+ ///
+ public void RequestExecute()
+ {
+ IRequestContext context = command.NewContext();
+ command.Execute(context);
+ Assert.IsTrue(context.IsNominal, "Expected nominal result.");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/RequestContextTest.cs b/struts-sandbox/overdrive/Nexus/Test/RequestContextTest.cs
new file mode 100644
index 0000000..1e2a052
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/RequestContextTest.cs
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core.Commands;
+using NUnit.Framework;
+
+namespace Nexus.Core
+{
+ /// <summary>
+ /// Exercise IRequestContext per [OVR-7].
+ /// </summary>
+ ///
+ [TestFixture]
+ public class RequestContextTest
+ {
+ private IRequestContext context;
+ private Exception fault;
+ private IList list;
+
+ /// <summary>
+ /// Initialize private fields.
+ /// </summary>
+ ///
+ [SetUp]
+ public void SetUp()
+ {
+ context = new RequestContext();
+ context.Command = "list_all";
+ context.CommandBin = new ListAll();
+ Assert.IsTrue(context.IsNominal, "Expected nominal state for a new IRequestContext.");
+ Assert.IsFalse(context.HasOutcome, "Expected no Outcome for a new IRequestContext.");
+
+ fault = new ApplicationException("RequestContextTest");
+ list = new ArrayList();
+ list.Add("data");
+ }
+
+ /// <summary>
+ /// A IRequestContext is not nominal if an alert is added.
+ /// </summary>
+ ///
+ [Test]
+ public void IsNominal_Alert()
+ {
+ context.AddAlert("Business logic alert");
+ Assert.IsFalse(context.IsNominal, "Expected non-nominal state after adding alert message.");
+ }
+
+ /// <summary>
+ /// A IRequestContext is not nominal if an Exception is set.
+ /// </summary>
+ ///
+ [Test]
+ public void IsNominal_Fault()
+ {
+ context.Fault = fault;
+ Assert.IsFalse(context.IsNominal,
+ "Expected non-nominal state after setting Exception.");
+ }
+
+ /// <summary>
+ /// A IRequestContext is not nominal if multiple errors are added
+ /// and an Exception is set.
+ /// </summary>
+ ///
+ [Test]
+ public void IsNominal_Alerts_and_Fault()
+ {
+ context.AddAlert("Business logic error");
+ context.AddAlert("Business logic error 2");
+ context.Fault = fault;
+ Assert.IsFalse(context.IsNominal,
+ "Expected non-nominal state after adding errors and Exception.");
+ }
+
+ /// <summary>
+ /// If data is set to the Outcome property, HasOutcome is true.
+ /// </summary>
+ ///
+ [Test]
+ public void HasOutcome()
+ {
+ context.Outcome = list;
+ Assert.IsTrue(context.HasOutcome);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppBase.xml b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppBase.xml
new file mode 100644
index 0000000..ce4c1c2
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppBase.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Base Elements (parents)-->
+
+ <object id="BaseLogic" >
+ </object>
+
+ <object id="BaseMapper" >
+ <property name="Mapper"><ref object="Mapper"/></property>
+ </object>
+
+ <object id="BaseController" >
+ <property name="Controller"><ref object="Controller" /></property>
+ </object>
+
+ <object id="BaseChain" />
+
+ <!-- ISSUE: We should have a parent for each of the standard base commands. -->
+
+ <object id="BaseHelper" singleton="false" scope="request" >
+ <property name="Controller">
+ <ref object="Controller" />
+ </property>
+</object>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppConfig.xml b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppConfig.xml
new file mode 100644
index 0000000..5fbd3e0
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppConfig.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+<!-- Catalog -->
+
+ <object id="Catalog" type="Nexus.Extras.Spring.Catalog">
+ <property name="FieldTable"><ref object="FieldTable"/></property>
+ <property name="PreOp"><ref object="PreOp"/></property>
+ <property name="PostOp"><ref object="PostOp"/></property>
+ </object>
+
+<!-- View Helper-->
+
+ <object id="ViewHelper" type="Nexus.Core.Helpers.ViewHelper" singleton="false">
+ <property name="ID"><value>ViewHelper</value></property>
+ </object>
+
+<!-- Request Processors -->
+
+ <object id="ConvertInput" type="Nexus.Core.Validators.ConvertInput">
+ <property name="ID"><value>ConvertInput</value></property>
+ </object>
+
+ <object id="FormatOutput" type="Nexus.Core.Validators.FormatOutput">
+ <property name="ID"><value>FormatOutput</value></property>
+ </object>
+
+ <object id="PreOp" type="Nexus.Core.RequestChain">
+ <property name="ID"><value>pre-op</value></property>
+ <property name="AddCommands">
+ <list>
+ <ref object="ConvertInput"/>
+ </list>
+ </property>
+ </object>
+
+ <object id="PostOp" type="Nexus.Core.RequestChain">
+ <property name="ID"><value>post-op</value></property>
+ <property name="AddCommands">
+ <list>
+ <ref object="FormatOutput"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- FieldTable -->
+
+ <object id="FieldTable" type="Nexus.Core.Tables.FieldTable">
+ <property name="Strict"><value>true</value></property>
+ <property name="AddProcessors">
+ <list>
+ <ref object="CollectionProcessor"/>
+ <ref object="DateTimeProcessor"/>
+ <ref object="StringProcessor"/>
+ </list>
+ </property>
+ <property name="AddFieldContexts">
+ <list>
+ <ref object="pk_something"/>
+ <ref object="SomeDate"/>
+ <ref object="SomethingResult"/>
+ </list>
+ </property>
+ </object>
+
+<!-- Field Processors -->
+
+ <object id="CollectionProcessor" type="Nexus.Core.Validators.CollectionProcessor">
+ <property name="ID"><value>CollectionProcessor</value></property>
+ </object>
+
+ <object id="DateTimeProcessor" type="Nexus.Core.Validators.DateTimeProcessor">
+ <property name="ID"><value>DateTimeProcessor</value></property>
+ <property name="Alert"><value>{0} must be a valid date</value></property>
+ <property name="DataFormat"><value>d</value></property>
+ </object>
+
+ <object id="StringProcessor" type="Nexus.Core.Validators.StringProcessor">
+ <property name="ID"><value>StringProcessor</value></property>
+ </object>
+
+<!-- Fields -->
+
+ <object id="BaseFieldContext" type="Nexus.Core.Tables.FieldContext">
+ <property name="Alert"><value>{0} is invalid.</value></property>
+ <property name="Required"><value>{0} is required.</value></property>
+ </object>
+
+ <object id="pk_something" parent="BaseFieldContext">
+ <property name="ID"><value>pk_something</value></property>
+ <property name="Label"><value>Something Key</value></property>
+ <property name="Processor"><ref object="StringProcessor"/></property>
+ </object>
+
+ <object id="SomethingResult" parent="BaseFieldContext">
+ <property name="ID"><value>SomethingResult</value></property>
+ <property name="Label"><value>Something Result</value></property>
+ <property name="Processor"><ref object="StringProcessor"/></property>
+ </object>
+
+ <object id="SomeDate" parent="BaseFieldContext">
+ <property name="ID"><value>SomeDate</value></property>
+ <property name="Label"><value>Some Date</value></property>
+ <property name="Processor"><ref object="DateTimeProcessor"/></property>
+ </object>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppFields.xml b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppFields.xml
new file mode 100644
index 0000000..4cde715
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/AppFields.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- FIELD TABLE -->
+
+ <object id="FieldTable" type="Agility.Nexus.FieldTable">
+ <property name="AddFields">
+ <list>
+ </list>
+ </property>
+ </object>
+
+<!-- FIELDS -->
+
+ <!-- parent fields -->
+
+ <!-- "d" is .NET for "short date" -->
+ <object id="date" type="Agility.Nexus.FieldContext">
+ <property name="Alert"><value>{0} must be a valid date</value></property>
+ <property name="DataFormat"><value>d</value></property>
+ <property name="DataTypeName"><value>System.DateTime</value></property>
+ </object>
+
+ <object id="list" type="Agility.Nexus.FieldContext">
+ <property name="ControlTypeName"><value>select</value></property>
+ </object>
+
+
+ <object id="" type="Agility.Nexus.FieldContext">
+ <property name="ID"><value></value></property>
+ </object>
+
+ <!-- instance fields (dates and lists) -->
+
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Test/Resources/Command/Catalog.xml b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/Catalog.xml
new file mode 100644
index 0000000..ead34bd
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Resources/Command/Catalog.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
+ "http://www.springframework.net/dtd/spring-objects.dtd">
+<objects>
+
+ <object id="ListAll" type="Nexus.Core.Commands.ListAll, Nexus.Test">
+ <property name="ID"><value>ListAll</value></property>
+ </object>
+
+ <object id="ObjectByKey" type="Nexus.Core.Commands.ObjectByKey, Nexus.Test">
+ <property name="ID"><value>ObjectByKey</value></property>
+ <property name="AddRequiredIDs">
+ <list>
+ <value>pk_something</value>
+ </list>
+ </property>
+ <property name="AddRelatedIDs">
+ <list>
+ <value>SomeDate</value>
+ <value>SomethingResult</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="ObjectByKeyWithRequired" type="Nexus.Core.RequestChain">
+ <property name="ID"><value>ObjectByKeyWithRequired</value></property>
+ <property name="AddCommands">
+ <list>
+ <ref object="ConvertInput"/>
+ <ref object="ObjectByKey"/>
+ </list>
+ </property>
+ </object>
+
+ <object id="ObjectByKeyWithValidate" type="Nexus.Core.RequestChain">
+ <property name="ID"><value>ObjectByKeyWithValidate</value></property>
+ <property name="AddCommands">
+ <list>
+ <ref object="ConvertInput"/>
+ <ref object="ObjectByKey"/>
+ <ref object="FormatOutput"/>
+ </list>
+ </property>
+ </object>
+
+
+</objects>
diff --git a/struts-sandbox/overdrive/Nexus/Test/Test.csproj b/struts-sandbox/overdrive/Nexus/Test/Test.csproj
new file mode 100644
index 0000000..3598ab7
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/Test.csproj
@@ -0,0 +1,179 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{C533FFAA-CB2B-40CD-B3C2-77394E4D9222}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "Nexus.Test"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Flow"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = "$(SolutionDir)postbuild.bat $(TargetDir) $(TargetName) $(SolutionName) $(SolutionDir)"
+ RootNamespace = "Nexus.Core"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = "Nexus.Test.xml"
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = "1591"
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "nunit.framework"
+ AssemblyName = "nunit.framework"
+ HintPath = "..\..\..\..\..\..\..\Program Files\NUnit 2.2\bin\nunit.framework.dll"
+ AssemblyFolderKey = "hklm\dn\nunit.framework"
+ />
+ <Reference
+ Name = "Core"
+ Project = "{7C8CAFD4-1E45-41B4-9963-F51199B12EA7}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ <Reference
+ Name = "Extras"
+ Project = "{7931CACD-0E73-4DD2-A373-FF6A01CE6186}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ <Reference
+ Name = "Web"
+ Project = "{2BD7CDE0-01F7-4CC5-9AE9-2F9470FB7007}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ <Reference
+ Name = "Spring.Core"
+ AssemblyName = "Spring.Core"
+ HintPath = "..\..\..\local-cache\SpringNet\Spring.Core.dll"
+ />
+ <Reference
+ Name = "Agility.Core"
+ AssemblyName = "Agility.Core"
+ HintPath = "..\..\..\local-cache\Agility\Agility.Core.dll"
+ />
+ <Reference
+ Name = "Spring.Web"
+ AssemblyName = "Spring.Web"
+ HintPath = "..\..\local-cache\SpringNet\Spring.Web.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "BaseNexusTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "ControllerTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "ObjectByKeyTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Objects.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "RequestCommandTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "RequestContextTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <Folder RelPath = "bin\Debug\" />
+ <File
+ RelPath = "Commands\ListAll.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\ObjectByKey.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Resources\Command\AppConfig.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\Command\Catalog.xml"
+ BuildAction = "Content"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/Nexus/Test/bin/Debug/PostBuildEvent.bat b/struts-sandbox/overdrive/Nexus/Test/bin/Debug/PostBuildEvent.bat
new file mode 100644
index 0000000..31528a4
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Test/bin/Debug/PostBuildEvent.bat
@@ -0,0 +1,8 @@
+@echo off
+C:\projects\Nexus\struts-overdrive\sandbox\overdrive\Nexus\postbuild.bat C:\projects\Nexus\struts-overdrive\sandbox\overdrive\Nexus\Test\bin\Debug\ Nexus.Test Nexus C:\projects\Nexus\struts-overdrive\sandbox\overdrive\Nexus\
+if errorlevel 1 goto CSharpReportError
+goto CSharpEnd
+:CSharpReportError
+echo Project error: A tool returned an error code from the build event
+exit 1
+:CSharpEnd
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/AlertLabel.cs b/struts-sandbox/overdrive/Nexus/Web/AlertLabel.cs
new file mode 100644
index 0000000..a489a1b
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/AlertLabel.cs
@@ -0,0 +1,28 @@
+namespace Nexus.Web
+{
+ /// <summary>
+ /// Extend MessageLabel to respond only to the View_Alert event
+ /// and use an alternate suffix.
+ /// </summary>
+ public class AlertLabel : ViewLabel
+ {
+ /// <summary>
+ /// Default suffix for NameLabel IDs ["_alert"].
+ /// </summary>
+ ///
+ public const string ALERT_SUFFIX = "_alert";
+
+ /// <summary>
+ /// Set the defaults for this subclass.
+ /// </summary>
+ ///
+ public AlertLabel() : base()
+ {
+ Suffix = ALERT_SUFFIX;
+ View_Hint = false;
+ base.EnableViewState = false;
+ // http://blogs.msdn.com/scottwil/archive/2005/01/14/353177.aspx
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/AssemblyInfo.cs b/struts-sandbox/overdrive/Nexus/Web/AssemblyInfo.cs
new file mode 100644
index 0000000..fad95dc
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/AssemblyInfo.cs
@@ -0,0 +1,60 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the "project output directory". The location of the project output
+// directory is dependent on whether you are working with a local or web project.
+// For local projects, the project output directory is defined as
+// <Project Directory>\obj\<Configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// For web projects, the project output directory is defined as
+// %HOMEPATH%\VSWebCache\<Machine Name>\<Project Directory>\obj\<Configuration>.
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx b/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx
new file mode 100644
index 0000000..dff05da
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx
@@ -0,0 +1,10 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="LetterFilter.ascx.cs" Inherits="Nexus.Web.Controls.LetterFilter" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
+<asp:repeater id="letters" runat="server">
+ <itemtemplate>
+ <asp:linkbutton id="letter" runat="server"
+ commandname="filter"
+ commandargument='<%# DataBinder.Eval(Container, "DataItem.Letter")%>' >
+ <%# DataBinder.Eval(Container, "DataItem.Letter")%>
+ </asp:linkbutton>
+ </itemtemplate>
+</asp:repeater>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx.cs b/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx.cs
new file mode 100644
index 0000000..793b169
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx.cs
@@ -0,0 +1,286 @@
+using System;
+using System.Collections;
+using System.Data;
+using System.Web.UI.WebControls;
+using WQD.Core.Controls;
+
+namespace Nexus.Web.Controls
+{
+ /// <summary>
+ /// Display a list of letters, one of which can be selected at a time,
+ /// so a client control can filter a list of entries.
+ /// </summary>
+ /// <remarks><p>
+ /// Adapted from http://www.codeproject.com/aspnet/LetterBasedPaging.asp
+ /// </p></remarks>
+ ///
+ public class LetterFilter : FindControl
+ {
+ /// <summary>
+ /// Document token representing match all entries.
+ /// </summary>
+ public const string ALL = "[*]";
+
+ /// <summary>
+ /// Document the attribute name for the initial letter by which to filter.
+ /// </summary>
+ public const string ITEM_INITIAL = "initial";
+ /// <summary>
+ /// Provide a key under which to store the selected letter in ViewState.
+ /// </summary>
+ ///
+ public const string LETTER_KEY = "_Letter";
+
+ /// <summary>
+ /// Document the wildcard character used by SQL queries.
+ /// </summary>
+ public const string WILDCARD = "%";
+
+ /// <summary>
+ /// Signal that input is ready to submit,
+ /// passing the ITEM_INTIIAL value as FindArgs.
+ /// </summary>
+ ///
+ public event EventHandler View_Filter;
+
+ /// <summary>
+ /// List the letters that can selected.
+ /// </summary>
+ ///
+ protected Repeater letters;
+
+ /// <summary>
+ /// Provide a private field to cache the LetterFilter property.
+ /// </summary>
+ ///
+ private string _Letter;
+
+ /// <summary>
+ /// Store the current letter by which client is to filter.
+ /// </summary>
+ /// <remarks><p>
+ /// The value is stored by ID in ViewState
+ /// so that more than one LetterFilter can be used by the same parent control.
+ /// </p></remarks>
+ ///
+ public string Letter
+ {
+ get
+ {
+ if (_Letter == null) _Letter = ViewState[ID + LETTER_KEY] as string;
+ return _Letter;
+ }
+ set
+ {
+ _Letter = value;
+ ViewState[ID + LETTER_KEY] = value;
+ // Bind the datasource so that Letter change is reflected
+ letters.DataBind();
+ }
+ }
+
+ /// <summary>
+ /// Provide a key under which to store the DataTable in ViewState.
+ /// </summary>
+ ///
+ private string LETTER_TABLE_KEY = "_LetterData";
+
+ /// <summary>
+ /// Provide a private field to cache the LetterTable property.
+ /// </summary>
+ ///
+ private DataTable _LetterTable;
+
+ /// <summary>
+ /// Store the DataTable containing our letters.
+ /// </summary>
+ ///
+ public DataTable LetterTable
+ {
+ get
+ {
+ if (_LetterTable == null) _LetterTable = ViewState[ID + LETTER_TABLE_KEY] as DataTable;
+ return _LetterTable;
+ }
+ set
+ {
+ _LetterTable = value;
+ ViewState[ID + LETTER_TABLE_KEY] = value;
+ }
+
+ }
+
+ /// <summary>
+ /// Provide the name of the item command to fire when the linkbutton for a letter is clicked.
+ /// </summary>
+ ///
+ protected const string FILTER_CMD = "filter";
+
+ /// <summary>
+ /// Identify the linkbutton that will contain the letter in each repeater cell.
+ /// </summary>
+ ///
+ protected const string LETTER_ID = "letter";
+
+ /// <summary>
+ /// Identify the column in our DataTable that holds the letters.
+ /// </summary>
+ ///
+ protected const string LETTER_COLUMN = "Letter";
+
+ /// <summary>
+ /// Handle the "Filter" by new letter command,
+ /// passing NULL if "ALL" is selected.
+ /// </summary>
+ ///
+ protected void letters_ItemCommand(object source, RepeaterCommandEventArgs e)
+ {
+ // Handle the "Filter" new record command
+ if (e.CommandName == FILTER_CMD)
+ {
+ // Set the new Letter selection
+ Letter = (string) e.CommandArgument;
+
+ // Raise the "Filter" event so that client can update its list.
+ if (View_Filter != null)
+ {
+ string letter = Letter;
+ if (ALL.Equals(letter)) letter = null;
+ string letter2 = letter + WILDCARD;
+ IDictionary criteria = new Hashtable(1);
+ criteria.Add(ITEM_INITIAL, letter2);
+ FindArgs a = new FindArgs(e, criteria);
+ View_Filter(source, a);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Called when an item in the letters repeater control is data bound to a source.
+ /// </summary>
+ protected void letters_ItemDataBound(object source, RepeaterItemEventArgs e)
+ {
+ // Retrieve the row of data that is to be bound to the repeater
+ DataRowView data = (DataRowView) e.Item.DataItem;
+
+ // If the letter we are binding to the current repeater control item is
+ // the same as the one currently selected, than disable it so the user
+ // knows which one was selected.
+ if ((string) data[0] == Letter)
+ {
+ LinkButton cmd = (LinkButton) e.Item.FindControl(LETTER_ID);
+ cmd.Enabled = false;
+ }
+ }
+
+
+ /// <summary>
+ /// Create a new DataTable from the list of letters provided,
+ /// and store a referance to the newly create data table for use on post back.
+ /// </summary>
+ /// <param name="input">List of letters to present as commands</param>
+ private void LetterTable_Init(IList input)
+ {
+ DataTable dt = new DataTable();
+ dt.Columns.Add(new DataColumn(LETTER_COLUMN, typeof (string)));
+
+ for (int i = 0; i < input.Count; i++)
+ {
+ DataRow dr = dt.NewRow();
+ dr[0] = input[i];
+ dt.Rows.Add(dr);
+ }
+
+ LetterTable = dt;
+ Letter = null;
+ }
+
+ /// <summary>
+ /// Bind the letters array to the repeater control,
+ /// set the default letter,
+ /// so that the letters are ready to present.
+ /// </summary>
+ ///
+ public override bool Open()
+ {
+ if (LetterTable == null)
+ {
+ // Default to A-Z
+ string[] input = {
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y", "Z", ALL
+ };
+
+ LetterTable_Init(input);
+ }
+
+ letters.DataSource = LetterTable.DefaultView;
+ string current = Letter;
+ if (current == null) Letter = ALL;
+ return true;
+ }
+
+ /// <summary>
+ /// Bind the letters array to the repeater control,
+ /// set the default letter,
+ /// so that the letters are ready to present.
+ /// </summary>
+ ///
+ public bool Open(IList letters)
+ {
+ LetterTable_Init(letters);
+ return Open();
+ }
+
+
+ /// <summary>
+ /// Pass our DataGrid instance to base member.
+ /// </summary>
+ ///
+ private void Page_Init()
+ {
+ letters.ItemCommand += new RepeaterCommandEventHandler(this.letters_ItemCommand);
+ letters.ItemDataBound += new RepeaterItemEventHandler(this.letters_ItemDataBound);
+ }
+
+ /// <summary>
+ /// Handle the page Load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ Open();
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Generated method for Designer support.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ Page_Init();
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx.resx b/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Controls/LetterFilter.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx b/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx
new file mode 100644
index 0000000..d5dab51
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx
@@ -0,0 +1 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="FindControl.ascx.cs" Inherits="Nexus.Web.FindControl" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
diff --git a/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx.cs b/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx.cs
new file mode 100644
index 0000000..0758263
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections;
+using Nexus.Core.Helpers;
+using WQD.Core.Controls;
+
+namespace Nexus.Web
+{
+ /// <summary>
+ /// Base class for find controls.
+ /// </summary>
+ /// <remarks><p>
+ /// Typically, a FindControl will collect input
+ /// to filter a list of entries displayed by a GridControl.
+ /// </p></remarks>
+ public class FindControl : ViewControl
+ {
+ /// <summary>
+ /// Provide a field for the FindCommand property.
+ /// </summary>
+ private string _FindCommand;
+
+ /// <summary>
+ /// Provide the command that will populate the data-entry controls.
+ /// </summary>
+ public string FindCommand
+ {
+ get { return _FindCommand; }
+ set { _FindCommand = value; }
+ }
+
+ /// <summary>
+ /// Expose values input by client
+ /// for use by another component.
+ /// </summary>
+ ///
+ public virtual IDictionary Criteria
+ {
+ get
+ {
+ IViewHelper helper = Read(FindCommand);
+ if (!helper.IsNominal)
+ {
+ Page_Alert = helper;
+ }
+ return helper.Criteria;
+ }
+ }
+
+ /// <summary>
+ /// Signal that input is ready to submit.
+ /// </summary>
+ ///
+ public event EventHandler View_Find;
+
+ /// <summary>
+ /// Fire Click event when input is ready to submit.
+ /// </summary>
+ /// <param name="sender">Source of event [find Button]</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected void find_Click(object sender, EventArgs e)
+ {
+ if (View_Find != null)
+ {
+ FindArgs a = new FindArgs(e, Criteria);
+ View_Find(sender, a);
+ }
+ }
+
+ /// <summary>
+ /// Prepare controls for data entry.
+ /// </summary>
+ /// <remarks><p>
+ /// Preparation includes obtaining lists from the
+ /// databases.
+ /// Any errors are reported
+ /// through the standard page error handler.
+ /// </p></remarks>
+ ///
+ public virtual bool Open()
+ {
+ IViewHelper helper = ExecuteBind(FindCommand);
+ Bind(Profile.Criteria);
+ bool okay = helper.IsNominal;
+ if (!okay) Page_Alert = helper;
+ return okay;
+ }
+
+ public virtual bool Open(IDictionary criteria)
+ {
+ IViewHelper helper = GetHelperFor(FindCommand);
+ helper.Read(criteria, true);
+ ExecuteBind(helper);
+ bool okay = helper.IsNominal;
+ if (!okay) Page_Alert = helper;
+ return okay;
+ }
+
+ /// <summary>
+ /// Handle the page Load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ // Put user code to initialize the page here
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ ///
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx.resx b/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/FindControl.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/Nexus/Web/Global.asax b/struts-sandbox/overdrive/Nexus/Web/Global.asax
new file mode 100644
index 0000000..89b6e2d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="Nexus.Global" %>
diff --git a/struts-sandbox/overdrive/Nexus/Web/Global.asax.cs b/struts-sandbox/overdrive/Nexus/Web/Global.asax.cs
new file mode 100644
index 0000000..3f60ed9
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Global.asax.cs
@@ -0,0 +1,67 @@
+using System;
+using System.ComponentModel;
+using System.Web;
+
+namespace Nexus
+{
+ /// <summary>
+ /// Summary description for Global.
+ /// </summary>
+ public class Global : HttpApplication
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private IContainer components = null;
+
+ public Global()
+ {
+ InitializeComponent();
+ }
+
+ protected void Application_Start(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Session_Start(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_BeginRequest(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_EndRequest(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_AuthenticateRequest(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_Error(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Session_End(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_End(Object sender, EventArgs e)
+ {
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.components = new Container();
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/Global.asax.resx b/struts-sandbox/overdrive/Nexus/Web/Global.asax.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Global.asax.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx b/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx
new file mode 100644
index 0000000..8fc6c80
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx
@@ -0,0 +1 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="GridControl.ascx.cs" Inherits="Nexus.Web.GridControl" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
diff --git a/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx.cs b/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx.cs
new file mode 100644
index 0000000..31d2f7c
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx.cs
@@ -0,0 +1,1804 @@
+using System;
+using System.Collections;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using WQD.Core.Controls;
+
+namespace Nexus.Web
+{
+ /// <summary>
+ /// List, edit, and select items using a DataGrid and IViewHelper commands.
+ /// </summary>
+ public class GridControl : ViewControl
+ {
+ #region Runtime state Properties
+
+ /// <summary>
+ /// Provide an attribute token for List_Criteria.
+ /// </summary>
+ private string LIST_CRITERIA_KEY = "list_Criteria";
+
+ /// <summary>
+ /// Set the given criteria to the list_Critieria (creating a new one if null), and,
+ /// if AllowCustomPage is set,
+ /// calculate new Limit and Offset, based on pageIndex, and set to criteria.
+ /// </summary>
+ /// <remarks><p>
+ /// This form is provided to be called by list_Criteria_Init.
+ /// The other form is provided to be called by other methods.
+ /// </p></remarks>
+ /// <param name="criteria">The criteria instance to store the attributes</param>
+ /// <param name="pageIndex">The new page index</param>
+ protected IDictionary list_Criteria_NewPageIndex(IDictionary criteria, int pageIndex)
+ {
+ if (Grid.AllowCustomPaging)
+ {
+ if (criteria == null) criteria = new Hashtable(); // FIXME: Spring?
+ int page = pageIndex;
+ int limit = Grid.PageSize;
+ int offset = page*limit;
+ criteria[ITEM_LIMIT] = limit;
+ criteria[ITEM_OFFSET] = offset;
+ }
+ list_Criteria = criteria;
+ return criteria;
+ }
+
+ protected IDictionary list_Criteria_NewPageIndex(IDictionary criteria, int pageIndex, bool allowCustomPaging)
+ {
+ Grid.AllowCustomPaging = allowCustomPaging;
+ return list_Criteria_NewPageIndex(criteria, pageIndex);
+ }
+
+ protected IDictionary list_Criteria_NewPageIndex(int pageIndex)
+ {
+ IDictionary criteria = list_Criteria;
+ return list_Criteria_NewPageIndex(criteria, pageIndex);
+ }
+
+ /// <summary>
+ /// Provide values to use with a query statement, persisted across requests.
+ /// </summary>
+ protected IDictionary list_Criteria
+ {
+ get
+ {
+ IDictionary criteria = ViewState[LIST_CRITERIA_KEY] as IDictionary;
+ return criteria;
+ }
+ set { ViewState[LIST_CRITERIA_KEY] = value; }
+ }
+
+ /// <summary>
+ /// Merge values into list_Criteria.
+ /// </summary>
+ /// <param name="criteria">Values to append</param>
+ public void Read(IDictionary criteria)
+ {
+ ICollection keys = criteria.Keys;
+ foreach (string key in keys)
+ {
+ list_Criteria[key] = criteria[key];
+ }
+ }
+
+ /// <summary>
+ /// Provide attribute token for List_ItemIndex.
+ /// </summary>
+ private const string LIST_ITEM_INDEX = "list_ItemIndex";
+
+ /// <summary>
+ /// Current item index, used mainly to signal editing.
+ /// </summary>
+ public virtual int list_ItemIndex
+ {
+ get
+ {
+ object value = ViewState[LIST_ITEM_INDEX];
+ if (value == null) return -1;
+ return (int) value;
+ }
+ set
+ {
+ ViewState[LIST_ITEM_INDEX] = value;
+ if (Grid != null) Grid.EditItemIndex = value;
+ }
+ }
+
+ /// <summary>
+ /// Provide attribute token for List_ItemKey.
+ /// </summary>
+ private const string LIST_ITEM_KEY = "list_ItemKey";
+
+ /// <summary>
+ /// Provide data key for the selected item.
+ /// </summary>
+ public virtual string list_ItemKey
+ {
+ get { return ViewState[LIST_ITEM_KEY] as string; }
+ set { ViewState[LIST_ITEM_KEY] = value; }
+ }
+
+ /// <summary>
+ /// Provide attribute token for List_Insert.
+ /// </summary>
+ private const string LIST_INSERT_KEY = "list_Insert";
+
+ /// <summary>
+ /// Determine insert mode - are we adding or modifying?
+ /// </summary>
+ public virtual bool list_Insert
+ {
+ get
+ {
+ object value = ViewState[LIST_INSERT_KEY];
+ if (value == null) return false;
+ return (bool) value;
+ }
+ set { ViewState[LIST_INSERT_KEY] = value; }
+ }
+
+ /// <summary>
+ /// Store whether command uses critiera.
+ /// </summary>
+ private bool _HasCriteria = true;
+
+ /// <summary>
+ /// Track whether a criteria is used.
+ /// </summary>
+ public virtual bool HasCriteria
+ {
+ get { return _HasCriteria; }
+ set { _HasCriteria = value; }
+ }
+
+ #endregion
+
+ #region Command properties to set
+
+ /// <summary>
+ /// Store the Find Command.
+ /// </summary>
+ private string _FindCommand;
+
+ /// <summary>
+ /// Provide the Find Command to prepare a new search.
+ /// </summary>
+ public virtual string FindCommand
+ {
+ get { return _FindCommand; }
+ set { _FindCommand = value; }
+ }
+
+ /// <summary>
+ /// Store the List Command.
+ /// </summary>
+ private string _ListCommand;
+
+ /// <summary>
+ /// Provide the List Command to filter items and populate the DataGrid.
+ /// </summary>
+ public virtual string ListCommand
+ {
+ get { return _ListCommand; }
+ set { _ListCommand = value; }
+ }
+
+ /// <summary>
+ /// Store the Save Command.
+ /// </summary>
+ private string _SaveCommand;
+
+ /// <summary>
+ /// Provide the Save Command to retain changes to an item.
+ /// </summary>
+ public virtual string SaveCommand
+ {
+ get { return _SaveCommand; }
+ set { _SaveCommand = value; }
+ }
+
+ #endregion
+
+ #region Column properties to set
+
+ /// <summary>
+ /// Store the key field.
+ /// </summary>
+ private string _DataKeyField;
+
+ /// <summary>
+ /// Provide the key field for the DataGrid.
+ /// </summary>
+ public virtual string DataKeyField
+ {
+ get { return _DataKeyField; }
+ set { _DataKeyField = value; }
+ }
+
+ /// <summary>
+ /// Store the list of GridConfig items.
+ /// </summary>
+ private IList _Configs;
+
+ /// <summary>
+ /// Provide a list of the GridConfig items.
+ /// </summary>
+ /// <remarks><p>
+ /// GridConfig is a local class that describes
+ /// the fields needed to program a DataGrid column.
+ /// </p></remarks>
+ public virtual IList Configs
+ {
+ get { return _Configs; }
+ set { _Configs = value; }
+ }
+
+ #endregion
+
+ #region Column properties with defaults
+
+ /// <summary>
+ /// Provide default text for the EDIT control.
+ /// </summary>
+ public const string msg_EDIT_TEXT = "EDIT";
+
+ /// <summary>
+ /// Provide default text for the CANCEL control.
+ /// </summary>
+ public const string msg_QUIT_TEXT = "CANCEL";
+
+ /// <summary>
+ /// Provide default text for the SAVE control.
+ /// </summary>
+ public const string msg_SAVE_TEXT = "SAVE";
+
+ /// <summary>
+ /// Provide default text for the ITEM control.
+ /// </summary>
+ public const string msg_ITEM_TEXT = "#";
+
+ /// <summary>
+ /// Store the text for the EDIT control.
+ /// </summary>
+ private string _EditText = msg_EDIT_TEXT;
+
+ /// <summary>
+ /// Provide the text for the EDIT control.
+ /// </summary>
+ public virtual string EditText
+ {
+ get { return _EditText; }
+ set { _EditText = value; }
+ }
+
+ /// <summary>
+ /// Store the text for the QUIT control.
+ /// </summary>
+ private string _QuitText = msg_QUIT_TEXT;
+
+ /// <summary>
+ /// Provide the text for the QUIT control.
+ /// </summary>
+ public virtual string QuitText
+ {
+ get { return _QuitText; }
+ set { _QuitText = value; }
+ }
+
+ /// <summary>
+ /// Store the text for the SAVE control.
+ /// </summary>
+ private string _SaveText = msg_SAVE_TEXT;
+
+ /// <summary>
+ /// Provide the text for the SAVE control.
+ /// </summary>
+ public virtual string SaveText
+ {
+ get { return _SaveText; }
+ set { _SaveText = value; }
+ }
+
+ /// <summary>
+ /// Store the text for the ITEM control.
+ /// </summary>
+ private string _ItemText = msg_ITEM_TEXT;
+
+ /// <summary>
+ /// Provide the text for the ITEM control.
+ /// </summary>
+ public virtual string ItemText
+ {
+ get { return _ItemText; }
+ set { _ItemText = value; }
+ }
+
+ /// <summary>
+ /// Provide default token to signal an item select command.
+ /// </summary>
+ public const string msg_ITEM_COMMAND = "Item";
+
+ /// <summary>
+ /// Store the token to signal an item select command.
+ /// </summary>
+ private string _ItemCommand = msg_ITEM_COMMAND;
+
+ /// <summary>
+ /// Provide the token to signal an item select command.
+ /// </summary>
+ public virtual string ItemCommandName
+ {
+ get { return _ItemCommand; }
+ set { _ItemCommand = value; }
+ }
+
+ /// <summary>
+ /// Store whether an item column is presented [false].
+ /// </summary>
+ private bool _HasItemColumn = false;
+
+ /// <summary>
+ /// Provide whether an item column is presented [false].
+ /// </summary>
+ public virtual bool HasItemColumn
+ {
+ get { return _HasItemColumn; }
+ set { _HasItemColumn = value; }
+ }
+
+ /// <summary>
+ /// Store whether an edit column is presented [false].
+ /// </summary>
+ private bool _HasEditColumn = false;
+
+ /// <summary>
+ /// Provide whether an edit column is presented [false].
+ /// </summary>
+ public virtual bool HasEditColumn
+ {
+ get { return _HasEditColumn; }
+ set { _HasEditColumn = value; }
+ }
+
+ /// <summary>
+ /// Store whether dataset is being accessed page by page.
+ /// </summary>
+ private bool _AllowCustomPaging = true;
+
+ /// <summary>
+ /// Provide whether dataset is being accessed page by page.
+ /// </summary>
+ /// <remarks><p>
+ /// Custom paging refers to whether the entire dataset is retrieved all at once
+ /// or whether the items to fill the current page are retrieved.
+ /// A DataGrid may be configured to display pages with AllowCusteomPaging set to false,
+ /// but the underlying query should retrieve the entire dataset up front.
+ /// Whether page numbers are used is set in the DataGrid markup, not here.
+ /// </p></remarks>
+ public virtual bool AllowCustomPaging
+ {
+ get { return _AllowCustomPaging; }
+ set { _AllowCustomPaging = value; }
+ }
+
+ /// <summary>
+ /// Store the ASP.NET default for a DataGrid page size.
+ /// </summary>
+ const int DEFAULT_DATAGRID_PAGESIZE = 10;
+
+ /// <summary>
+ /// Store the DataGrid default page size.
+ /// </summary>
+ private int _PageSize = DEFAULT_DATAGRID_PAGESIZE;
+
+ /// <summary>
+ /// Provide the DataGrid default page size.
+ /// </summary>
+ public virtual int PageSize
+ {
+ get { return _PageSize; }
+ set { _PageSize = value; }
+ }
+
+ #endregion
+
+ #region Binding methods
+
+ /// <summary>
+ /// Set the Helper's outcome to the DataGrid datasource,
+ /// and update the virtual item count if AllowCustomPaging.
+ /// </summary>
+ /// <param name="helper"></param>
+ protected virtual void DataSource(IViewHelper helper)
+ {
+ IList list = helper.Outcome;
+ DataGrid grid = Grid;
+ grid.DataSource = list;
+ if (grid.AllowCustomPaging)
+ {
+ grid.VirtualItemCount = GetItemCount(helper);
+ }
+ }
+
+ /// <summary>
+ /// Bind the current datasource to the base control and the DataGrid control.
+ /// </summary>
+ public override void DataBind()
+ {
+ base.DataBind();
+ Grid.DataBind();
+ }
+
+ /// <summary>
+ /// Configure a control column to select a DataGrid item (or row).
+ /// </summary>
+ /// <param name="pos">The column position</param>
+ /// <returns>The next column position</returns>
+ protected virtual int BindItemColumn(int pos)
+ {
+ ButtonColumn column = new ButtonColumn();
+ column.ButtonType = ButtonColumnType.PushButton;
+ column.Text = ItemText;
+ column.CommandName = ItemCommandName;
+ Grid.Columns.AddAt(pos, column);
+ return ++pos;
+ }
+
+ /// <summary>
+ /// Configure a control column to edit a DataGrid item (or row).
+ /// </summary>
+ /// <param name="pos">The column position</param>
+ /// <returns>The next column position</returns>
+ protected virtual int BindEditColumn(int pos)
+ {
+ EditCommandColumn column = new EditCommandColumn();
+ column.ButtonType = ButtonColumnType.PushButton;
+ column.EditText = EditText;
+ column.CancelText = QuitText;
+ column.UpdateText = SaveText;
+ Grid.Columns.AddAt(pos, column);
+ return ++pos;
+ }
+
+ /// <summary>
+ /// Configure the list of custom columns, starting from a given column position.
+ /// </summary>
+ /// <remarks><p>
+ /// If the edit or item columns have already been configured,
+ /// then starting position may be 1 or 2.
+ /// </p></remarks>
+ /// <param name="pos">Starting column position</param>
+ /// <returns>Next column position</returns>
+ protected virtual int BindColumns(int pos)
+ {
+ DataGrid grid = Grid;
+ grid.DataKeyField = DataKeyField;
+ IList configs = Configs;
+ int colCount = configs.Count;
+ for (int c = 0; c < colCount; c++)
+ {
+ IGridConfig config = configs[c] as IGridConfig;
+ if (config.HasTemplate)
+ {
+ pos = BindTemplateColumn(pos, config);
+ }
+ else pos = BindColumn(pos, config);
+ }
+ return pos;
+ }
+
+ /// <summary>
+ /// Configure a DataGrid column at the given position,
+ /// using the IGridConfig settings.
+ /// </summary>
+ /// <param name="pos">Position to insert column</param>
+ /// <param name="config">Column settings</param>
+ /// <returns>The next column pos</returns>
+ protected int BindColumn(int pos, IGridConfig config)
+ {
+ BoundColumn column = new BoundColumn();
+ column.HeaderText = config.HeaderText;
+ column.DataField = config.DataField;
+ // column.SortExpression = config.sortExpression; // See DataGridColumn.SortExpression Property
+ // column.DataFormatString = config.dataFormat; // See Formatting Types in .NET Dev Guide
+ Grid.Columns.AddAt(pos, column);
+ return pos + 1;
+ }
+
+ /// <summary>
+ /// Configure a template column at the given position,
+ /// using the IGtridConfig settings.
+ /// </summary>
+ /// <param name="pos">Position to insert column</param>
+ /// <param name="config">Column settings</param>
+ /// <returns>The next column pos</returns>
+ protected int BindTemplateColumn(int pos, IGridConfig config)
+ {
+ TemplateColumn column = new TemplateColumn();
+ column.HeaderText = config.HeaderText;
+ column.ItemTemplate = config.ItemTemplate;
+ column.EditItemTemplate = config.EditItemTemplate;
+ // column.SortExpression = config.sortExpression; // See DataGridColumn.SortExpression Property
+ // column.DataFormatString = config.dataFormat; // See Formatting Types in .NET Dev Guide
+ Grid.Columns.AddAt(pos, column);
+ return pos + 1;
+ }
+
+ /// <summary>
+ /// Store whether the DataGrid has bee configured.
+ /// </summary>
+ private bool bind = true;
+
+ /// <summary>
+ /// Initialize the DataGrid with any custom columns.
+ /// </summary>
+ /// <remarks>
+ /// This method is meant to be overriden by subclasses
+ /// to program a custom set of DataGrid columns.
+ /// </remarks>
+ protected virtual void InitGrid()
+ {
+ bind = true;
+ }
+
+ /// <summary>
+ /// Obtain the item count from Helper.
+ /// </summary>
+ /// <param name="helper">The helper to examine</param>
+ /// <returns>Total count of items for all pages</returns>
+ ///
+ protected int GetItemCount(IViewHelper helper)
+ {
+ return Convert.ToInt32(helper.Criteria[ITEM_COUNT]);
+ }
+
+ /// <summary>
+ /// Obtain the item page from Helper, or zero if no page set.
+ /// </summary>
+ /// <param name="helper">The helper to examine</param>
+ /// <returns>Current page number within data set</returns>
+ ///
+ protected int GetItemPage(IViewHelper helper)
+ {
+ object page = helper.Criteria[ITEM_PAGE];
+ if (page==null) return 0;
+ return Convert.ToInt32(page);
+ }
+
+ /// <summary>
+ /// Update the item page from Helper.
+ /// </summary>
+ /// <param name="helper">The helper to examine</param>
+ /// <returns>Current page number for current item</returns>
+ ///
+ protected void SetItemPage(IViewHelper helper, int page)
+ {
+ helper.Criteria[ITEM_PAGE] = Convert.ToString(page);
+ }
+
+
+ /// <summary>
+ /// Update the item offset from Helper.
+ /// </summary>
+ /// <param name="helper">The helper to examine</param>
+ /// <returns>Current page number for current item</returns>
+ ///
+ protected void SetItemOffset(IViewHelper helper, int ofs)
+ {
+ helper.Criteria[ITEM_OFFSET] = Convert.ToString(ofs);
+ }
+
+
+ /// <summary>
+ /// Obtain the item key field name.
+ /// </summary>
+ /// <param name="context">The context to examine</param>
+ /// <returns>Name of key field</returns>
+ ///
+ protected object GetItemKey(IDictionary context)
+ {
+ if (context==null) return null;
+ return context[ITEM_KEY];
+ }
+
+ /// <summary>
+ /// Store the item key field name.
+ /// </summary>
+ /// <param name="context">The context to examine</param>
+ /// <param name="key">The name of the item key field</param>
+ ///
+ protected void SetItemKey(IDictionary context, string key)
+ {
+ if (context!=null) context[ITEM_KEY] = key;
+ }
+
+ /// <summary>
+ /// Obtain the item key value for Helper.
+ /// </summary>
+ /// <param name="context">The context to examine</param>
+ /// <returns>Current page number within data set</returns>
+ ///
+ protected object GetItemKeyValue(IDictionary context)
+ {
+ if (context==null) return null;
+ object key = context[ITEM_KEY];
+ if (key==null) return null;
+ return context[key];
+ }
+
+ /// <summary>
+ /// Update the item key value for Helper, especially to clear on Add.
+ /// </summary>
+ /// <param name="context">The context to examine</param>
+ /// <returns>Current page number within data set</returns>
+ ///
+ protected void SetItemKeyValue(IDictionary context, string val)
+ {
+ if (context==null) return;
+ object key = context[ITEM_KEY];
+ if (key!=null) context[key] = val;
+ }
+
+ /// <summary>
+ /// Configure the DataGrid for initial display.
+ /// </summary>
+ /// <param name="helper">The Helper with an outcome to bind as a DataSource</param>
+ protected virtual void BindGrid(IViewHelper helper)
+ {
+
+ // Only bind columns once
+ // WARNING: Won't work with a singleton
+ DataGrid grid = Grid;
+ int count = (helper.Outcome).Count;
+ if (bind)
+ {
+ bind = false;
+ int i = 0;
+ if (HasEditColumn) i = BindEditColumn(i);
+ if (HasItemColumn) i = BindItemColumn(i);
+ // Adopt any direct changes to Grid object
+ if (grid.PageSize==DEFAULT_DATAGRID_PAGESIZE) grid.PageSize = PageSize;
+ AllowCustomPaging = AllowCustomPaging || grid.AllowCustomPaging;
+ // Check custom page settings
+ if (AllowCustomPaging)
+ {
+ grid.AllowCustomPaging = true;
+ count = GetItemCount(helper);
+ grid.VirtualItemCount = count;
+ int page = GetItemPage(helper);
+ if (page!=0) grid.CurrentPageIndex = page;
+ }
+ BindColumns(i);
+ }
+ ListPageIndexChanged_Raise(this,
+ grid.CurrentPageIndex,
+ grid.PageSize,
+ count);
+ DataSource(helper);
+ DataBind();
+ }
+
+ #endregion
+
+ #region Special ReadControls method
+
+ /// <summary>
+ /// Inspect a collection of DataGrid controls and set control values to a dictionary.
+ /// </summary>
+ /// <param name="controls">DataGrid Control Collection</param>
+ /// <param name="dictionary">Output object for control values</param>
+ /// <param name="keys">List of control/attribute names to collect</param>
+ /// <param name="nullIfEmpty">If value is an empty strong, set to null</param>
+ protected void ReadGridControls(ControlCollection controls, IDictionary dictionary, string[] keys, bool nullIfEmpty)
+ {
+ int i = -1;
+ foreach (Control t in controls)
+ {
+ i++;
+ string key = keys[i];
+ if (IsTextBox(t))
+ {
+ TextBox x = (TextBox) t;
+ string value = (nullIfEmpty) ? NullOnEmpty(x.Text) : x.Text;
+ dictionary.Add(key, value);
+ continue;
+ }
+ if (IsLabel(t))
+ {
+ Label x = (Label) t;
+ string value = (nullIfEmpty) ? NullOnEmpty(x.Text) : x.Text;
+ dictionary.Add(key, value);
+ continue;
+ }
+ if (IsListControl(t))
+ {
+ ListControl x = (ListControl) t;
+ string value = (nullIfEmpty) ? NullOnEmpty(x.SelectedValue) : x.SelectedValue;
+ dictionary.Add(key, value);
+ continue;
+ }
+ if (IsCheckBox(t))
+ {
+ CheckBox x = (CheckBox) t;
+ string value = (x.Checked) ? key : null;
+ dictionary.Add(key, value);
+ continue;
+ }
+ if (IsRadioButton(t))
+ {
+ RadioButton x = (RadioButton) t;
+ string value = (x.Checked) ? key : null;
+ dictionary.Add(key, value);
+ continue;
+ }
+ }
+
+ /// Workaround so that template columns can be utilized by a dynamic DataGrid.
+ /// [OVR-24] - Template columns not passed by DataGridCommandEventArgs
+ foreach (IGridConfig c in Configs)
+ {
+ bool isTemplateColumn = c.ItemTemplate!=null;
+ if (isTemplateColumn)
+ {
+ string key = c.DataField;
+ string value = FindControlValue(key);
+ dictionary.Add(key,value);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Command methods
+
+ /// <summary>
+ /// Provide an internal extension point
+ /// that can return an entry item of the appropriate type
+ /// to use when adding a new entry to the dataset.
+ /// </summary>
+ protected virtual IEntryList NewContextList
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Create a blank for editing by creating an empty row
+ /// and temporarily changing the datasource.
+ /// </summary>
+ /// <returns></returns>
+ protected virtual IViewHelper DataInsert()
+ {
+ DataGrid grid = Grid;
+ IEntryList list = NewContextList;
+ // Fake a blank row
+ IViewHelper helper = GetHelperFor(ListCommand);
+ list.Insert(String.Empty);
+ helper.Criteria[ListCommand] = list;
+ grid.DataSource = list;
+ grid.CurrentPageIndex = 0;
+ grid.EditItemIndex = 0;
+ BindGrid(helper);
+ return helper;
+ }
+
+ /// <summary>
+ /// Invoke a Find command.
+ /// </summary>
+ /// <param name="key">Data index key for the entry, if any</param>
+ /// <param name="controls">The set of controls</param>
+ /// <returns>The executed helper</returns>
+ protected virtual IViewHelper Find(string key, ControlCollection controls)
+ {
+ IViewHelper helper = ExecuteBind(FindCommand);
+ return helper;
+ }
+
+ /// <summary>
+ /// Invoke a Save command.
+ /// </summary>
+ /// <param name="key">Data index key for the entry, if any</param>
+ /// <param name="controls">The set of controls</param>
+ /// <returns>The executed helper</returns>
+ protected virtual IViewHelper Save(string key, ControlCollection controls)
+ {
+ IViewHelper h = GetHelperFor(SaveCommand);
+ if (h.IsNominal)
+ {
+ IList configs = Configs;
+ h.Criteria[DataKeyField] = key;
+ int cols = configs.Count;
+ string[] keys = new string[2 + cols];
+ // reconstruct the standard edit column keys
+ // just as placeholders, really
+ keys[0] = SaveText;
+ keys[1] = QuitText;
+ int index = 2;
+ // append our field names to the array of keys
+ for (int i = 0; i < cols; i++)
+ keys[index++] = (configs[i] as IGridConfig).DataField;
+ ReadGridControls(controls, h.Criteria, keys, true);
+
+ h.Execute();
+ }
+ return h;
+ }
+
+ #endregion
+
+ #region Loading methods
+
+ /// <summary>
+ /// Invoke a ListCommand that doesn't require a criteria.
+ /// </summary>
+ /// <returns>Executed helper</returns>
+ public virtual IViewHelper ExecuteList()
+ {
+ IViewHelper helper = Execute(ListCommand);
+ bool okay = helper.IsNominal;
+ if (okay) BindGrid(helper); // DoBindGrid = helper;
+ return helper;
+ }
+
+ /// <summary>
+ /// Look for a IssueEventKey, and scroll to it, if found.
+ /// </summary>
+ /// <param name="criteria">Input/outpout values</param>
+ /// <returns>Helper after obtaining list</returns>
+ public virtual IViewHelper ExecuteList(IDictionary criteria)
+ {
+
+ IViewHelper helper = ReadExecute(ListCommand, criteria);
+
+ object issue_event_key = GetItemKeyValue(criteria);
+ int count = GetItemCount(helper);
+ bool okay = helper.IsNominal;
+ bool skip_to_item = (issue_event_key == null) || (count==0) || !okay;
+ if (skip_to_item)
+ {
+ if (okay) BindGrid(helper); // DoBindGrid = helper;
+ return helper;
+ }
+
+ bool found = false;
+ int page = -1;
+ int item = -1;
+ object key = GetItemKey(criteria);
+ while ((!found) && (count>item) && helper.IsNominal)
+ {
+ page++;
+ if (helper.IsNominal)
+ {
+ IList outcome = helper.Outcome;
+ foreach (EntryDictionary e in outcome)
+ {
+ found = found || (issue_event_key.Equals(e.Criteria[key]));
+ }
+ if (!found)
+ {
+ item = item + outcome.Count;
+ SetItemOffset(helper,item+1);
+ helper.Execute();
+ }
+ }
+ }
+
+ if (helper.IsNominal)
+ {
+ if (found) SetItemPage(helper,page);
+ BindGrid(helper); // DoBindGrid = helper;
+ }
+ return helper;
+ }
+
+
+
+
+ /// <summary>
+ /// Setup the DataGrid when the page is first initialized.
+ /// </summary>
+ /// <param name="criteria">Parameters for the comamnd</param>
+ /// <returns></returns>
+ public virtual IViewHelper LoadGrid(IDictionary criteria)
+ {
+ IViewHelper helper;
+
+ if ((Grid.AllowCustomPaging) && (criteria == null))
+ {
+ list_Criteria_NewPageIndex(criteria, 0, true);
+ HasCriteria = true;
+ }
+
+ if (HasCriteria)
+ {
+ helper = ExecuteList(criteria);
+ }
+ else
+ helper = ExecuteList();
+
+ if (Grid.AllowCustomPaging)
+ {
+ int page = GetItemPage(helper);
+ int count = GetItemCount(helper);
+ ListPageIndexChanged_Raise(this, page, Grid.PageSize, count);
+ }
+
+ return helper;
+ }
+
+ #endregion
+
+ #region List properties to set
+
+ private DataGrid _Grid;
+
+ public DataGrid Grid
+ {
+ get { return _Grid; }
+ set { _Grid = value; }
+ }
+
+ #endregion
+
+ #region List methods
+
+ public virtual bool Open()
+ {
+ IViewHelper helper = LoadGrid(list_Criteria);
+ bool okay = helper.IsNominal;
+ if (!okay)
+ {
+ Page_Alert = helper;
+ }
+ return okay;
+ }
+
+ public virtual bool Open(IDictionary criteria)
+ {
+ Page_Reset();
+ list_Criteria_NewPageIndex(criteria, 0, AllowCustomPaging);
+ return Open();
+ }
+
+ public virtual void Reset(IDictionary criteria)
+ {
+ list_ResetIndex();
+ Open(criteria);
+ }
+
+ public virtual void Reset()
+ {
+ Reset(list_Criteria);
+ }
+
+ /// <summary>
+ /// Handle standard list Item events by opening item
+ /// or preparing to add a new item.
+ /// </summary>
+ /// <param name="commandName">The com</param>
+ /// <param name="index"></param>
+ protected virtual void list_Item(string commandName, int index)
+ {
+ switch (commandName)
+ {
+ case "Page":
+ // Handled by StepList_PageIndexChanged
+ break;
+ case msg_ITEM_COMMAND:
+ string key = Grid.DataKeys[index] as string;
+ list_ItemKey = key;
+ list_Item_Click(index);
+ break;
+ default:
+ {
+ if (list_Insert)
+ // ISSUE: If insert fails, old input is not retained. [WNE-67]
+ list_Add();
+ else
+ list_Refresh();
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handle standard Edit events by setting the index and refreshing display.
+ /// </summary>
+ /// <param name="index"></param>
+ protected virtual void list_Edit(int index)
+ {
+ // ISSUE: Event? Page_Prompt = msg_EDIT_HINT;
+ list_ItemIndex = index;
+ list_Refresh();
+ }
+
+ /// <summary>
+ /// Reset DataGrid state.
+ /// </summary>
+ protected virtual void list_Quit()
+ {
+ // ISSUE: Event? Page_Prompt = msg_QUIT_SUCCESS;
+ list_Insert = false;
+ list_ItemIndex = -1;
+ list_Refresh();
+ }
+
+ /// <summary>
+ /// Refresh DataGrid by rebinding datasource.
+ /// </summary>
+ protected virtual void list_Refresh()
+ {
+ DataBind();
+ }
+
+ /// <summary>
+ /// Set the selected index to 0.
+ /// </summary>
+ /// <remarks><p>
+ /// When changing the find set, also call List_ResetIndex;
+ /// otherwise, the DataGrid may try to select an item
+ /// that is outside the new found set.
+ /// </p></remarks>
+ protected void list_ResetIndex()
+ {
+ Grid.SelectedIndex = 0;
+ Grid.CurrentPageIndex = 0; // sic
+ }
+
+ /// <summary>
+ /// Insert a new row for editing.
+ /// </summary>
+ protected virtual void list_Add()
+ {
+ IViewHelper helper = DataInsert();
+ bool okay = helper.IsNominal;
+ if (okay)
+ {
+ // ISSUE: Event? Page_Prompt = msg_EDIT_HINT;
+ list_Insert = true;
+ list_ItemIndex = 0;
+ Grid.Visible = true;
+ }
+ else Page_Alert = helper;
+ }
+
+ #endregion
+
+ #region List events
+
+ /// <summary>
+ /// Prepare an item for editing and return its key.
+ /// </summary>
+ /// <returns>Data key for item to edit</returns>
+ private string GetDataKey()
+ {
+ DataGrid grid = Grid;
+ int index = grid.EditItemIndex;
+ string key = grid.DataKeys[index] as string;
+ return key;
+ }
+
+ /// <summary>
+ /// Harvest a collection of controls from DataGrid
+ /// </summary>
+ /// <param name="e"></param>
+ /// <returns>A control collection for DataGrid</returns>
+ public virtual ControlCollection GetControls(DataGridCommandEventArgs e)
+ {
+ DataGrid grid = Grid;
+ ControlCollection controls = new ControlCollection(grid);
+ foreach (TableCell t in e.Item.Cells)
+ {
+ for (int i = 0; i < t.Controls.Count; i++)
+ controls.Add(t.Controls[i]);
+ }
+ return controls;
+ }
+
+ // postback events
+
+ /// <summary>
+ /// Handle event by presenting selected row in an editable form.
+ /// </summary>
+ /// <param name="source">Event source</param>
+ /// <param name="e">Event parameters</param>
+ private void list_Edit(object source, DataGridCommandEventArgs e)
+ {
+ list_Edit(e.Item.ItemIndex);
+ }
+
+ /// <summary>
+ /// Handle event by retaining any changes to the selected DataGrid row.
+ /// </summary>
+ /// <param name="source">Event source</param>
+ /// <param name="e">Event parameters</param>
+ private void list_Save(object source, DataGridCommandEventArgs e)
+ {
+ string key = (list_Insert) ? null : GetDataKey();
+ ControlCollection controls = GetControls(e);
+ IViewHelper helper = Save(key, controls);
+ bool okay = helper.IsNominal;
+ if (okay)
+ {
+ if (View_Save != null) View_Save(this, new ViewArgs(helper));
+ list_Insert = false;
+ list_ItemIndex = -1;
+ okay = Open();
+ // ISSUE: Event? Page_Prompt = (List_Insert) ? msg_ADD_SUCCESS : msg_SAVE_SUCCESS;
+ }
+ if (!okay) Page_Alert = helper;
+ }
+
+
+ /// <summary>
+ /// Handle event by resetting DataGrid state.
+ /// </summary>
+ /// <param name="source">Event source</param>
+ /// <param name="e">Event parameters</param>
+ private void list_Quit(object source, DataGridCommandEventArgs e)
+ {
+ list_Quit();
+ }
+
+ /// <summary>
+ /// Handle list add event by inserting a new row,
+ /// and raising a View Add event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Event parameters</param>
+ protected void list_Add(object sender, EventArgs e)
+ {
+ list_Add();
+ if (View_Add != null) View_Add(sender, e);
+ }
+
+ /// <summary>
+ /// Handle list item event by opening item or preparing to add new item.
+ /// </summary>
+ /// <param name="source">Event source</param>
+ /// <param name="e">Event parameters</param>
+ private void List_Item(object source, DataGridCommandEventArgs e)
+ {
+ int index = e.Item.ItemIndex;
+ list_Item(e.CommandName, index);
+ }
+
+ /// <summary>
+ /// Provide key to store item limit in criteria.
+ /// </summary>
+ public const string ITEM_LIMIT = "item_limit";
+
+ /// <summary>
+ /// Provide key to store item offset in criteria.
+ /// </summary>
+ public const string ITEM_OFFSET = "item_offset";
+
+ /// <summary>
+ /// Provide key to store item count in criteria.
+ /// </summary>
+ public const string ITEM_COUNT = "item_count";
+
+ /// <summary>
+ /// Provide key to store item page in criteria.
+ /// </summary>
+ public const string ITEM_PAGE = "item_page";
+
+ /// <summary>
+ /// Provide key to store item key in criteria.
+ /// </summary>
+ public const string ITEM_KEY = "item_key";
+
+ #endregion
+
+ #region ListPageIndexChanged
+
+ /// <summary>
+ /// Signal that the Grid page index has changed,
+ /// and provide values for a page index hint.
+ /// </summary>
+ ///
+ public event EventHandler ListPageIndexChanged;
+
+ /// <summary>
+ /// Provide a default key for message resources that set the hint label.
+ /// </summary>
+ ///
+ public const string PAGE_INDEX_HINT = "page_index_hint";
+
+ /// <summary>
+ /// Provide a default key for the "Not Found" hint.
+ /// </summary>
+ ///
+ public const string NOT_FOUND_HINT = "not_found_hint";
+
+ /// <summary>
+ /// Provide values for a page index message (items x thru x of x).
+ /// </summary>
+ ///
+ public class ListPageIndexChangedArgs : EventArgs
+ {
+ public int ItemFrom;
+ public int ItemThru;
+ public int ItemCount;
+ }
+
+ /// <summary>
+ /// Optional extension point so that subclasses can make adjustments
+ /// based on whether there are items to display or not.
+ /// </summary>
+ /// <remarks><p>
+ /// The classic use case for this method is to turn off the Grid
+ /// if there are not any items to display in the Grid.
+ /// In this case, if this control is used more than once in an enclosing
+ /// page or control, then the Grid should be toggled on or off for
+ /// each instance (Visible = isItems);
+ /// </p></remarks>
+ /// <param name="isItems">True if there are 1 or more items to display</param>
+ public virtual void ListPageIndexChanged_IsItems(bool isItems)
+ {
+ // Override to provide functionalilty
+ }
+
+ /// <summary>
+ /// Lookup the PAGE_INDEX_HINT or the NOT_FOUND_HINT in the application
+ /// message resources, and return as a formatted string.
+ /// </summary>
+ /// <param name="args">Our ListPageIndexChangedArgs with the page index values</param>
+ /// <returns>Formatted message string ready to markup and present</returns>
+ ///
+ public virtual string ListPageIndexChanged_Message(ListPageIndexChangedArgs args)
+ {
+ bool isItems = (args.ItemCount > 0);
+ ListPageIndexChanged_IsItems(isItems);
+
+ string[] m_args = new string[3];
+ m_args[0] = Convert.ToString(args.ItemFrom);
+ m_args[1] = Convert.ToString(args.ItemThru);
+ m_args[2] = Convert.ToString(args.ItemCount);
+
+ string text = isItems ? GetMessage(PAGE_INDEX_HINT, m_args) : GetMessage(NOT_FOUND_HINT);
+ return text;
+ }
+
+ /// <summary>
+ /// Raise the ListPageIndexChanged event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="page">Current page number</param>
+ /// <param name="size">Items per page</param>
+ /// <param name="count">Total number of items</param>
+ ///
+ private void ListPageIndexChanged_Raise(object sender, int page, int size, int count)
+ {
+ if (ListPageIndexChanged != null)
+ {
+ int from = (page*size) + 1;
+ int thru = (page*size) + size;
+ if (thru > count) thru = count;
+ ListPageIndexChangedArgs a = new ListPageIndexChangedArgs();
+ a.ItemFrom = from;
+ a.ItemThru = thru;
+ a.ItemCount = count;
+ ListPageIndexChanged(sender, a);
+ }
+ }
+
+ /// <summary>
+ /// Handle the PageIndexChanged raised by our DataGrid.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguements</param>
+ ///
+ private void list_PageIndexChanged(object sender, DataGridPageChangedEventArgs e)
+ {
+ DataGrid grid = Grid;
+ int count = (grid.DataSource as IList).Count;
+
+ if (grid.AllowCustomPaging)
+ {
+ IDictionary criteria = list_Criteria_NewPageIndex(e.NewPageIndex);
+ IViewHelper helper = GetHelperFor(ListCommand);
+ helper.Read(criteria, true);
+ helper.Execute();
+ DataSource(helper);
+ count = GetItemCount(helper);
+ }
+ grid.CurrentPageIndex = e.NewPageIndex;
+
+ ListPageIndexChanged_Raise(sender, e.NewPageIndex, grid.PageSize, count);
+ list_Refresh();
+ }
+
+
+ #endregion
+
+ /// <summary>
+ /// Signal when an item is being added.
+ /// </summary>
+ ///
+ public event EventHandler View_Add;
+
+ /// <summary>
+ /// Handle click event by raising a View Add event
+ /// and passing the list criteria.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguments</param>
+ protected void add_Click(object sender, EventArgs e)
+ {
+ if (View_Add != null)
+ {
+ SetItemKeyValue(list_Criteria, null);
+ FindArgs f = new FindArgs(e, list_Criteria);
+ View_Add(sender, f);
+ }
+ }
+
+ /// <summary>
+ /// Provide an internal extension point for handling a selected item.
+ /// </summary>
+ /// <param name="index">Page index of item being selected</param>
+ protected virtual void list_Item_Click(int index)
+ {
+ // Override to provide implementation
+ }
+
+ /// <summary>
+ /// Signal when an item is being saved.
+ /// </summary>
+ public event EventHandler View_Save;
+
+ /// <summary>
+ /// Reset state for this control, including any ViewState attributes
+ /// and the page indexes (@see(list_ResetIndex)),
+ /// usually on a new Open event or on a Quit event,
+ /// </summary>
+ public override void Page_Reset()
+ {
+ list_ResetIndex();
+ base.Page_Reset();
+ }
+
+ /// <summary>
+ /// Handle the page's Load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguments</param>
+ private void Page_Load(object sender, EventArgs e)
+ {
+ DataGrid grid = Grid;
+ grid.AutoGenerateColumns = false;
+ grid.EditItemIndex = list_ItemIndex;
+ grid.CancelCommand += new DataGridCommandEventHandler(list_Quit);
+ grid.EditCommand += new DataGridCommandEventHandler(list_Edit);
+ grid.UpdateCommand += new DataGridCommandEventHandler(list_Save);
+ grid.ItemCommand += new DataGridCommandEventHandler(List_Item);
+ grid.PageIndexChanged += new DataGridPageChangedEventHandler(list_PageIndexChanged);
+ if (Visible) Open();
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ InitGrid();
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+
+ #region Templates
+
+ /// <summary>
+ /// Describe the fields needed to program a DataGrid column.
+ /// </summary>
+ public interface IGridConfig
+ {
+ string DataField { get; }
+ string HeaderText { get; }
+ ITemplate ItemTemplate { get; set; }
+ ITemplate EditItemTemplate { get; set; }
+ bool HasTemplate { get; }
+ }
+
+ /// <summary>
+ /// Implement IGridConfig.
+ /// </summary>
+ public class GridConfig : IGridConfig
+ {
+ /// <summary>
+ /// Store attribute name for column (required).
+ /// </summary>
+ private string _DataField;
+
+ /// <summary>
+ /// Provide attribute name for column (required).
+ /// </summary>
+ public string DataField
+ {
+ get { return _DataField; }
+ }
+
+ /// <summary>
+ /// Store heading for this column (optional).
+ /// </summary>
+ private string _HeaderText;
+
+ /// <summary>
+ /// Provide heading for this column (optional).
+ /// </summary>
+ public string HeaderText
+ {
+ get
+ {
+ if (_HeaderText == null) return DataField;
+ return _HeaderText;
+ }
+ }
+
+ /// <summary>
+ /// Store item template for this column (optional).
+ /// </summary>
+ private ITemplate _ItemTemplate;
+
+ /// <summary>
+ /// Provide item template for this column (optional).
+ /// </summary>
+ public ITemplate ItemTemplate
+ {
+ get { return _ItemTemplate; }
+ set { _ItemTemplate = value; }
+ }
+
+ /// <summary>
+ /// Store edit template for this column (optional).
+ /// </summary>
+ private ITemplate _EditItemTemplate;
+
+ /// <summary>
+ /// Provide edit template for this column (optional).
+ /// </summary>
+ public ITemplate EditItemTemplate
+ {
+ get { return _EditItemTemplate; }
+ set { _EditItemTemplate = value; }
+ }
+
+ // string DataFormat;
+ // string SortFormat;
+ // ITemplate ItemFormat;
+
+ /// <summary>
+ /// Store whether attribute has a template.
+ /// </summary>
+ public bool HasTemplate
+ {
+ get { return (_ItemTemplate != null) || (_EditItemTemplate != null); }
+ }
+
+ /// <summary>
+ /// Construct a GridConfig from a data field and header test.
+ /// </summary>
+ /// <param name="dataField">The attribute name for this column</param>
+ /// <param name="headerText">The header text for this column</param>
+ public GridConfig(string dataField, string headerText)
+ {
+ _DataField = dataField;
+ _HeaderText = headerText;
+ }
+
+ /// <summary>
+ /// Construct a GridConfig using all attributes.
+ /// </summary>
+ /// <param name="dataField">The attribute name for this column</param>
+ /// <param name="headerText">The header text for this column</param>
+ /// <param name="itemTemplate">The item template for this column</param>
+ /// <param name="editItemTemplate">The edit template for this column</param>
+ public GridConfig(string dataField, string headerText, ITemplate itemTemplate, ITemplate editItemTemplate)
+ {
+ _DataField = dataField;
+ _HeaderText = headerText;
+ _ItemTemplate = itemTemplate;
+ _EditItemTemplate = editItemTemplate;
+ }
+ }
+
+ /// <summary>
+ /// Add literal text to a DataGrid column.
+ /// </summary>
+ public class LiteralTemplate : ITemplate
+ {
+
+ /// <summary>
+ /// Store attribute name.
+ /// </summary>
+ private string _DataField;
+
+ /// <summary>
+ /// Handle data binding event by setting control text to data field.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void OnDataBinding(object sender, EventArgs e)
+ {
+ Literal control;
+ control = (Literal) sender;
+ DataGridItem container = (DataGridItem) control.NamingContainer;
+ control.Text = DataBinder.Eval(container.DataItem, _DataField) as string;
+ }
+
+ public void InstantiateIn(Control container)
+ {
+ Literal control = new Literal();
+ control.ID = _DataField;
+ control.DataBinding += new EventHandler(OnDataBinding);
+ container.Controls.Add(control);
+ }
+
+ /// <summary>
+ /// Construct instance from attribute name.
+ /// </summary>
+ /// <param name="dataField">Attribute name</param>
+ public LiteralTemplate(string dataField)
+ {
+ _DataField = dataField;
+ }
+ }
+
+ /// <summary>
+ /// Configure a DataGrid column to display the selected value on the KeyValue list.
+ /// </summary>
+ public class KeyValueTemplate : ITemplate
+ {
+ private string _DataField;
+ private IKeyValueList _Control;
+
+ /// <summary>
+ /// Handle data binding events by extracting key and value,
+ /// and setting selected value to control text.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguments</param>
+ private void OnDataBinding(object sender, EventArgs e)
+ {
+ Literal control;
+ control = (Literal) sender;
+ DataGridItem container = (DataGridItem) control.NamingContainer;
+ string key = DataBinder.Eval(container.DataItem, _DataField) as string;
+ control.Text = _Control.ValueFor(key);
+ }
+
+ public void InstantiateIn(Control container)
+ {
+ Literal control = new Literal();
+ control.ID = _DataField;
+ control.DataBinding += new EventHandler(OnDataBinding);
+ container.Controls.Add(control);
+ }
+
+ /// <summary>
+ /// Construct instance from a datafield and the list.
+ /// </summary>
+ /// <param name="dataField">Attribute name</param>
+ /// <param name="list">List of keyValue items</param>
+ public KeyValueTemplate(string dataField, IKeyValueList list)
+ {
+ _DataField = dataField;
+ _Control = list;
+ }
+ }
+
+ /// <summary>
+ /// Present a drop down list control when editing a column.
+ /// </summary>
+ public class DropDownListTemplate : ITemplate
+ {
+ /// <summary>
+ /// Store attribute name.
+ /// </summary>
+ private string _DataField;
+
+ /// <summary>
+ /// Store reference to the DropDownList control.
+ /// </summary>
+ private DropDownList _Control;
+
+ /// <summary>
+ /// Scan list for an item matching value.
+ /// </summary>
+ /// <param name="control">The control to scan</param>
+ /// <param name="value">The value to match</param>
+ private void SelectItem(ListControl control, string value)
+ {
+ if (value != null)
+ {
+ int index = 0;
+ foreach (ListItem i in control.Items)
+ {
+ if (value.Equals(i.Value))
+ {
+ control.SelectedIndex = index;
+ continue;
+ }
+ index++;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handle a data binding event by selecting the key row.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void OnDataBinding(object sender, EventArgs e)
+ {
+ DropDownList control;
+ control = (DropDownList) sender;
+ DataGridItem container = (DataGridItem) control.NamingContainer;
+ string key = DataBinder.Eval(container.DataItem, _DataField) as string;
+ SelectItem(control, key);
+ _SelectedIndex = control.SelectedIndex; // FIXME: [OVR-24]
+ }
+
+ /// <summary>
+ /// Cache the selected index for OnPreRender.
+ /// </summary>
+ private int _SelectedIndex;
+
+ /// <summary>
+ /// Provide a kludge method to set Selected Index.
+ /// </summary>
+ /// <remarks><p>
+ /// After setting the selected index on DataBinding,
+ /// it is somehow being reset to 0 before prerender.
+ /// This method restores the selected index st by
+ /// OnDataBinding.
+ /// </p></remarks>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ private void OnPreRender(object sender, EventArgs e)
+ {
+ DropDownList control;
+ control = (DropDownList) sender;
+ control.SelectedIndex = _SelectedIndex;
+ }
+
+ public void InstantiateIn(Control container)
+ {
+ container.Controls.Add(_Control);
+ }
+
+ /// <summary>
+ /// Construct a DropDownListTempate from an id and datasource.
+ /// </summary>
+ /// <param name="id">Data Field Name</param>
+ public DropDownListTemplate(string id, object dataSource)
+ {
+ _DataField = id;
+ _Control = new DropDownList();
+ _Control.ID = id;
+ _Control.DataSource = dataSource;
+ _Control.DataBind();
+ _Control.DataBinding += new EventHandler(OnDataBinding);
+ _Control.PreRender += new EventHandler(OnPreRender);
+ }
+
+ /// <summary>
+ /// Construct a DropDownListTempate from an id and list.
+ /// </summary>
+ /// <param name="id">Data Field Name</param>
+ /// <param name="list">Items to list</param>
+ public DropDownListTemplate(string id, IKeyValueList list) : this(id,list,false)
+ {}
+
+ /// <summary>
+ /// Construct a DropDownListTempate from id, list, insertNullKey.
+ /// </summary>
+ /// <param name="id">Data Field Name</param>
+ /// <param name="list">Items to list</param>
+ /// <param name="insertNullKey">Whether to prepend a -v- item to the list</param>
+ public DropDownListTemplate(string id, IKeyValueList list, bool insertNullKey)
+ {
+ if (insertNullKey)
+ {
+ lock(list)
+ {
+ IKeyValue e = list[0] as KeyValue;
+ if (!NULL_TOKEN.Equals(e.Text))
+ {
+ list.Insert(0, new KeyValue(String.Empty, NULL_TOKEN));
+ }
+ }
+ }
+
+ _DataField = id;
+ _Control = new DropDownList();
+ _Control.ID = id;
+ _Control.DataSource = list;
+ _Control.DataTextField = "value";
+ _Control.DataValueField = "key";
+ _Control.DataBind();
+ _Control.DataBinding += new EventHandler(OnDataBinding);
+ _Control.PreRender += new EventHandler(OnPreRender);
+ }
+ }
+
+ #endregion
+ }
+
+ /*
+
+
+ #region List Panel
+
+ protected Panel pnlList;
+ protected DataGridControl list_report;
+ // from BaseGrid: Button cmdListAdd;
+
+ private void List_Init()
+ {
+ list_report.Helper = this.Helper;
+ list_report.List_Init();
+ pnlList.Visible = false;
+ }
+
+ /// <summary>
+ /// Select only those items in control
+ /// whose Value property matches the given value.
+ /// If the value is null, no action is taken.
+ /// </summary>
+ /// <param name="control">ListControl to process</param>
+ /// <param name="text">Text label to match</param>
+ ///
+ static void SelectItemText (ListControl control, string text)
+ {
+ if (text != null)
+ {
+ foreach (ListItem i in control.Items)
+ i.Selected = false;
+
+ foreach (ListItem i in control.Items)
+ {
+ if (text.Equals (i.Text))
+ i.Selected = true;
+ }
+ }
+ }
+
+ private void List_Edit_Submit(IDictionary context)
+ {
+ Helper.BindControls(pnlEdit.Controls,context,null);
+ string county_name = context[App.COUNTY_NAME] as string;
+ SelectItemText(county_key_list,county_name);
+ Template_Load (App.msg_ROUTING_HEADING, App.msg_ROUTING_EDIT_PROMPT);
+ pnlEdit.Visible = true;
+ pnlFind.Visible = false;
+ pnlList.Visible = false;
+ }
+
+ #endregion
+
+
+
+ */
+}
diff --git a/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx.resx b/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/GridControl.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/Nexus/Web/HintLabel.cs b/struts-sandbox/overdrive/Nexus/Web/HintLabel.cs
new file mode 100644
index 0000000..0db23c4
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/HintLabel.cs
@@ -0,0 +1,23 @@
+namespace Nexus.Web
+{
+ /// <summary>
+ /// Extend MessageLabel to respond only to the View_Hint event
+ /// and use an alternate suffix.
+ /// </summary>
+ public class HintLabel : ViewLabel
+ {
+ /// <summary>
+ /// Default suffix for NameLabel IDs ["_hint"].
+ /// </summary>
+ public const string HINT_SUFFIX = "_hint";
+
+ /// <summary>
+ /// Set the defaults for this subclass.
+ /// </summary>
+ public HintLabel()
+ {
+ Suffix = HINT_SUFFIX;
+ View_Alert = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/IViewControl.cs b/struts-sandbox/overdrive/Nexus/Web/IViewControl.cs
new file mode 100644
index 0000000..613a7c0
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/IViewControl.cs
@@ -0,0 +1,51 @@
+using System.Collections;
+using System.Web.UI;
+using Nexus.Core.Helpers;
+using Nexus.Core.Profile;
+
+namespace Nexus.Web
+{
+ public interface IViewControl
+ {
+ /// <summary>
+ /// Set Labels and TextBoxes to an empty string
+ /// to ensure inappropriate values are not carried over.
+ /// </summary>
+ ///
+ void ResetControls();
+
+ /// <summary>
+ /// User profile, which includes user ID and Locale.
+ /// </summary>
+ IProfile Profile { get; set; }
+
+ IViewHelper GetHelperFor(string command);
+ IViewHelper Execute(string command);
+
+ void Bind(ControlCollection controls, IDictionary dictionary);
+ void Bind(IDictionary dictionary);
+
+ void ExecuteBind(ControlCollection controls, IViewHelper helper);
+ void ExecuteBind(IViewHelper helper);
+
+ IViewHelper ExecuteBind(ControlCollection controls, string command);
+ IViewHelper ExecuteBind(string command);
+
+ void ReadExecute(IViewHelper helper, bool nullIfEmpty);
+ void ReadExecute(IViewHelper helper);
+
+ IViewHelper Read(string command, bool nullIfEmpty);
+ IViewHelper Read(string command);
+
+ IViewHelper ReadExecute(string command, bool nullIfEmpty);
+ IViewHelper ReadExecute(string command);
+
+ IViewHelper ReadExecute(ControlCollection collection, string command, bool nullIfEmpty);
+ IViewHelper ReadExecute(ControlCollection collection, string command);
+
+ IViewHelper Read(string command, IDictionary criteria, bool nullIfEmpty);
+ IViewHelper ReadExecute(string command, IDictionary criteria, bool nullIfEmpty);
+ IViewHelper ReadExecute(string command, IDictionary criteria);
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/Messages.resx b/struts-sandbox/overdrive/Nexus/Web/Messages.resx
new file mode 100644
index 0000000..d7db7ae
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Messages.resx
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+
+
+ <!-- Any of these values can be overridden in the host application. Load the host resources FIRST! -->
+
+ <data name="entry_edit_command">
+ <value>EDIT</value>
+ </data>
+
+ <data name="entry_quit_command">
+ <value>QUIT</value>
+ </data>
+
+ <data name="entry_save_command">
+ <value>SAVE</value>
+ </data>
+
+ <data name="entry_item_command">
+ <value>#</value>
+ </data>
+
+ <data name="entry_item_command_name">
+ <value>item_command</value>
+ </data>
+
+ <data name="hint_edit">
+ <value>Edit entry, press SAVE. </value>
+ </data>
+
+ <data name="hint_success_add">
+ <value>Item added. </value>
+ </data>
+
+ <data name="hint_success_edit">
+ <value>Changes saved. </value>
+ </data>
+
+ <data name="hint_success_quit">
+ <value>Change cancelled. </value>
+ </data>
+
+ <data name="list_add_command">
+ <value>ADD ITEM</value>
+ </data>
+
+
+</root>
diff --git a/struts-sandbox/overdrive/Nexus/Web/TextLabel.cs b/struts-sandbox/overdrive/Nexus/Web/TextLabel.cs
new file mode 100644
index 0000000..3610d8a
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/TextLabel.cs
@@ -0,0 +1,25 @@
+namespace Nexus.Web
+{
+ /// <summary>
+ /// Extend MessageLabel to ignore runtime events,
+ /// require an entry, and use an alternate suffix.
+ /// </summary>
+ public class TextLabel : ViewLabel
+ {
+ /// <summary>
+ /// Default suffix for NameLabel IDs ["_label"].
+ /// </summary>
+ public const string TEXT_SUFFIX = "_label";
+
+ /// <summary>
+ /// Set the defaults for this subclass.
+ /// </summary>
+ public TextLabel()
+ {
+ Suffix = TEXT_SUFFIX;
+ Required = true;
+ View_Hint = false;
+ View_Alert = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx b/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx
new file mode 100644
index 0000000..6a12e25
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx
@@ -0,0 +1 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="ViewControl.ascx.cs" Inherits="Nexus.Web.ViewControl" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
diff --git a/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx.cs b/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx.cs
new file mode 100644
index 0000000..30fc3ac
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx.cs
@@ -0,0 +1,950 @@
+using System;
+using System.Collections;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using Nexus.Core.Profile;
+using UserControl = Spring.Web.UI.UserControl;
+
+namespace Nexus.Web
+{
+ /// <summary>
+ /// Base class for view controls (sub forms).
+ /// </summary>
+ /// <remarks>
+ /// ViewControl can read and bind controls,
+ /// and provides access methods for helper and message resources
+ /// </remarks>
+ ///
+ ///
+ ///
+ public class ViewControl : UserControl, IViewControl
+ {
+ private IRequestCatalog _Catalog;
+
+ /// <summary>
+ /// Helper passed by an enclosing control (e.g. Page).
+ /// </summary>
+ /// <remarks><p>
+ /// Subclasses adding EventHandlers
+ /// should pass a reference to themselves with a ViewArgs instance,
+ /// encapsulating the Helper.
+ /// </p></remarks>
+ public virtual IRequestCatalog Catalog
+ {
+ get { return _Catalog; }
+ set { _Catalog = value; }
+ }
+
+ /// <summary>
+ /// Psuedo property to generate an Error event encapsulating
+ /// our Helper property, containing the error.
+ /// </summary>
+ protected IViewHelper Page_Alert
+ {
+ set { View_Alert_Handler(this, new ViewArgs(value)); }
+ }
+
+ #region String utilities
+
+ protected string NullOnEmpty(string input)
+ {
+ return (string.Empty.Equals(input)) ? null : input;
+ }
+
+ protected string Trim(string input, bool nullOnEmpty)
+ {
+ string output = (input==null) ? null : input.Trim();
+ return (nullOnEmpty) ? NullOnEmpty(output) : output;
+ }
+
+ /// <summary>
+ /// Extract the root name from the id, allowing for a prefix and suffix.
+ /// </summary>
+ /// <param name="id">The full id, including prefix and suffix.</param>
+ /// <param name="prefix">The prefix to omit.</param>
+ /// <param name="suffix">The suffix to omit.</param>
+ /// <returns>ID for corresponding entry</returns>
+ ///
+ private string RootId(string id, string prefix, string suffix)
+ {
+ int v = id.LastIndexOf(suffix);
+ string fore = id.Substring(0, v);
+ string root = ToColumn(fore, prefix);
+ return root;
+ }
+
+ /// <summary>
+ /// Trim any SQL wildcards that may have been added to a search string.
+ /// </summary>
+ /// <param name="input">String to trim</param>
+ /// <returns>Input without SQL wildcards</returns>
+ ///
+ protected string TrimWildCards(string input)
+ {
+ string trimmed = null;
+ if (input != null) trimmed = input.Trim('%');
+ return trimmed;
+ }
+
+ public const string NULL_TOKEN = "--v--";
+
+ private static KeyValue _NullKey = new KeyValue(String.Empty, NULL_TOKEN);
+
+ /// <summary>
+ /// Default value for dropdown lists.
+ /// </summary>
+ protected KeyValue NullKey
+ {
+ get { return _NullKey; }
+ }
+
+ /// <summary>
+ /// The default list suffix.
+ /// </summary>
+ private string _ListSuffix = "_list";
+
+ protected string ListSuffix
+ {
+ get { return _ListSuffix; }
+ set { _ListSuffix = value; }
+ }
+
+ #endregion
+
+ #region Control utilities
+
+ /// <summary>
+ /// Return true if control is a button.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a Button</returns>
+ ///
+ protected bool IsButton(Control control)
+ {
+ return (typeof (Button).Equals(control.GetType()));
+ }
+
+ /// <summary>
+ /// Return true if control is a Checkbox.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a Checkbox</returns>
+ ///
+ protected bool IsCheckBox(Control control)
+ {
+ return (typeof (CheckBox).Equals(control.GetType()));
+ }
+
+ /// <summary>
+ /// Return true if control is a HyperLink.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a TextBox</returns>
+ ///
+ protected bool IsHyperLink(Control control)
+ {
+ return (typeof (HyperLink).Equals(control.GetType()));
+ }
+
+ /// <summary>
+ /// Return true if control is a Label.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a Label</returns>
+ ///
+ protected bool IsLabel(Control control)
+ {
+ return (typeof (Label).Equals(control.GetType()));
+ }
+
+ /// <summary>
+ /// Return true if control is a MessageLabel
+ /// or MessageLabel subclass.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a NameLabel</returns>
+ ///
+ protected bool IsViewLabel(Control control)
+ {
+ return (control is ViewLabel);
+ }
+
+ /// <summary>
+ /// Return true if control is a List Control or one of the standard subclasses.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a TextBox</returns>
+ ///
+ protected bool IsListControl(Control control)
+ {
+ bool isList = false;
+ Type type = control.GetType();
+ isList = (isList) || typeof (ListControl).Equals(type);
+ isList = (isList) || typeof (CheckBoxList).Equals(type);
+ isList = (isList) || typeof (DropDownList).Equals(type);
+ isList = (isList) || typeof (ListBox).Equals(type);
+ isList = (isList) || typeof (RadioButtonList).Equals(type);
+ return isList;
+ }
+
+ /// <summary>
+ /// Return true if control is a RadioButton.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a RadioButton</returns>
+ ///
+ protected bool IsRadioButton(Control control)
+ {
+ return (typeof (RadioButton).Equals(control.GetType()));
+ }
+
+ /// <summary>
+ /// Return true if control is a TextBox.
+ /// </summary>
+ /// <param name="control">Control to test.</param>
+ /// <returns>True if control is a TextBox</returns>
+ ///
+ protected bool IsTextBox(Control control)
+ {
+ return (typeof (TextBox).Equals(control.GetType()));
+ }
+
+ /// <summary>
+ /// Select only those items in control
+ /// whose Text property matches the given text.
+ /// If the value is null, no action is taken.
+ /// </summary>
+ /// <param name="control">Control to set</param>
+ /// <param name="text">Text to match</param>
+ ///
+ protected void SelectItemText(ListControl control, string text)
+ {
+ if (text != null)
+ {
+ foreach (ListItem i in control.Items)
+ i.Selected = false;
+
+ foreach (ListItem i in control.Items)
+ {
+ if (text.Equals(i.Text))
+ i.Selected = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Kludgy method to read the value of a control
+ /// directly from the request under certain circumstances.
+ /// </summary>
+ /// <remarks><p>
+ /// This method is intended to workaround a problem
+ /// we are having with dymanci DataGrid templates.
+ /// The template column seems to be absent from the event args.
+ /// Other columns are there, but a template column is ignored.
+ /// </p><p>
+ /// This method can retrieve the value directly from the request
+ /// *if* the identifier is a unique string of characters that
+ /// won't be found as part of another parameter.
+ /// The DataGrid changes the identifer name,
+ /// but appends the control id given by the template.
+ /// So, we use key.IndexOf to find the control id within the
+ /// manufactured parameter id.
+ /// Kludgy, but it's only meant as a workaround (see OVR-24).
+ /// </p></remarks>
+ ///
+ /// <param name="id">Control ID</param>
+ /// <returns>Value of first paramter that has "id"
+ /// as any part of its name.</returns>
+ protected string FindControlValue(string id)
+ {
+ string ctlKey = null;
+ string[] keys = Request.Params.AllKeys;
+ foreach (string key in keys)
+ {
+ bool found = (key.IndexOf(id) > -1);
+ if (found) ctlKey = key;
+ continue;
+ }
+ return Request.Params[ctlKey]; // FIXME
+ }
+
+ #endregion
+
+ #region ViewState methods
+
+ /// <summary>
+ /// Token under which to store the array of primary keys.
+ /// </summary>
+ ///
+ private const string KEYS = "Keys";
+
+ /// <summary>
+ /// Set an array of primary keys to the view state.
+ /// </summary>
+ /// <param name="keys">.</param>
+ ///
+ protected void SetKeyIndex(string[] keys)
+ {
+ ViewState[KEYS] = keys;
+ }
+
+ /// <summary>
+ /// Return the nth key from the array kept in view state.
+ /// </summary>
+ /// <param name="index">Array index for the primary key (corresponds to index of the DataGrid).</param>
+ /// <returns>Nth key from primary key array kept in view state.</returns>
+ protected string GetKeyIndex(int index)
+ {
+ string[] keys = (string[]) ViewState[KEYS];
+ return keys[index];
+ }
+
+ /// <summary>
+ /// Return the primary key for the current item index of the DataGrid.
+ /// </summary>
+ /// <param name="e">DataGrid event arguments.</param>
+ /// <param name="offset">Number of items on prior pages, if any (page*pagesize).</param>
+ /// <returns>The primary key for the current item index of the DataGrid.</returns>
+ protected string GetKeyIndex(DataGridCommandEventArgs e, int offset)
+ {
+ return GetKeyIndex(e.Item.ItemIndex + offset);
+ }
+
+ /// <summary>
+ /// Return the index for the given key,
+ /// usually so that it can be selected.
+ /// </summary>
+ /// <param name="list">List of KeyValue entries.</param>
+ /// <param name="key">A key value from the list</param>
+ /// <returns>-1 if not found</returns>
+ ///
+ protected int IndexForKey(IList list, string key)
+ {
+ int i = 0;
+ foreach (KeyValue row in list)
+ {
+ if (key.Equals(row.Key))
+ return i;
+ i++;
+ }
+ return -1;
+ }
+
+ #endregion
+
+ #region IViewControl methods
+
+ public void ResetControls()
+ {
+ ControlCollection controls = Controls;
+ foreach (Control control in controls)
+ {
+ if (IsTextBox(control))
+ {
+ TextBox x = (TextBox) control;
+ x.Text = String.Empty;
+ continue;
+ }
+ if (IsListControl(control))
+ {
+ ListControl x = (ListControl) control;
+ x.SelectedIndex = -1;
+ continue;
+ }
+
+ if (IsRadioButton(control))
+ {
+ RadioButton x = (RadioButton) control;
+ x.Checked = false;
+ continue;
+ }
+
+ if (IsCheckBox(control))
+ {
+ CheckBox x = (CheckBox) control;
+ x.Checked = false;
+ continue;
+ }
+ }
+ }
+
+ private IProfile _Profile;
+
+ public IProfile Profile
+ {
+ get { return _Profile; }
+ set { _Profile = value; }
+ }
+
+ public IViewHelper GetHelperFor(string command)
+ {
+ IViewHelper helper = Catalog.GetHelperFor(command);
+ helper.Profile = Profile;
+ return helper;
+ }
+
+ public IViewHelper Execute(string command)
+ {
+ IViewHelper helper = GetHelperFor(command);
+ helper.Execute();
+ return helper;
+ }
+
+ protected virtual void InitViewLabels()
+ {
+ foreach (Control t in Controls)
+ {
+ if (IsViewLabel(t))
+ {
+ ViewLabel x = (ViewLabel) t;
+ if (x.View_Alert)
+ {
+ View_Alert += new EventHandler(x.View_Alert_Handler);
+ }
+ /*
+ if (x.View_Hint)
+ {
+ View_Hint += new EventHandler(x.View_Hint_Handler);
+ }
+ */
+ continue;
+ }
+ }
+ }
+
+ public void EnableControls(ControlCollection controls, bool enable)
+ {
+ foreach (Control t in controls)
+ {
+ if (IsTextBox(t))
+ {
+ TextBox x = (TextBox) t;
+ x.Enabled = enable;
+ continue;
+ }
+ if (IsViewLabel(t))
+ {
+ ViewLabel x = (ViewLabel) t;
+ x.Enabled = enable;
+ continue;
+ }
+ if (IsLabel(t))
+ {
+ Label x = (Label) t;
+ x.Enabled = enable;
+ continue;
+ }
+ if (IsListControl(t))
+ {
+ ListControl x = (ListControl) t;
+ x.Enabled = enable;
+ continue;
+ }
+ if (IsCheckBox(t))
+ {
+ CheckBox x = (CheckBox) t;
+ x.Enabled = enable;
+ continue;
+ }
+ if (IsRadioButton(t))
+ {
+ RadioButton x = (RadioButton) t;
+ x.Enabled = enable;
+ continue;
+ }
+ if (IsButton(t))
+ {
+ Button x = (Button) t;
+ x.Enabled = enable;
+ continue;
+ }
+ }
+ }
+
+ public void EnableControls(ControlCollection controls)
+ {
+ EnableControls(controls,true);
+ }
+
+ public void EnableControls()
+ {
+ EnableControls(Controls,true);
+ }
+
+ public void DisableControls(ControlCollection controls)
+ {
+ EnableControls(controls,false);
+ }
+
+ public void DisableControls()
+ {
+ EnableControls(Controls,false);
+ }
+
+ private void BindControls(ControlCollection controls, IDictionary dictionary, string prefix, string list_suffix)
+ {
+ foreach (Control t in controls)
+ {
+ if (IsTextBox(t))
+ {
+ TextBox x = (TextBox) t;
+ object v = dictionary[ToColumn(x.ID, prefix)];
+ if (v != null) x.Text = v.ToString();
+ continue;
+ }
+ if (IsViewLabel(t))
+ {
+ ViewLabel x = (ViewLabel) t;
+ object v = dictionary[ToColumn(x.ID, prefix)];
+ if (v != null) x.Text = v.ToString();
+ continue;
+ }
+ if (IsLabel(t))
+ {
+ Label x = (Label) t;
+ object v = dictionary[ToColumn(x.ID, prefix)];
+ if (v != null) x.Text = v.ToString();
+ continue;
+ }
+ if (IsListControl(t))
+ {
+ ListControl x = (ListControl) t;
+ string root = RootId(x.ID, prefix, list_suffix);
+ IList s = dictionary[root + list_suffix] as IList; // this_key_list
+ string r = dictionary[root] as string; // this_key
+ if ((null == r) || (0 == r.Length))
+ BindListControl(x, s);
+ else
+ BindListControl(x, s, r);
+ continue;
+ }
+ if (IsCheckBox(t))
+ {
+ CheckBox x = (CheckBox) t;
+ object v = dictionary[ToColumn(x.ID, prefix)];
+ if (v != null) x.Checked = true;
+ continue;
+ }
+ if (IsRadioButton(t))
+ {
+ RadioButton x = (RadioButton) t;
+ object v = dictionary[ToColumn(x.ID, prefix)];
+ if (v != null) x.Checked = true;
+ continue;
+ }
+ }
+ }
+
+ public void Bind(ControlCollection controls, IDictionary dictionary)
+ {
+ BindControls(controls, dictionary, null, ListSuffix);
+ }
+
+ public void Bind(IDictionary dictionary)
+ {
+ BindControls(Controls, dictionary, null, ListSuffix);
+ }
+
+ public void ExecuteBind(ControlCollection controls, IViewHelper helper)
+ {
+ helper.Execute();
+ Bind(controls, helper.Criteria);
+ }
+
+ public IViewHelper ExecuteBind(ControlCollection controls, string command)
+ {
+ IViewHelper helper = GetHelperFor(command);
+ ExecuteBind(controls, helper);
+ return helper;
+ }
+
+ public void ExecuteBind(IViewHelper helper)
+ {
+ ExecuteBind(Controls, helper);
+ }
+
+ public IViewHelper ExecuteBind(string command)
+ {
+ IViewHelper helper = GetHelperFor(command);
+ ExecuteBind(helper);
+ return helper;
+ }
+
+ /// <summary>
+ /// Render a control id as a column name
+ /// by trimming a prefix from the id, if any.
+ /// </summary>
+ /// <param name="id">String to process.</param>
+ /// <param name="prefix">Prefix to remove.</param>
+ /// <returns>id without prefix.</returns>
+ ///
+ private string ToColumn(string id, string prefix)
+ {
+ string trimmed;
+ if (null == prefix) trimmed = id;
+ else trimmed = id.Substring(prefix.Length);
+ return trimmed;
+ }
+
+ private void ReadControls(ControlCollection controls, IDictionary dictionary, string prefix, string list_suffix, bool nullOnEmpty)
+ {
+ foreach (Control t in controls)
+ {
+ if (IsTextBox(t))
+ {
+ TextBox x = (TextBox) t;
+ string value = Trim(x.Text, nullOnEmpty);
+ dictionary.Add(ToColumn(x.ID, prefix), value);
+ continue;
+ }
+ if (IsLabel(t))
+ {
+ Label x = (Label) t;
+ string value = Trim(x.Text, nullOnEmpty);
+ dictionary.Add(ToColumn(x.ID, prefix), value);
+ continue;
+ }
+ if (IsListControl(t))
+ {
+ ListControl x = (ListControl) t;
+ string root = RootId(x.ID, prefix, list_suffix);
+ string value = Trim(x.SelectedValue, nullOnEmpty);;
+ dictionary.Add(root, value);
+ continue;
+ }
+ if (IsCheckBox(t))
+ {
+ CheckBox x = (CheckBox) t;
+ string key = ToColumn(x.ID, prefix);
+ string value = (x.Checked) ? key : null;
+ dictionary.Add(key, value);
+ continue;
+ }
+ if (IsRadioButton(t))
+ {
+ RadioButton x = (RadioButton) t;
+ string key = ToColumn(x.ID, prefix);
+ string value = (x.Checked) ? key : null;
+ dictionary.Add(key, value);
+ continue;
+ }
+ }
+ }
+
+ public void Read(ControlCollection controls, IDictionary dictionary, bool nullIfEmpty)
+ {
+ ReadControls(controls, dictionary, null, ListSuffix, nullIfEmpty);
+ }
+
+ public void ReadExecute(ControlCollection controls, IViewHelper helper, bool nullIfEmpty)
+ {
+ Read(Controls, helper.Criteria, nullIfEmpty);
+ helper.Execute();
+ }
+
+ public void ReadExecute(IViewHelper helper, bool nullIfEmpty)
+ {
+ ReadExecute(Controls, helper, nullIfEmpty);
+ }
+
+ public void ReadExecute(IViewHelper helper)
+ {
+ ReadExecute(helper, true);
+ }
+
+ public IViewHelper Read(ControlCollection controls, string command, bool nullOnEmpty)
+ {
+ IViewHelper helper = GetHelperFor(command);
+ ReadControls(controls, helper.Criteria, null, ListSuffix, nullOnEmpty);
+ return helper;
+ }
+
+ public IViewHelper Read(string command, bool nullOnEmpty)
+ {
+ return Read(Controls, command, nullOnEmpty);
+ }
+
+ public IViewHelper Read(string command)
+ {
+ return Read(Controls, command, true);
+ }
+
+ public IViewHelper ReadExecute(ControlCollection collection, string command, bool nullOnEmpty)
+ {
+ IViewHelper helper = Read(collection, command, nullOnEmpty);
+ helper.Execute();
+ return helper;
+ }
+
+ public IViewHelper ReadExecute(ControlCollection collection, string command)
+ {
+ return ReadExecute(collection, command, true);
+ }
+
+
+ public IViewHelper ReadExecute(string command, bool nullIfEmpty)
+ {
+ return ReadExecute(Controls, command, nullIfEmpty);
+ }
+
+ public IViewHelper ReadExecute(string command)
+ {
+ return ReadExecute(Controls, command, true);
+ }
+
+
+ public IViewHelper Read(string command, IDictionary criteria, bool nullIfEmpty)
+ {
+ IViewHelper helper = GetHelperFor(command);
+ helper.Read(criteria, nullIfEmpty);
+ return helper;
+ }
+
+ public IViewHelper ReadExecute(string command, IDictionary criteria)
+ {
+ return ReadExecute(command, criteria, true);
+ }
+
+ public IViewHelper ReadExecute(string command, IDictionary criteria, bool nullIfEmpty)
+ {
+ IViewHelper helper = Read(command, criteria, nullIfEmpty);
+ helper.Execute();
+ return helper;
+ }
+
+ private static string TITLE = "_title";
+ private static string LINK = "_link";
+
+ public virtual void GetMessages(ControlCollection controls)
+ {
+ foreach (Control t in controls)
+ {
+ if (IsViewLabel(t))
+ {
+ ViewLabel x = (ViewLabel) t;
+ if (x.Resource) try
+ {
+ x.Text = GetMessage(x.ID);
+ }
+ catch (Exception e)
+ {
+ if (x.Required) throw(e);
+ }
+ continue;
+ }
+ if (IsButton(t))
+ {
+ Button x = (Button) t;
+ x.Text = GetMessage(x.ID);
+ continue;
+ }
+ if (IsHyperLink(t))
+ {
+ HyperLink x = (HyperLink) t;
+ x.Text = GetMessage(x.ID + TITLE);
+ x.NavigateUrl = GetMessage(x.ID + LINK);
+ continue;
+ }
+ }
+ }
+
+ public virtual void GetMessages()
+ {
+ GetMessages(Controls);
+ }
+
+ #endregion
+
+ #region ListControl methods
+
+ /// <summary>
+ /// Select only those items in control
+ /// whose Value property matches the given value.
+ /// If the value is null, no action is taken.
+ /// </summary>
+ /// <param name="control"></param>
+ /// <param name="value"></param>
+ ///
+ protected void SelectItem(ListControl control, string value)
+ {
+ if (value != null)
+ {
+ foreach (ListItem i in control.Items)
+ i.Selected = false;
+
+ foreach (ListItem i in control.Items)
+ {
+ if (value.Equals(i.Value))
+ i.Selected = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Deactivate the selected item, and select any item matching value.
+ /// </summary>
+ /// <param name="control"></param>
+ /// <param name="value"></param>
+ ///
+ protected void SelectListItem(ListControl control, string value)
+ {
+ try
+ {
+ control.SelectedIndex = -1;
+ SelectItem(control, value);
+ }
+ catch (NullReferenceException okay)
+ {
+ if (okay==null) throw okay; // Silly, but it placates the IDE
+ }
+ }
+
+ /// <summary>
+ /// Bind a list of KeyValue objects to a ListControl,
+ /// select any item matching value.
+ /// </summary>
+ /// <param name="control">ListControl to process</param>
+ /// <param name="list">List of TextKey objects.</param>
+ /// <param name="value">Value to select, or null if nothing is selected.</param>
+ ///
+ private void BindListControl(ListControl control, IList list, string value)
+ {
+ bool insertKey = ((list != null) && (!list.Contains(NullKey)));
+ if (insertKey) list.Insert(0, NullKey);
+ control.DataTextField = KeyValue.VALUE;
+ control.DataValueField = KeyValue.KEY;
+ control.DataSource = list;
+ control.DataBind();
+ if (value!=null) SelectListItem(control, value);
+ }
+
+ protected void BindListControl(ListControl control, IList list)
+ {
+ BindListControl(control, list, null);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Signal when an error is exposed.
+ /// </summary>
+ public event EventHandler View_Alert;
+
+ /// <summary>
+ /// Pass an error to another control registered to received it.
+ /// </summary>
+ /// <param name="sender">This object</param>
+ /// <param name="e">A ViewArgs instance with the IViewHelper containing the error messages(s).</param>
+ private void View_Alert_Handler(object sender, EventArgs e)
+ {
+ if (View_Alert != null)
+ {
+ View_Alert(sender, e);
+ }
+ }
+
+ /// <summary>
+ /// Initialize the control to use the standard View_Alert event handerl.
+ /// </summary>
+ /// <param name="c">Control to register</param>
+ ///
+ protected void InitView(ViewControl c)
+ {
+ c.View_Alert += new EventHandler(View_Alert_Handler); // Bubble event
+ c.Profile = Profile;
+ }
+
+ /// <summary>
+ /// Reset state for this control, including any ViewState attributes,
+ /// usually on a new Open event or on a Quit event.
+ /// </summary>
+ /// <remarks><p>
+ /// Subclasses can override to clear any attributes manages through ViewState,
+ /// and to retain any default values that should survive a reset.
+ /// If overridden, the best practice is to call base.Page_Reset
+ /// rather than call ResetControls directly.
+ /// </p><p>
+ /// Usually, Page_Reset should *not* be called on a Save event,
+ /// since the state at Save might be needed by another component.
+ /// The typical idiom is to call Page_Reset when an Open method is passed new parameters
+ /// or on a Quit event.
+ /// </p></remarks>
+ public virtual void Page_Reset()
+ {
+ ResetControls();
+ }
+
+ /// <summary>
+ /// Signal that input was reset.
+ /// </summary>
+ ///
+ public event EventHandler View_Reset;
+
+ /// <summary>
+ /// Reset control values.
+ /// </summary>
+ ///
+ protected void reset_Click(object sender, EventArgs e)
+ {
+ Page_Reset();
+ if (View_Reset != null)
+ {
+ View_Reset(sender, e); // bubble it
+ }
+ }
+
+ /// <summary>
+ /// Automatically lookup messages for Buttons, HyperLinks, and Labels.
+ /// </summary>
+ /// <remarks><p>
+ /// Called during page Init cycle; override to change behavior or disable.
+ /// </p></remarks>
+ protected virtual void Page_Init()
+ {
+ InitViewLabels();
+ if (IsPostBack) return;
+ GetMessages();
+ }
+
+ /// <summary>
+ /// Handle the page's Load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguments</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ // Put user code to initialize the page here
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ Page_Init();
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx.resx b/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/ViewControl.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/Nexus/Web/ViewLabel.cs b/struts-sandbox/overdrive/Nexus/Web/ViewLabel.cs
new file mode 100644
index 0000000..5f21905
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/ViewLabel.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Web.UI.WebControls;
+using Nexus.Core.Helpers;
+
+namespace Nexus.Web
+{
+ /// <summary>
+ /// Present dynamic message by consulting with Message Resources
+ /// or handling an event.
+ /// </summary>
+ public class ViewLabel : Label
+ {
+ /// <summary>
+ /// Field for EntryID property.
+ /// </summary>
+ ///
+ private string _EntryID;
+
+ /// <summary>
+ /// Name of corresponding entry.
+ /// </summary>
+ /// <remarks><p>
+ /// If this is not set,
+ /// the EntryId is obtained by truncating the Suffix
+ /// from the ID.
+ /// </p></remarks>
+ public string EntryID
+ {
+ get
+ {
+ if ((_EntryID == null) || (_EntryID.Length == 0))
+ {
+ int v = ID.LastIndexOf(Suffix);
+ _EntryID = ID.Substring(0, v);
+ }
+ return _EntryID;
+ }
+ set { _EntryID = value; }
+ }
+
+ public const string MESSAGE_SUFFIX = "_msg";
+
+ /// <summary>
+ /// Field for Suffix property ["_msg"].
+ /// </summary>
+ ///
+ private string _Suffix = MESSAGE_SUFFIX;
+
+ /// <summary>
+ /// Suffix to trim from ID to obtain EntryID [MESSAGE_SUFFIX].
+ /// </summary>
+ ///
+ public string Suffix
+ {
+ get { return _Suffix; }
+ set { _Suffix = value; }
+ }
+
+ /// <summary>
+ /// Field for Resource property [TRUE].
+ /// </summary>
+ ///
+ private bool _Resource = true;
+
+ /// <summary>
+ /// If true, populate from Message Resources.
+ /// </summary>
+ ///
+ public bool Resource
+ {
+ get { return _Resource; }
+ set { _Resource = value; }
+ }
+
+ /// <summary>
+ /// Field for Required property [FALSE].
+ /// </summary>
+ ///
+ private bool _Required = false;
+
+ /// <summary>
+ /// If true, throw exception if Resource==true
+ /// and message not in resource.
+ /// </summary>
+ ///
+ public bool Required
+ {
+ get { return _Required; }
+ set { _Required = value; }
+ }
+
+ /// <summary>
+ /// Field for View_Hint property [TRUE].
+ /// </summary>
+ ///
+ private bool _View_Hint = true;
+
+ /// <summary>
+ /// If true, register for View_Alert event
+ /// and display any alert for corresponding field.
+ /// </summary>
+ ///
+ public bool View_Hint
+ {
+ get { return _View_Hint; }
+ set { _View_Hint = value; }
+ }
+
+ /// <summary>
+ /// Field for View_Alert property [TRUE].
+ /// </summary>
+ ///
+ private bool _View_Alert = true;
+
+ /// <summary>
+ /// If true, register for View_Hint event
+ /// and display any hint for corresponding field.
+ /// </summary>
+ ///
+ public bool View_Alert
+ {
+ get { return _View_Alert; }
+ set { _View_Alert = value; }
+ }
+
+ /// <summary>
+ /// Present a list of error mesasges.
+ /// </summary>
+ ///
+ protected IViewHelper Alerts
+ {
+ set
+ {
+ if (value != null)
+ {
+ Text = value.AlertsFor(EntryID);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provide a standard Event Handler for passing Alert messages.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ public void View_Alert_Handler(object sender, EventArgs e)
+ {
+ ViewArgs v = e as ViewArgs;
+ if (v == null) throw new ArgumentException("ViewLabel.View_Alert_Handler: !(e is ViewArgs)");
+ IViewHelper helper = v.Helper;
+ if (helper != null) Alerts = helper;
+ else throw new ArgumentException("ViewLabel.View_Alert_Handler: (e.helper==null)");
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/Web/Web.config b/struts-sandbox/overdrive/Nexus/Web/Web.config
new file mode 100644
index 0000000..5fdfc70
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Web.config
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+
+ <system.web>
+
+ <!-- DYNAMIC DEBUG COMPILATION
+ Set compilation debug="true" to enable ASPX debugging. Otherwise, setting this value to
+ false will improve runtime performance of this application.
+ Set compilation debug="true" to insert debugging symbols (.pdb information)
+ into the compiled page. Because this creates a larger file that executes
+ more slowly, you should set this value to true only when debugging and to
+ false at all other times. For more information, refer to the documentation about
+ debugging ASP.NET files.
+ -->
+ <compilation
+ defaultLanguage="c#"
+ debug="true"
+ />
+
+ <!-- CUSTOM ERROR MESSAGES
+ Set customErrors mode="On" or "RemoteOnly" to enable custom error messages, "Off" to disable.
+ Add <error> tags for each of the errors you want to handle.
+
+ "On" Always display custom (friendly) messages.
+ "Off" Always display detailed ASP.NET error information.
+ "RemoteOnly" Display custom (friendly) messages only to users not running
+ on the local Web server. This setting is recommended for security purposes, so
+ that you do not display application detail information to remote clients.
+ -->
+ <customErrors
+ mode="RemoteOnly"
+ />
+
+ <!-- AUTHENTICATION
+ This section sets the authentication policies of the application. Possible modes are "Windows",
+ "Forms", "Passport" and "None"
+
+ "None" No authentication is performed.
+ "Windows" IIS performs authentication (Basic, Digest, or Integrated Windows) according to
+ its settings for the application. Anonymous access must be disabled in IIS.
+ "Forms" You provide a custom form (Web page) for users to enter their credentials, and then
+ you authenticate them in your application. A user credential token is stored in a cookie.
+ "Passport" Authentication is performed via a centralized authentication service provided
+ by Microsoft that offers a single logon and core profile services for member sites.
+ -->
+ <authentication mode="Windows" />
+
+ <!-- AUTHORIZATION
+ This section sets the authorization policies of the application. You can allow or deny access
+ to application resources by user or role. Wildcards: "*" mean everyone, "?" means anonymous
+ (unauthenticated) users.
+ -->
+
+ <authorization>
+ <allow users="*" /> <!-- Allow all users -->
+ <!-- <allow users="[comma separated list of users]"
+ roles="[comma separated list of roles]"/>
+ <deny users="[comma separated list of users]"
+ roles="[comma separated list of roles]"/>
+ -->
+ </authorization>
+
+ <!-- APPLICATION-LEVEL TRACE LOGGING
+ Application-level tracing enables trace log output for every page within an application.
+ Set trace enabled="true" to enable application trace logging. If pageOutput="true", the
+ trace information will be displayed at the bottom of each page. Otherwise, you can view the
+ application trace log by browsing the "trace.axd" page from your web application
+ root.
+ -->
+ <trace
+ enabled="false"
+ requestLimit="10"
+ pageOutput="false"
+ traceMode="SortByTime"
+ localOnly="true"
+ />
+
+ <!-- SESSION STATE SETTINGS
+ By default ASP.NET uses cookies to identify which requests belong to a particular session.
+ If cookies are not available, a session can be tracked by adding a session identifier to the URL.
+ To disable cookies, set sessionState cookieless="true".
+ -->
+ <sessionState
+ mode="InProc"
+ stateConnectionString="tcpip=127.0.0.1:42424"
+ sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
+ cookieless="false"
+ timeout="20"
+ />
+
+ <!-- GLOBALIZATION
+ This section sets the globalization settings of the application.
+ -->
+ <globalization
+ requestEncoding="utf-8"
+ responseEncoding="utf-8"
+ />
+
+ </system.web>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity
+ name="log4net"
+ publicKeyToken="b32731d11ce58905"
+ culture="neutral"/>
+ <bindingRedirect
+ oldVersion="1.2.0.30714"
+ newVersion="1.2.9.0"/>
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+
+</configuration>
diff --git a/struts-sandbox/overdrive/Nexus/Web/Web.csproj b/struts-sandbox/overdrive/Nexus/Web/Web.csproj
new file mode 100644
index 0000000..5bdc856
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Web.csproj
@@ -0,0 +1,241 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Web"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{2BD7CDE0-01F7-4CC5-9AE9-2F9470FB7007}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "Nexus.Web"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Flow"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = "$(SolutionDir)postbuild.bat $(TargetDir) $(TargetName) $(SolutionName) $(SolutionDir)"
+ RootNamespace = "Nexus.Web"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "false"
+ OutputPath = "bin\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Drawing"
+ AssemblyName = "System.Drawing"
+ HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.Web"
+ AssemblyName = "System.Web"
+ HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Web.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "Core"
+ Project = "{7C8CAFD4-1E45-41B4-9963-F51199B12EA7}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ <Reference
+ Name = "Spring.Web"
+ AssemblyName = "Spring.Web"
+ HintPath = "..\..\..\local-cache\SpringNet\Spring.Web.dll"
+ />
+ <Reference
+ Name = "Spring.Core"
+ AssemblyName = "Spring.Core"
+ HintPath = "..\..\..\local-cache\SpringNet\Spring.Core.dll"
+ />
+ <Reference
+ Name = "Agility.Core"
+ AssemblyName = "Agility.Core"
+ HintPath = "..\..\..\local-cache\Agility\Agility.Core.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AlertLabel.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "FindControl.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "FindControl.ascx.cs"
+ DependentUpon = "FindControl.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "FindControl.ascx.resx"
+ DependentUpon = "FindControl.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Global.asax"
+ SubType = "Component"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Global.asax.cs"
+ DependentUpon = "Global.asax"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Global.asax.resx"
+ DependentUpon = "Global.asax.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "GridControl.ascx"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "GridControl.ascx.cs"
+ DependentUpon = "GridControl.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "GridControl.ascx.resx"
+ DependentUpon = "GridControl.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "HintLabel.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "IViewControl.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Messages.resx"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "TextLabel.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "ViewControl.ascx"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "ViewControl.ascx.cs"
+ DependentUpon = "ViewControl.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "ViewControl.ascx.resx"
+ DependentUpon = "ViewControl.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "ViewLabel.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Web.config"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "WebHelper.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\LetterFilter.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\LetterFilter.ascx.cs"
+ DependentUpon = "LetterFilter.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\LetterFilter.ascx.resx"
+ DependentUpon = "LetterFilter.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/Nexus/Web/Web.csproj.webinfo b/struts-sandbox/overdrive/Nexus/Web/Web.csproj.webinfo
new file mode 100644
index 0000000..0aef5d2
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/Web.csproj.webinfo
@@ -0,0 +1,4 @@
+<VisualStudioUNCWeb>
+ <Web URLPath = "http://localhost/Nexus/Web.csproj" />
+</VisualStudioUNCWeb>
+
diff --git a/struts-sandbox/overdrive/Nexus/Web/WebHelper.cs b/struts-sandbox/overdrive/Nexus/Web/WebHelper.cs
new file mode 100644
index 0000000..e9e7e01
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/Web/WebHelper.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections;
+using System.Text;
+using Nexus.Core.Helpers;
+
+namespace Nexus.Web
+{
+ public class WebHelper : ViewHelper
+ {
+ public override string AlertsFor(string id)
+ {
+ string alert = null;
+ IList list = Alerts[id] as IList;
+ if (list == null) return alert;
+
+ if (list.Count == 1)
+ {
+ alert = HtmlMessage(list[0]);
+ }
+ else
+ {
+ alert = HtmlMessageList(list);
+ }
+ return alert;
+ }
+
+ /**
+ * Return Fault messages in HTML format.
+ */
+ private string FaultMessages()
+ {
+ Exception e = Fault;
+ StringBuilder fault = new StringBuilder("[");
+ fault.Append(e.Message);
+ fault.Append("] ");
+ fault.Append(e.Source);
+ fault.Append(e.StackTrace);
+ return HtmlMessage(fault.ToString());
+ }
+
+ public override string AlertsText
+ {
+ get
+ {
+ if (HasFault)
+ {
+ string field_messages = HtmlMessageBuilder(Alerts);
+ StringBuilder alerts = new StringBuilder(field_messages);
+ alerts.Append(FaultMessages());
+ return alerts.ToString();
+ }
+ else
+ {
+ return HtmlMessageBuilder(Alerts);
+ }
+ }
+ }
+
+ public override string HintsFor(string id)
+ {
+ return HtmlMessageList(Hints[id] as IList);
+ }
+
+ public override string HintsText
+ {
+ get { return HtmlMessageBuilder(Hints); }
+ }
+
+ #region Message utilities
+
+ /// <summary>
+ /// Build a message using HTML markup.
+ /// </summary>
+ /// <param name="message">A message</param>
+ /// <returns>HTML markup presenting the messages.</returns>
+ ///
+ private string HtmlMessage(object message)
+ {
+ if (message==null) return null;
+ StringBuilder sb = new StringBuilder("<p>");
+ sb.Append(message.ToString());
+ sb.Append("</p>");
+ return sb.ToString();
+ }
+
+ /// <summary>
+ /// Build a set of messages using HTML markup.
+ /// </summary>
+ /// <param name="messages">A list of messages</param>
+ /// <returns>HTML markup presenting the messages.</returns>
+ ///
+ private string HtmlMessageList(IList messages)
+ {
+ StringBuilder sb = new StringBuilder("<ul>");
+ foreach (object o in messages)
+ {
+ sb.Append("<li>");
+ sb.Append(o.ToString());
+ sb.Append("</li>");
+ }
+ sb.Append("</ul>");
+
+ return sb.ToString();
+ }
+
+ /// <summary>
+ /// Build a set error messages using HTML markup.
+ /// </summary>
+ /// <param name="store">A context listing errors, if any</param>
+ /// <returns>HTML markup presenting the errors.</returns>
+ ///
+ private string HtmlMessageBuilder(IDictionary store)
+ {
+ string messageMarkup = null;
+ if (store != null)
+ {
+ IList messages = new ArrayList();
+ ICollection keys = store.Keys;
+ foreach (string key in keys)
+ {
+ IList sublist = store[key] as IList;
+ foreach (string message in sublist) messages.Add(message);
+ }
+ messageMarkup = HtmlMessageList(messages);
+ }
+
+ if (messageMarkup != null)
+ {
+ StringBuilder sb = new StringBuilder(messageMarkup);
+ return sb.ToString();
+ }
+ return null;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/Nexus/postbuild.bat b/struts-sandbox/overdrive/Nexus/postbuild.bat
new file mode 100644
index 0000000..78e0f9a
--- /dev/null
+++ b/struts-sandbox/overdrive/Nexus/postbuild.bat
@@ -0,0 +1,3 @@
+REM %LOCAL_CACHE% doesn't work.
+CD %4
+COPY %1%2.* ..\local-cache\%3
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/App.cs b/struts-sandbox/overdrive/PhoneBook/Core/App.cs
new file mode 100644
index 0000000..2a47d80
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/App.cs
@@ -0,0 +1,205 @@
+/*
+* Copyright 2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Tokens representing context keys.
+ /// </summary>
+ ///
+ public class App
+ {
+ private App()
+ {
+ // No need to construct static helper class
+ }
+
+ #region Properties
+
+ /// <summary>
+ /// Token for Catalog property.
+ /// </summary>
+ ///
+ public const string CATALOG_KEY = "Catalog";
+
+ /// <summary>
+ /// Token for entry_key property.
+ /// </summary>
+ ///
+ public const string ENTRY_KEY = "entry_key";
+
+ /// <summary>
+ /// Token for first_name property.
+ /// </summary>
+ ///
+ public const string FIRST_NAME = "first_name";
+
+ /// <summary>
+ /// Token for last_name property.
+ /// </summary>
+ ///
+ public const string LAST_NAME = "last_name";
+
+ /// <summary>
+ /// Token for user_name property.
+ /// </summary>
+ ///
+ public const string USER_NAME = "user_name";
+
+ /// <summary>
+ /// Token for extension property.
+ /// </summary>
+ ///
+ public const string EXTENSION = "extension";
+
+ /// <summary>
+ /// Token for hired property.
+ /// </summary>
+ ///
+ public const string HIRED = "hired";
+
+ /// <summary>
+ /// Token for hours property.
+ /// </summary>
+ ///
+ public const string HOURS = "hours";
+
+ /// <summary>
+ /// Token for editor property.
+ /// </summary>
+ ///
+ public const string EDITOR = "editor";
+
+ #endregion
+
+ #region Commands
+
+ public const string FROM_DATE = "from_date";
+
+ public const string THRU_DATE = "thru_date";
+
+ /// <summary>
+ /// Token for SQL LIMIT clause.
+ /// </summary>
+ ///
+ public const string ITEM_LIMIT = "item_limit";
+
+ /// <summary>
+ /// Token for SQL OFFSET clause.
+ /// </summary>
+ ///
+ public const string ITEM_OFFSET = "item_offset";
+
+ /// <summary>
+ /// Token for SQL COUNT clause.
+ /// </summary>
+ ///
+ public const string ITEM_COUNT = "item_count";
+
+ /// <summary>
+ /// Token for select one command.
+ /// </summary>
+ ///
+ public const string ENTRY = "entry";
+
+ /// <summary>
+ /// Token for list all command.
+ /// </summary>
+ ///
+ public const string ENTRY_LIST = "entry_list";
+
+ /// <summary>
+ /// Token for Entry Initial command.
+ /// </summary>
+ ///
+ public const string ENTRY_INITIAL = "entry_initial";
+
+ /// <summary>
+ /// Token for List Last Names command.
+ /// </summary>
+ ///
+ public const string LAST_NAME_LIST = "last_name_list";
+
+ /// <summary>
+ /// Token for List Last Names command.
+ /// </summary>
+ ///
+ public const string FIRST_NAME_LIST = "first_name_list";
+
+ /// <summary>
+ /// Token for List Extensions command.
+ /// </summary>
+ ///
+ public const string EXTENSION_LIST = "extension_list";
+
+ /// <summary>
+ /// Token for List UserNames command.
+ /// </summary>
+ ///
+ public const string USER_NAME_LIST = "user_name_list";
+
+ /// <summary>
+ /// Token for List Hire Dates command.
+ /// </summary>
+ ///
+ public const string HIRED_LIST = "hired_list";
+
+ /// <summary>
+ /// Token for List Hours command.
+ /// </summary>
+ ///
+ public const string HOURS_LIST = "hours_list";
+
+ /// <summary>
+ /// Token for Entry Find command.
+ /// </summary>
+ ///
+ public const string ENTRY_FIND = "entry_find";
+
+ /// <summary>
+ /// Token for Entry Save command.
+ /// </summary>
+ ///
+ public const string ENTRY_SAVE = "entry_save";
+
+ /// <summary>
+ /// Token for Entry Delete command.
+ /// </summary>
+ ///
+ public const string ENTRY_DELETE = "entry_delete";
+
+ #endregion
+
+ #region Messages
+
+ /// <summary>
+ /// Token for Directory page title.
+ /// </summary>
+ public const string DIRECTORY_TITLE = "directory_title";
+
+ /// <summary>
+ /// Token for Directory directory page heading.
+ /// </summary>
+ public const string DIRECTORY_HEADING = "directory_heading";
+
+ /// <summary>
+ /// Token for Directory page prompt.
+ /// </summary>
+ public const string DIRECTORY_PROMPT = "directory_prompt";
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/AppEntry.cs b/struts-sandbox/overdrive/PhoneBook/Core/AppEntry.cs
new file mode 100644
index 0000000..667b70b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/AppEntry.cs
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use _Store file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Expose field attributes as public properties.
+ /// </summary>
+ ///
+ [Serializable]
+ public class AppEntry : EntryDictionary
+ {
+
+ public AppEntry()
+ {
+ // Default contstructor
+ }
+
+ public AppEntry(IDictionary sources)
+ {
+ AddAll(sources);
+ }
+
+ public AppEntry(AppEntry row)
+ {
+ AddAll(row);
+ }
+
+ /// <summary>
+ /// Add each source entry to our internal store.
+ /// </summary>
+ /// <remarks><p>
+ /// Entries with keys that match the property names will be exposed.
+ /// Other entries may be added, but can only be retrieved via Get.
+ /// </p></remarks>
+ /// <param name="row">Entries to add</param>
+ ///
+ public void AddAll(AppEntry row)
+ {
+ ICollection keys = row.Keys;
+ foreach (string key in keys)
+ {
+ Add(key, row.Get(key));
+ }
+ }
+
+ /*
+ public string Property
+ {
+ get { return Get(App.PROPERTY); }
+ set { Set(App.PROPERTY, value); }
+ }
+ */
+
+ public string entry_key
+ {
+ get { return Get(App.ENTRY_KEY); }
+ set { Set(App.ENTRY_KEY, value); }
+ }
+
+ public string first_name
+ {
+ get { return Get(App.FIRST_NAME); }
+ set { Set(App.FIRST_NAME, value); }
+ }
+
+ public string last_name
+ {
+ get { return Get(App.LAST_NAME); }
+ set { Set(App.LAST_NAME, value); }
+ }
+
+ public string extension
+ {
+ get { return Get(App.EXTENSION); }
+ set { Set(App.EXTENSION, value); }
+ }
+
+ public string user_name
+ {
+ get { return Get(App.USER_NAME); }
+ set { Set(App.USER_NAME, value); }
+ }
+
+ public string hired
+ {
+ get { return Get(App.HIRED); }
+ set { Set(App.HIRED, value); }
+ }
+
+ public string hours
+ {
+ get { return Get(App.HOURS); }
+ set { Set(App.HOURS, value); }
+ }
+
+ public string editor
+ {
+ get { return Get(App.EDITOR); }
+ set { Set(App.EDITOR, value); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/AppEntryList.cs b/struts-sandbox/overdrive/PhoneBook/Core/AppEntryList.cs
new file mode 100644
index 0000000..82ea8c6
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/AppEntryList.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Implement Nexus.Core.IEntryList for AppEntry objects.
+ /// </summary>
+ ///
+ public class AppEntryList : ArrayList, IEntryList
+ {
+ public object Insert(string key)
+ {
+ AppEntry entry = new AppEntry();
+ entry.entry_key = key;
+ Insert(0, entry);
+ return entry;
+ }
+
+ public void AddEntry(IDictionary row)
+ {
+ AppEntry entry = new AppEntry();
+ foreach (DictionaryEntry col in row)
+ {
+ string key = Convert.ToString(col.Key);
+ string value = Convert.ToString(col.Value);
+ entry.Add(key, value);
+ }
+ Add(entry);
+ }
+
+ public AppEntry[] ToAppEntryArray()
+ {
+ return (AppEntry[])ToArray(typeof(AppEntry));
+ }
+ }
+}
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/AppEntryListProcessor.cs b/struts-sandbox/overdrive/PhoneBook/Core/AppEntryListProcessor.cs
new file mode 100644
index 0000000..f9f8e38
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/AppEntryListProcessor.cs
@@ -0,0 +1,17 @@
+using Nexus.Core;
+using Nexus.Core.Validators;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Implement Nexus.Core.Validators.EntryListProcess for AppEntryList.
+ /// </summary>
+ ///
+ public class AppEntryListProcessor : EntryListProcessor
+ {
+ public override IEntryList NewEntryList()
+ {
+ return new AppEntryList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/AppUserProfile.cs b/struts-sandbox/overdrive/PhoneBook/Core/AppUserProfile.cs
new file mode 100644
index 0000000..0d0dac8
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/AppUserProfile.cs
@@ -0,0 +1,84 @@
+using System.Security.Principal;
+using System.Text;
+using Nexus.Core.Profile;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Extend UserProfile to include properties specific to this application,
+ /// such as IsEditor.
+ /// </summary>
+ ///
+ public class AppUserProfile : UserProfile
+ {
+ /// <summary>
+ /// Provide a field for IsEditor property.
+ /// </summary>
+ private bool _IsEditor = false;
+
+ /// <summary>
+ /// Indicate whether user has editing priveleges.
+ /// </summary>
+ ///
+ public bool IsEditor
+ {
+ get { return _IsEditor; }
+ set { _IsEditor = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for Entry property.
+ /// </summary>
+ ///
+ private AppEntry _Entry;
+
+
+ /// <summary>
+ /// Record directory entry for user.
+ /// </summary>
+ ///
+ public AppEntry Entry
+ {
+ get { return _Entry; }
+ set
+ {
+ _Entry = value;
+ if (_Entry != null)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(_Entry.first_name);
+ sb.Append(" ");
+ sb.Append(Entry.last_name);
+ FullName = sb.ToString().Trim();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provide a field for FullName property.
+ /// </summary>
+ ///
+ private string _FullName;
+
+ /// <summary>
+ /// Record the user's full name (first and last names).
+ /// </summary>
+ ///
+ public string FullName
+ {
+ get { return _FullName; }
+ set { _FullName = value; }
+ }
+
+ /// <summary>
+ /// Instantiate from an IIdentity.
+ /// </summary>
+ /// <param name="id">Identity to copy for this profile.</param>
+ ///
+ public AppUserProfile(IIdentity id)
+ {
+ Principal = new UserPrincipal(id);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/AssemblyInfo.cs b/struts-sandbox/overdrive/PhoneBook/Core/AssemblyInfo.cs
new file mode 100644
index 0000000..05af947
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/AppCommand.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/AppCommand.cs
new file mode 100644
index 0000000..72ddd9a
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/AppCommand.cs
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using IBatisNet.DataMapper;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Extend RequestCommand with data access methods.
+ /// </summary>
+ ///
+ public abstract class BaseMapper : RequestCommand
+ {
+ /// <summary>
+ /// Provide a field for Mapper property.
+ /// </summary>
+ ///
+ private SqlMapper _Mapper;
+
+ /// <summary>
+ /// Expose a preconfigured SqlMapper instance that Commands can use to run statements.
+ /// </summary>
+ /// <remarks><p>
+ /// Commands use Mapper to invoke SqlMap statements, such as
+ /// <code>
+ /// object row = Mapper.QueryForObject (QueryID, context);
+ /// </code>.
+ /// </p><p>
+ /// Any SqlMapper API method may be called.
+ /// </p><p>
+ /// The default behavior of BAseNexusCommand is to use the
+ /// command ID if the QueryID is null.
+ /// </p></remarks>
+ /// <returns>Preconfigured Mapper instance</returns>
+ ///
+ public SqlMapper Mapper
+ {
+ get { return _Mapper; }
+ set { _Mapper = value; }
+
+ }
+
+ /// <summary>
+ /// Indicate whether string is null or zero length.
+ /// </summary>
+ /// <param name="input">Input to validate</param>
+ /// <returns>True if string is nyull or zero length</returns>
+ ///
+ public bool IsEmpty(string input)
+ {
+ return ((input == null) || (input.Equals(String.Empty)));
+ }
+
+ /// <summary>
+ /// Create new Global Universal Identifer as a formatted string.
+ /// </summary>
+ /// <returns>String representing a new GUID</returns>
+ /// <remarks><p>
+ /// No two calls to this method will ever return duplicate strings.
+ /// </p></remarks>
+ ///
+ public string GuidString()
+ {
+ Guid guid = Guid.NewGuid();
+ string gs = guid.ToString();
+ return gs;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseCommand.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseCommand.cs
new file mode 100644
index 0000000..109f9ea
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseCommand.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Text;
+using Agility.Core;
+using IBatisNet.DataMapper;
+using Nexus.Core;
+using Spring.Objects.Factory;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Provide an abtract extension of BaseNexusCommand
+ /// with shared members for WNE Commands,
+ /// including a SqlMapper factory method.
+ /// </summary>
+ /// <remarks><p>
+ /// Superclasses must implement a NexusExecute method (inherited from BaseNexusCommand.
+ /// </p><p>
+ /// Concrete subclasses are expected to be created by a IOC Container, like Spring.NET.
+ /// Most concrete subclasses will be "decorator" classes designed to behave
+ /// differently based on what properties are set when the class is created.
+ /// Others may be custom classes with predefined behaviors.
+ /// </p><p>
+ /// The Spring catalog provides the versatility we need to mix-and-match
+ /// base commands with custom commands, as needed,
+ /// and call either from the client in exactly the same way.
+ /// </p><p>
+ /// NOTE that subclasses should NOT use the Outcome property of
+ /// the Nexus context since they may be subcommands in a Chain.
+ /// All BaseCommands should use the idiom
+ /// <code>context[ID] = object</code>
+ /// to store output.
+ /// </p><p>
+ /// NOTE after using the ReShaper code reformatter,
+ /// the Mapper method needs to be edited.
+ /// ReSharper removes an absolute reference that we actually need.
+ /// (Our Mapper method calls the IBatisNet Mapper method.)
+ /// The correct line of code is maintained as a comment,
+ /// so that it can <b>copied</b> over the reformatted version.
+ /// </p></remarks>
+ public abstract class BaseCommand : RequestCommand, IObjectNameAware
+ {
+ /// <summary>
+ /// If an ID is not provided, default to the ObjectName.
+ /// </summary>
+ public override string ID
+ {
+ get
+ {
+ string _ID = base.ID;
+ if (null == _ID) return ObjectName;
+ else return _ID;
+ }
+ set { base.ID = value; }
+ }
+
+ private string _ObjectName;
+
+ /// <summary>
+ /// Provide a field for the Spring object name (set by Spring).
+ /// </summary>
+ public string ObjectName
+ {
+ get { return _ObjectName; }
+ set { _ObjectName = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for the Remark property.
+ /// </summary>
+ private string _Remark;
+
+ /// <summary>
+ /// Accept an arbitrary comment about a command
+ /// -- more for use in the XML document.
+ /// </summary>
+ ///
+ public string Remark
+ {
+ get { return _Remark; }
+ set { _Remark = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for the Mapper property.
+ /// </summary>
+ ///
+ private SqlMapper _Mapper;
+
+ /// <summary>
+ /// Expose a preconfigured SqlMapper instance that Commands can use to run statements.
+ /// </summary>
+ /// <remarks><p>
+ /// Commands use Mapper to invoke SqlMap statements, such as
+ /// <code>
+ /// object row = Mapper ().QueryForObject (QueryID, context);
+ /// </code>.
+ /// </p><p>
+ /// Any SqlMapper API method may be called.
+ /// </p><p>
+ /// The default behavior of BAseNexusCommand is to use the
+ /// command ID if the QueryID is null.
+ /// </p></remarks>
+ /// <returns>Preconfigured Mapper</returns>
+ ///
+ public SqlMapper Mapper
+ {
+ get { return _Mapper; }
+ set { _Mapper = value; }
+ }
+
+ /// <summary>
+ /// Indicate whether string is null or zero length.
+ /// </summary>
+ /// <param name="input">Input to validate</param>
+ /// <returns>True if string is nyull or zero length</returns>
+ ///
+ protected bool IsEmpty(string input)
+ {
+ return ((input == null) || (input.Equals(String.Empty)));
+ }
+
+ /// <summary>
+ /// Create new Global Universal Identifer as a formatted string.
+ /// </summary>
+ /// <returns>String representing a new GUID</returns>
+ /// <remarks><p>
+ /// No two calls to this method will ever return duplicate strings.
+ /// </p></remarks>
+ ///
+ protected string GuidString()
+ {
+ Guid guid = Guid.NewGuid();
+ string gs = guid.ToString();
+ return gs;
+ }
+
+ /// <summary>
+ /// Document the wildcard character used by SQL queries.
+ /// </summary>
+ public const string WILDCARD = "%";
+
+ /// <summary>
+ /// Prepare an attribute for use with a SQL wildcard ("LIKE") operation.
+ /// </summary>
+ /// <remarks><p>
+ /// A wildcard is prepended and appended for a full, scan-across match,
+ /// so that the string will found in any part of the field.
+ /// </p></remarks>
+ /// <param name="context">Context with attribute to escape</param>
+ /// <param name="id">Name of attribute to escape</param>
+ protected void LikeMe(IContext context, string id)
+ {
+ string param = context[id] as string;
+ if (null != param)
+ {
+ StringBuilder sb = new StringBuilder(WILDCARD);
+ sb.Append(param);
+ sb.Append(WILDCARD);
+ context[id] = sb.ToString();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseCount.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseCount.cs
new file mode 100644
index 0000000..8540d9e
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseCount.cs
@@ -0,0 +1,17 @@
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Invoke a query that returns the count of a result set.
+ /// </summary>
+ public class BaseCount : BaseMapper
+ {
+ public override bool RequestExecute(IRequestContext context)
+ {
+ object result = Mapper.QueryForObject(QueryID, context);
+ context[App.ITEM_COUNT] = result;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseEntry.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseEntry.cs
new file mode 100644
index 0000000..5e4ba83
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseEntry.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Execute database statement indicated by QueryID
+ /// for a single object,
+ /// returning each attribute in the main context.
+ /// </summary>
+ ///
+ public class BaseEntry : BaseMapper
+ {
+ public override bool RequestExecute(IRequestContext context)
+ {
+ object o = Mapper.QueryForObject(QueryID, context);
+ context[ID] = o;
+ IDictionary entry = o as IDictionary;
+ foreach (DictionaryEntry e in entry)
+ {
+ context[e.Key] = e.Value;
+ }
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseFilterList.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseFilterList.cs
new file mode 100644
index 0000000..5774b59
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseFilterList.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Execute database statement indicated by QueryID
+ /// and wrap result in KeyValue objects
+ /// so that lists can be displayed by standard methods.
+ /// </summary>
+ ///
+ public class BaseFilterList : BaseMapper
+ {
+ public override bool RequestExecute(IRequestContext context)
+ {
+ IList rows = Mapper.QueryForList(QueryID, null);
+ IKeyValueList list = new KeyValueList();
+ foreach (object key in rows)
+ {
+ list.Add(new KeyValue(key.ToString(), key));
+ }
+ context[ID] = list;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseList.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseList.cs
new file mode 100644
index 0000000..ee91d82
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseList.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections;
+using Nexus.Core;
+using PhoneBook.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Run the select query indicated by QueryID,
+ /// first escaping any LikeIDs and extending any date ranges,
+ /// and return the result as an IList,
+ /// </summary>
+ public class BaseList : BaseCommand
+ {
+ private IList _LikeIDs = null;
+
+ /// <summary>
+ /// Names of key fields to escape for a "like" search.
+ /// </summary>
+ public IList LikeIDs
+ {
+ get { return _LikeIDs; }
+ set { _LikeIDs = value; }
+ }
+
+ /// <summary>
+ /// Generate an array from the IDs.
+ /// </summary>
+ /// <returns>Array of LikeIDs</returns>
+ protected string[] GetArray(string IDs)
+ {
+ string csv = IDs;
+ bool noLike = ((null == csv) || (string.Empty.Equals(csv)));
+ if (noLike)
+ return new string[0];
+ else
+ {
+ string[] _Array = csv.Split(',');
+ return _Array;
+ }
+ }
+
+ /// <summary>
+ /// Document the last second of the day
+ /// so as to calculate values for concepts like today and tomorrow.
+ /// </summary>
+ private string LAST_TICK = " 23:59";
+
+ /// <summary>
+ /// If ThruDate is set to the minimum time (00:00),
+ /// set to the maximum time instead (23:59).
+ /// </summary>
+ /// <param name="context"></param>
+ private void ExtendThruDate(IRequestContext context)
+ {
+ bool have = context.Contains(App.THRU_DATE);
+ if (!have) return;
+ DateTime thruDate = DateTime.MinValue;
+ try
+ {
+ thruDate = (DateTime) context[App.THRU_DATE];
+ }
+ catch (Exception e)
+ {
+ if (e != null) return; // Placate Resharper
+ }
+ bool defaultTime = (thruDate.Hour == 0) && (thruDate.Minute == 0) && (thruDate.Second == 0) &&
+ (thruDate.Millisecond == 0);
+ if (defaultTime)
+ {
+ string strThruDate = thruDate.ToShortDateString() + LAST_TICK;
+ DateTime newThruDate = Convert.ToDateTime(strThruDate);
+ context.Remove(App.THRU_DATE);
+ context.Add(App.THRU_DATE, newThruDate);
+ }
+ }
+
+ /// <summary>
+ /// Prepare special attributes for the query.
+ /// </summary>
+ /// <param name="context">The context we are processing</param>
+ protected void PreProcess(IRequestContext context)
+ {
+ // Escape any "like" fields
+ IList likes = LikeIDs;
+ if (likes != null)
+ {
+ IEnumerator e = likes.GetEnumerator();
+ while (e.MoveNext())
+ LikeMe(context, e.Current as string);
+ }
+
+ // Extend any "thru_date" to midnight
+ ExtendThruDate(context);
+
+ // Ensure that list_item and list_offset are numeric
+ object limit = context[App.ITEM_LIMIT];
+ if (limit != null)
+ {
+ context[App.ITEM_LIMIT] = Convert.ToInt32(limit);
+ object offset = context[App.ITEM_OFFSET];
+ context[App.ITEM_OFFSET] = Convert.ToInt32(offset);
+ }
+ }
+
+ /// <summary>
+ /// Provide a default, convenience implementation that will run a "QueryForList"
+ /// using a data mapping statement of the same ID as the Command;
+ /// override as needed.
+ /// </summary>
+ /// <param name="context">The INexusContext we are processing.</param>
+ /// <returns>CONTINUE, if an Exception is not thrown.</returns>
+ public override bool RequestExecute(IRequestContext context)
+ {
+ PreProcess(context);
+
+ IList rows = Mapper.QueryForList(QueryID, context);
+ context[ID] = rows;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseSave.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseSave.cs
new file mode 100644
index 0000000..081fdac
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/BaseSave.cs
@@ -0,0 +1,92 @@
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Store an entity for future reference.
+ /// </summary>
+ ///
+ public class BaseSave : BaseMapper
+ {
+ /// <summary>
+ /// Provide a field for KeyID property.
+ /// </summary>
+ ///
+ private string _KeyID = null;
+
+ /// <summary>
+ /// Record the unique identifier for the entity.
+ /// </summary>
+ ///
+ public string KeyID
+ {
+ get { return _KeyID; }
+ set { _KeyID = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for InsertID property.
+ /// </summary>
+ private string _InsertID = null;
+
+ /// <summary>
+ /// Record the name of the "insert" mapping for the entity.
+ /// </summary>
+ ///
+ public string InsertID
+ {
+ get { return _InsertID; }
+ set { _InsertID = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for UpdateID property.
+ /// </summary>
+ ///
+ private string _UpdateID = null;
+
+ /// <summary>
+ /// Record the name of the "update" mapping for the entity.
+ /// </summary>
+ ///
+ public string UpdateID
+ {
+ get { return _UpdateID; }
+ set { _UpdateID = value; }
+ }
+
+ /// <summary>
+ /// Insert or update an entity to the persistent store.
+ /// </summary>
+ /// <remark><p>
+ /// If the "fieldID" is empty, use the insertID statement,
+ /// otherwise, use the updateID statement.
+ /// </p></remark>
+ /// <param name="context">The INexusContext we are processing.</param>
+ /// <param name="fieldID">The name of the key field.</param>
+ /// <param name="insertID">The name of the "insert" mapping for the Entity.</param>
+ /// <param name="updateID">The name of the "update" mapping for the Entity.</param>
+ /// <returns>False</returns>
+ ///
+ protected bool Save(IRequestContext context, string fieldID, string insertID, string updateID)
+ {
+ bool insert = IsEmpty(context[fieldID] as string);
+
+ if (insert)
+ {
+ context[fieldID] = GuidString();
+ Mapper.Insert(insertID, context);
+ }
+ else
+ Mapper.Update(updateID, context);
+
+ return CONTINUE;
+ }
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ return Save(context, KeyID, InsertID, UpdateID);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Commands/EntryInitial.cs b/struts-sandbox/overdrive/PhoneBook/Core/Commands/EntryInitial.cs
new file mode 100644
index 0000000..a3083b0
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Commands/EntryInitial.cs
@@ -0,0 +1,46 @@
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Create list of initial letters for Facility Names.
+ /// </summary>
+ public class EntryInitial : BaseMapper
+ {
+ /// <summary>
+ /// Document token representing match all entries.
+ /// </summary>
+ public const string ALL = "[*]";
+
+ /// <summary>
+ /// Document the wildcard character used by SQL queries.
+ /// </summary>
+ public const string WILDCARD = "%";
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ const string ZERO = "0";
+
+ string[] input = {
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y", "Z"
+ };
+
+ IList output = new ArrayList(26);
+
+ foreach (string letter in input)
+ {
+ string initial = letter + WILDCARD;
+ object result = Mapper.QueryForObject(QueryID, initial);
+ if (ZERO.Equals(result)) continue;
+ output.Add(letter);
+ }
+
+ output.Add(ALL);
+ context.Outcome = output;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Core.csproj b/struts-sandbox/overdrive/PhoneBook/Core/Core.csproj
new file mode 100644
index 0000000..ad95fb0
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Core.csproj
@@ -0,0 +1,195 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{3150F3E8-9A04-4FED-B16F-CEA57756E934}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "PhoneBook.Core"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = ""
+ PostBuildEvent = ""
+ RootNamespace = "PhoneBook.Core"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = "PhoneBook.Core.xml"
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = "1591"
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "Nexus.Core"
+ AssemblyName = "Nexus.Core"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Core.dll"
+ />
+ <Reference
+ Name = "IBatisNet.DataMapper"
+ AssemblyName = "IBatisNet.DataMapper"
+ HintPath = "..\..\local-cache\iBatisNet\IBatisNet.DataMapper.dll"
+ />
+ <Reference
+ Name = "Agility.Core"
+ AssemblyName = "Agility.Core"
+ HintPath = "..\..\local-cache\Agility\Agility.Core.dll"
+ />
+ <Reference
+ Name = "Spring.Core"
+ AssemblyName = "Spring.Core"
+ HintPath = "..\..\local-cache\SpringNet\Spring.Core.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "App.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "AppEntry.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "AppEntryList.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "AppEntryListProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "AppUserProfile.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Messages.resx"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "TelephoneProcessor.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <Folder RelPath = "bin\Debug\" />
+ <File
+ RelPath = "Commands\AppCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\BaseCommand.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\BaseCount.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\BaseDelete.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\BaseEntry.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\BaseFilterList.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\BaseList.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\BaseSave.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\EntryInitial.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/Messages.resx b/struts-sandbox/overdrive/PhoneBook/Core/Messages.resx
new file mode 100644
index 0000000..9e2b2bd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/Messages.resx
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+
+ <data name="page_index_hint">
+ <value>Viewing {0}-{1} of {2}.</value>
+ </data>
+
+ <!-- command labels -->
+
+ <data name="find">
+ <value>LIST ALL</value>
+ </data>
+
+ <data name="add">
+ <value>ADD</value>
+ </data>
+
+ <!-- field alerts -->
+
+ <data name="_alert">
+ <value>{0} is invalid.</value>
+ </data>
+
+ <data name="_required">
+ <value>{0} is required.</value>
+ </data>
+
+ <data name="DateTimeProcessor_alert">
+ <value>{0} must be a valid date.</value>
+ </data>
+
+ <data name="TelephoneProcessor_alert">
+ <value>{0} must be a telephone extension.</value>
+ </data>
+
+
+ <!-- field labels -->
+
+ <data name="last_name_label">
+ <value>Last Name</value>
+ </data>
+
+ <data name="first_name_label">
+ <value>First Name</value>
+ </data>
+
+ <data name="extension_label">
+ <value>Extension</value>
+ </data>
+
+ <data name="user_name_label">
+ <value>User Name</value>
+ </data>
+
+ <data name="hired_label">
+ <value>Hired</value>
+ </data>
+
+ <data name="hours_label">
+ <value>Hours</value>
+ </data>
+
+ <data name="editor_label">
+ <value>Editor?</value>
+ </data>
+
+
+ <!-- prompts -->
+
+ <data name="greeting">
+ <value>Welcome, </value>
+ </data>
+
+ <data name="directory_title">
+ <value>Directory (2)</value>
+ </data>
+
+ <data name="directory_heading">
+ <value>Directory</value>
+ </data>
+
+ <data name="directory_prompt">
+ <value>Select a filter to display fewer entries</value>
+ </data>
+
+ <data name="not_found_hint">
+ <value>No matching entries found.</value>
+ </data>
+
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/PhoneBook.Core.xml b/struts-sandbox/overdrive/PhoneBook/Core/PhoneBook.Core.xml
new file mode 100644
index 0000000..adc18d7
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/PhoneBook.Core.xml
@@ -0,0 +1,567 @@
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>PhoneBook.Core</name>
+ </assembly>
+ <members>
+ <member name="T:PhoneBook.Core.Commands.BaseMapper">
+ <summary>
+ Extend RequestCommand with data access methods.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseMapper._Mapper">
+ <summary>
+ Provide a field for Mapper property.
+ </summary>
+
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseMapper.IsEmpty(System.String)">
+ <summary>
+ Indicate whether string is null or zero length.
+ </summary>
+ <param name="input">Input to validate</param>
+ <returns>True if string is nyull or zero length</returns>
+
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseMapper.GuidString">
+ <summary>
+ Create new Global Universal Identifer as a formatted string.
+ </summary>
+ <returns>String representing a new GUID</returns>
+ <remarks><p>
+ No two calls to this method will ever return duplicate strings.
+ </p></remarks>
+
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseMapper.Mapper">
+ <summary>
+ Expose a preconfigured SqlMapper instance that Commands can use to run statements.
+ </summary>
+ <remarks><p>
+ Commands use Mapper to invoke SqlMap statements, such as
+ <code>
+ object row = Mapper.QueryForObject (QueryID, context);
+ </code>.
+ </p><p>
+ Any SqlMapper API method may be called.
+ </p><p>
+ The default behavior of BAseNexusCommand is to use the
+ command ID if the QueryID is null.
+ </p></remarks>
+ <returns>Preconfigured Mapper instance</returns>
+
+ </member>
+ <member name="T:PhoneBook.Core.Commands.BaseCommand">
+ <summary>
+ Provide an abtract extension of BaseNexusCommand
+ with shared members for WNE Commands,
+ including a SqlMapper factory method.
+ </summary>
+ <remarks><p>
+ Superclasses must implement a NexusExecute method (inherited from BaseNexusCommand.
+ </p><p>
+ Concrete subclasses are expected to be created by a IOC Container, like Spring.NET.
+ Most concrete subclasses will be "decorator" classes designed to behave
+ differently based on what properties are set when the class is created.
+ Others may be custom classes with predefined behaviors.
+ </p><p>
+ The Spring catalog provides the versatility we need to mix-and-match
+ base commands with custom commands, as needed,
+ and call either from the client in exactly the same way.
+ </p><p>
+ NOTE that subclasses should NOT use the Outcome property of
+ the Nexus context since they may be subcommands in a Chain.
+ All BaseCommands should use the idiom
+ <code>context[ID] = object</code>
+ to store output.
+ </p><p>
+ NOTE after using the ReShaper code reformatter,
+ the Mapper method needs to be edited.
+ ReSharper removes an absolute reference that we actually need.
+ (Our Mapper method calls the IBatisNet Mapper method.)
+ The correct line of code is maintained as a comment,
+ so that it can <b>copied</b> over the reformatted version.
+ </p></remarks>
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseCommand.WILDCARD">
+ <summary>
+ Document the wildcard character used by SQL queries.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseCommand._Remark">
+ <summary>
+ Provide a field for the Remark property.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseCommand._Mapper">
+ <summary>
+ Provide a field for the Mapper property.
+ </summary>
+
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseCommand.IsEmpty(System.String)">
+ <summary>
+ Indicate whether string is null or zero length.
+ </summary>
+ <param name="input">Input to validate</param>
+ <returns>True if string is nyull or zero length</returns>
+
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseCommand.GuidString">
+ <summary>
+ Create new Global Universal Identifer as a formatted string.
+ </summary>
+ <returns>String representing a new GUID</returns>
+ <remarks><p>
+ No two calls to this method will ever return duplicate strings.
+ </p></remarks>
+
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseCommand.LikeMe(Agility.Core.IContext,System.String)">
+ <summary>
+ Prepare an attribute for use with a SQL wildcard ("LIKE") operation.
+ </summary>
+ <remarks><p>
+ A wildcard is prepended and appended for a full, scan-across match,
+ so that the string will found in any part of the field.
+ </p></remarks>
+ <param name="context">Context with attribute to escape</param>
+ <param name="id">Name of attribute to escape</param>
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseCommand.ID">
+ <summary>
+ If an ID is not provided, default to the ObjectName.
+ </summary>
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseCommand.ObjectName">
+ <summary>
+ Provide a field for the Spring object name (set by Spring).
+ </summary>
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseCommand.Remark">
+ <summary>
+ Accept an arbitrary comment about a command
+ -- more for use in the XML document.
+ </summary>
+
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseCommand.Mapper">
+ <summary>
+ Expose a preconfigured SqlMapper instance that Commands can use to run statements.
+ </summary>
+ <remarks><p>
+ Commands use Mapper to invoke SqlMap statements, such as
+ <code>
+ object row = Mapper ().QueryForObject (QueryID, context);
+ </code>.
+ </p><p>
+ Any SqlMapper API method may be called.
+ </p><p>
+ The default behavior of BAseNexusCommand is to use the
+ command ID if the QueryID is null.
+ </p></remarks>
+ <returns>Preconfigured Mapper</returns>
+
+ </member>
+ <member name="T:PhoneBook.Core.Commands.BaseCount">
+ <summary>
+ Invoke a query that returns the count of a result set.
+ </summary>
+ </member>
+ <member name="T:PhoneBook.Core.Commands.BaseDelete">
+ <summary>
+ Execute delete statement indicated by QueryID
+ for a single entity.
+ </summary>
+
+ </member>
+ <member name="T:PhoneBook.Core.Commands.BaseEntry">
+ <summary>
+ Execute database statement indicated by QueryID
+ for a single object,
+ returning each attribute in the main context.
+ </summary>
+
+ </member>
+ <member name="T:PhoneBook.Core.Commands.BaseFilterList">
+ <summary>
+ Execute database statement indicated by QueryID
+ and wrap result in KeyValue objects
+ so that lists can be displayed by standard methods.
+ </summary>
+
+ </member>
+ <member name="T:PhoneBook.Core.Commands.BaseList">
+ <summary>
+ Run the select query indicated by QueryID,
+ first escaping any LikeIDs and extending any date ranges,
+ and return the result as an IList,
+ </summary>
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseList.GetArray(System.String)">
+ <summary>
+ Generate an array from the IDs.
+ </summary>
+ <returns>Array of LikeIDs</returns>
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseList.LAST_TICK">
+ <summary>
+ Document the last second of the day
+ so as to calculate values for concepts like today and tomorrow.
+ </summary>
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseList.ExtendThruDate(Nexus.Core.IRequestContext)">
+ <summary>
+ If ThruDate is set to the minimum time (00:00),
+ set to the maximum time instead (23:59).
+ </summary>
+ <param name="context"></param>
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseList.PreProcess(Nexus.Core.IRequestContext)">
+ <summary>
+ Prepare special attributes for the query.
+ </summary>
+ <param name="context">The context we are processing</param>
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseList.RequestExecute(Nexus.Core.IRequestContext)">
+ <summary>
+ Provide a default, convenience implementation that will run a "QueryForList"
+ using a data mapping statement of the same ID as the Command;
+ override as needed.
+ </summary>
+ <param name="context">The INexusContext we are processing.</param>
+ <returns>CONTINUE, if an Exception is not thrown.</returns>
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseList.LikeIDs">
+ <summary>
+ Names of key fields to escape for a "like" search.
+ </summary>
+ </member>
+ <member name="T:PhoneBook.Core.Commands.BaseSave">
+ <summary>
+ Store an entity for future reference.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseSave._KeyID">
+ <summary>
+ Provide a field for KeyID property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseSave._InsertID">
+ <summary>
+ Provide a field for InsertID property.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.Commands.BaseSave._UpdateID">
+ <summary>
+ Provide a field for UpdateID property.
+ </summary>
+
+ </member>
+ <member name="M:PhoneBook.Core.Commands.BaseSave.Save(Nexus.Core.IRequestContext,System.String,System.String,System.String)">
+ <summary>
+ Insert or update an entity to the persistent store.
+ </summary>
+ <remark><p>
+ If the "fieldID" is empty, use the insertID statement,
+ otherwise, use the updateID statement.
+ </p></remark>
+ <param name="context">The INexusContext we are processing.</param>
+ <param name="fieldID">The name of the key field.</param>
+ <param name="insertID">The name of the "insert" mapping for the Entity.</param>
+ <param name="updateID">The name of the "update" mapping for the Entity.</param>
+ <returns>False</returns>
+
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseSave.KeyID">
+ <summary>
+ Record the unique identifier for the entity.
+ </summary>
+
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseSave.InsertID">
+ <summary>
+ Record the name of the "insert" mapping for the entity.
+ </summary>
+
+ </member>
+ <member name="P:PhoneBook.Core.Commands.BaseSave.UpdateID">
+ <summary>
+ Record the name of the "update" mapping for the entity.
+ </summary>
+
+ </member>
+ <member name="T:PhoneBook.Core.Commands.EntryInitial">
+ <summary>
+ Create list of initial letters for Facility Names.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.Commands.EntryInitial.ALL">
+ <summary>
+ Document token representing match all entries.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.Commands.EntryInitial.WILDCARD">
+ <summary>
+ Document the wildcard character used by SQL queries.
+ </summary>
+ </member>
+ <member name="T:PhoneBook.Core.App">
+ <summary>
+ Tokens representing context keys.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.CATALOG_KEY">
+ <summary>
+ Token for Catalog property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ENTRY_KEY">
+ <summary>
+ Token for entry_key property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.FIRST_NAME">
+ <summary>
+ Token for first_name property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.LAST_NAME">
+ <summary>
+ Token for last_name property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.USER_NAME">
+ <summary>
+ Token for user_name property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.EXTENSION">
+ <summary>
+ Token for extension property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.HIRED">
+ <summary>
+ Token for hired property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.HOURS">
+ <summary>
+ Token for hours property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.EDITOR">
+ <summary>
+ Token for editor property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ITEM_LIMIT">
+ <summary>
+ Token for SQL LIMIT clause.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ITEM_OFFSET">
+ <summary>
+ Token for SQL OFFSET clause.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ITEM_COUNT">
+ <summary>
+ Token for SQL COUNT clause.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ENTRY">
+ <summary>
+ Token for select one command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ENTRY_LIST">
+ <summary>
+ Token for list all command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ENTRY_INITIAL">
+ <summary>
+ Token for Entry Initial command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.LAST_NAME_LIST">
+ <summary>
+ Token for List Last Names command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.FIRST_NAME_LIST">
+ <summary>
+ Token for List Last Names command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.EXTENSION_LIST">
+ <summary>
+ Token for List Extensions command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.USER_NAME_LIST">
+ <summary>
+ Token for List UserNames command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.HIRED_LIST">
+ <summary>
+ Token for List Hire Dates command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.HOURS_LIST">
+ <summary>
+ Token for List Hours command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ENTRY_FIND">
+ <summary>
+ Token for Entry Find command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ENTRY_SAVE">
+ <summary>
+ Token for Entry Save command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.ENTRY_DELETE">
+ <summary>
+ Token for Entry Delete command.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.App.DIRECTORY_TITLE">
+ <summary>
+ Token for Directory page title.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.App.DIRECTORY_HEADING">
+ <summary>
+ Token for Directory directory page heading.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.App.DIRECTORY_PROMPT">
+ <summary>
+ Token for Directory page prompt.
+ </summary>
+ </member>
+ <member name="T:PhoneBook.Core.AppEntry">
+ <summary>
+ Expose field attributes as public properties.
+ </summary>
+
+ </member>
+ <member name="M:PhoneBook.Core.AppEntry.AddAll(PhoneBook.Core.AppEntry)">
+ <summary>
+ Add each source entry to our internal store.
+ </summary>
+ <remarks><p>
+ Entries with keys that match the property names will be exposed.
+ Other entries may be added, but can only be retrieved via Get.
+ </p></remarks>
+ <param name="row">Entries to add</param>
+
+ </member>
+ <member name="T:PhoneBook.Core.AppEntryList">
+ <summary>
+ Implement Nexus.Core.IEntryList for AppEntry objects.
+ </summary>
+
+ </member>
+ <member name="T:PhoneBook.Core.AppEntryListProcessor">
+ <summary>
+ Implement Nexus.Core.Validators.EntryListProcess for AppEntryList.
+ </summary>
+
+ </member>
+ <member name="T:PhoneBook.Core.AppUserProfile">
+ <summary>
+ Extend UserProfile to include properties specific to this application,
+ such as IsEditor.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.AppUserProfile._IsEditor">
+ <summary>
+ Provide a field for IsEditor property.
+ </summary>
+ </member>
+ <member name="F:PhoneBook.Core.AppUserProfile._Entry">
+ <summary>
+ Provide a field for Entry property.
+ </summary>
+
+ </member>
+ <member name="F:PhoneBook.Core.AppUserProfile._FullName">
+ <summary>
+ Provide a field for FullName property.
+ </summary>
+
+ </member>
+ <member name="M:PhoneBook.Core.AppUserProfile.#ctor(System.Security.Principal.IIdentity)">
+ <summary>
+ Instantiate from an IIdentity.
+ </summary>
+ <param name="id">Identity to copy for this profile.</param>
+
+ </member>
+ <member name="P:PhoneBook.Core.AppUserProfile.IsEditor">
+ <summary>
+ Indicate whether user has editing priveleges.
+ </summary>
+
+ </member>
+ <member name="P:PhoneBook.Core.AppUserProfile.Entry">
+ <summary>
+ Record directory entry for user.
+ </summary>
+
+ </member>
+ <member name="P:PhoneBook.Core.AppUserProfile.FullName">
+ <summary>
+ Record the user's full name (first and last names).
+ </summary>
+
+ </member>
+ <member name="T:PhoneBook.Core.TelephoneProcessor">
+ <summary>
+ Remove punctuation on input and insert punctuation on output.
+ </summary>
+ <remarks><p>
+ Null input or output is passed thorugh as null.
+ Non-null input or output must be strings.
+ Output is formatted for local or long distane US telephone numbers.
+ Output strings that are too short or too long are passed through.
+ </p></remarks>
+ </member>
+ </members>
+</doc>
diff --git a/struts-sandbox/overdrive/PhoneBook/Core/TelephoneProcessor.cs b/struts-sandbox/overdrive/PhoneBook/Core/TelephoneProcessor.cs
new file mode 100644
index 0000000..fa614b2
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Core/TelephoneProcessor.cs
@@ -0,0 +1,65 @@
+using System.Text;
+using Nexus.Core.Validators;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Remove punctuation on input and insert punctuation on output.
+ /// </summary>
+ /// <remarks><p>
+ /// Null input or output is passed thorugh as null.
+ /// Non-null input or output must be strings.
+ /// Output is formatted for local or long distane US telephone numbers.
+ /// Output strings that are too short or too long are passed through.
+ /// </p></remarks>
+ public class TelephoneProcessor : Processor
+ {
+ public override bool ConvertInput(IProcessorContext incoming)
+ {
+ object source = incoming.Source;
+ if (source == null) return true;
+
+ string input = source as string;
+ if (input == null) return false;
+
+ char[] marks = {'-'};
+ string[] splits = input.Split(marks);
+ StringBuilder sb = new StringBuilder(input.Length);
+ foreach (string s in splits)
+ {
+ sb.Append(s);
+ }
+ incoming.Target = sb.ToString();
+ return true;
+ }
+
+ public override bool FormatOutput(IProcessorContext outgoing)
+ {
+ object source = outgoing.Source;
+ if (source == null) return true;
+
+ string output = source as string;
+ if (output == null) return false;
+
+ string mark = "-";
+ if (output == null) return false;
+ string buffer = null;
+
+ if (output.Length == 10)
+ {
+ // 012-345-6789
+ string buffer1 = output.Insert(6, mark);
+ buffer = buffer1.Insert(3, mark);
+ }
+ else if (output.Length == 7)
+ {
+ // 012-3456
+ buffer = output.Insert(3, mark);
+ }
+ else buffer = output;
+
+ outgoing.Target = buffer;
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/LICENSE.txt b/struts-sandbox/overdrive/PhoneBook/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/struts-sandbox/overdrive/PhoneBook/NOTICE.txt b/struts-sandbox/overdrive/PhoneBook/NOTICE.txt
new file mode 100644
index 0000000..73c4637
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/NOTICE.txt
@@ -0,0 +1,6 @@
+NOTICE
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the Apache Software Foundation and was
+originally based, in part, on public domain software written by the
+Oklahoma Department of Environmental Quality, Oklahoma City OK US.
diff --git a/struts-sandbox/overdrive/PhoneBook/PhoneBook-start.sql b/struts-sandbox/overdrive/PhoneBook/PhoneBook-start.sql
new file mode 100644
index 0000000..1221c59
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/PhoneBook-start.sql
@@ -0,0 +1,18 @@
+CREATE DATABASE `phonebook`;
+USE `phonebook`;
+CREATE TABLE `entry` (
+ `pk_entry` char(36) NOT NULL default '',
+ `last_name` char(18) NOT NULL default '',
+ `first_name` char(18) NOT NULL default '',
+ `extension` char(18) NOT NULL default '',
+ `user_name` char(9) NOT NULL default '',
+ `editor` tinyint(3) unsigned NOT NULL default '0',
+ `hired` datetime NOT NULL default '0000-00-00 00:00:00',
+ `hours` double NOT NULL default '37.5'
+) TYPE=MyISAM ROW_FORMAT=FIXED;
+INSERT INTO `entry` (`pk_entry`,`last_name`,`first_name`,`extension`,`user_name`,`editor`,`hired`,`hours`) VALUES
+ ('c5b6bbb1-66d6-49cb-9db6-743af6627828','Clinton','William','5557437828','bubba',0,'1992-08-19 00:00:00',37.5),
+ ('7c424227-8e19-4fb5-b089-423cfca723e1','Roosevelt','Theodore','5557438942','bull',0,'2001-09-14 00:00:00',37.5),
+ ('9320ea40-0c01-43e8-9cec-8fb9b3928c2c','Kennedy','John F.','5557433928','fitz',0,'1987-05-29 00:00:00',37.5),
+ ('3b27c933-c1dc-4d85-9744-c7d9debae196','Pierce','Franklin','5557437919','hawkeye',0,'1984-11-18 00:00:00',35),
+ ('554ff9e7-a6f5-478a-b76b-a666f5c54e40','Jefferson','Thomas','5557435440','monty',0,'1976-07-04 00:00:00',37.5);
diff --git a/struts-sandbox/overdrive/PhoneBook/PhoneBook.sln b/struts-sandbox/overdrive/PhoneBook/PhoneBook.sln
new file mode 100644
index 0000000..817b37b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/PhoneBook.sln
@@ -0,0 +1,43 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "http://localhost/PhoneBook/Web.csproj", "{948EE344-D033-4358-88E8-77FDE080D93C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {3150F3E8-9A04-4FED-B16F-CEA57756E934} = {3150F3E8-9A04-4FED-B16F-CEA57756E934}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{3150F3E8-9A04-4FED-B16F-CEA57756E934}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{2F4D056B-4211-4A17-8F47-37901085B3AE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {3150F3E8-9A04-4FED-B16F-CEA57756E934} = {3150F3E8-9A04-4FED-B16F-CEA57756E934}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {948EE344-D033-4358-88E8-77FDE080D93C}.Debug.ActiveCfg = Debug|.NET
+ {948EE344-D033-4358-88E8-77FDE080D93C}.Debug.Build.0 = Debug|.NET
+ {948EE344-D033-4358-88E8-77FDE080D93C}.Release.ActiveCfg = Release|.NET
+ {948EE344-D033-4358-88E8-77FDE080D93C}.Release.Build.0 = Release|.NET
+ {3150F3E8-9A04-4FED-B16F-CEA57756E934}.Debug.ActiveCfg = Debug|.NET
+ {3150F3E8-9A04-4FED-B16F-CEA57756E934}.Debug.Build.0 = Debug|.NET
+ {3150F3E8-9A04-4FED-B16F-CEA57756E934}.Release.ActiveCfg = Release|.NET
+ {3150F3E8-9A04-4FED-B16F-CEA57756E934}.Release.Build.0 = Release|.NET
+ {2F4D056B-4211-4A17-8F47-37901085B3AE}.Debug.ActiveCfg = Debug|.NET
+ {2F4D056B-4211-4A17-8F47-37901085B3AE}.Debug.Build.0 = Debug|.NET
+ {2F4D056B-4211-4A17-8F47-37901085B3AE}.Release.ActiveCfg = Release|.NET
+ {2F4D056B-4211-4A17-8F47-37901085B3AE}.Release.Build.0 = Release|.NET
+ EndGlobalSection
+ GlobalSection(SolutionItems) = postSolution
+ ..\Nexus\Web\GridControl.ascx.cs = ..\Nexus\Web\GridControl.ascx.cs
+ prebuild.bat = prebuild.bat
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/AssemblyInfo.cs b/struts-sandbox/overdrive/PhoneBook/Test/AssemblyInfo.cs
new file mode 100644
index 0000000..05af947
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/BaseTest.cs b/struts-sandbox/overdrive/PhoneBook/Test/BaseTest.cs
new file mode 100644
index 0000000..1fdeddd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/BaseTest.cs
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+using NUnit.Framework;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Provide base class so unit tests can share utility.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class BaseTest : CatalogBaseTest
+ {
+ /// <summary>
+ /// Confirm that the outcome is a non-null, non-empty list.
+ /// </summary>
+ /// <param name="context">Context to confirm</param>
+ /// <returns>The non-null, non-empty list</returns>
+ ///
+ protected IList AssertListOutcome(IRequestContext context)
+ {
+ AssertNominal(context);
+ Assert.IsTrue(context.HasOutcome, "Expected command to set an Outcome.");
+ IList list = context.Outcome as IList;
+ bool notEmpty = ((list != null) && (list.Count > 0));
+ Assert.IsTrue(notEmpty, "Expected outcome to be a not-empty list");
+ return list;
+ }
+
+ /// <summary>
+ /// Exercise the testing infrastructure.
+ /// </summary>
+ ///
+ [Test]
+ public void Pass()
+ {
+ }
+
+ /// <summary>
+ /// Exercise GUID creation,
+ /// and provide a device for generating GUIDs if needed.
+ /// </summary>
+ ///
+ [Test]
+ public void GuidString()
+ {
+ IDictionary test = new Hashtable();
+ for (int i = 0; i < 10; i++)
+ {
+ string key = Guid.NewGuid().ToString();
+ Assert.IsNotNull(key);
+ Assert.IsTrue(36 == key.Length);
+ test.Add(key, key); // Add throws an exception on duplicate keys
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Commands/DirectoryViewTest.cs b/struts-sandbox/overdrive/PhoneBook/Test/Commands/DirectoryViewTest.cs
new file mode 100644
index 0000000..db7241f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Commands/DirectoryViewTest.cs
@@ -0,0 +1,43 @@
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Exercise Directory View Command.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class EntryFindTest : BaseTest
+ {
+ /// <summary>
+ /// Confirm that Context contains the expected attributes for the list filter-0ps.
+ /// </summary>
+ ///
+ [Test]
+ public void ContainsFilters()
+ {
+ IRequestContext context = catalog.ExecuteRequest(App.ENTRY_FIND);
+ this.AssertNominal(context);
+ string[] FILTERS = {App.LAST_NAME_LIST, App.FIRST_NAME_LIST, App.EXTENSION_LIST, App.USER_NAME_LIST, App.HIRED_LIST, App.HOURS_LIST};
+ foreach (string filter in FILTERS)
+ {
+ Assert.IsTrue(context.Contains(filter), filter + ": Expected context to contain key.");
+ }
+ }
+
+ /// <summary>
+ /// Confirm that Helper contains the expected command.
+ /// </summary>
+ ///
+ [Test]
+ public void HelperContains()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_FIND);
+ IRequestCommand command = helper.Command;
+ Assert.IsNotNull(command, "Expected Helper to have a Command");
+ Assert.AreEqual(App.ENTRY_FIND, command.ID, "Expected Helper to have View Command.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Commands/FilterLists.cs b/struts-sandbox/overdrive/PhoneBook/Test/Commands/FilterLists.cs
new file mode 100644
index 0000000..a7161c5
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Commands/FilterLists.cs
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Exercise the various lists of distinct values
+ /// that are used to filter the directory.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class FilterListsTest : BaseTest
+ {
+ /// <summary>
+ /// Confirm that a list is returned as the outcome,
+ /// and that each item on the list is not-empty and unique.
+ /// </summary>
+ /// <param name="context">Context returned by command</param>
+ ///
+ private void FilterList_Result(IRequestContext context)
+ {
+ IList list = AssertListOutcome(context);
+ foreach (IKeyValue item in list)
+ {
+ Assert.IsNotNull(item, "Expected each item to be non-null");
+ object key = item.Value;
+ Assert.IsNotNull(key, "Expected each key to be non-null");
+ string keystring = key.ToString();
+ Assert.IsTrue(keystring.Length > 0, "Expected each key to be non-empty");
+ }
+ IDictionary keys = new Hashtable(list.Count);
+ foreach (IKeyValue item in list)
+ {
+ string key = item.Value.ToString();
+ if (keys.Contains(key)) Assert.Fail(key + ": Expected each item to be unique");
+ keys.Add(key, key);
+ }
+ }
+
+ /// <summary>
+ /// Exercise the filter commands.
+ /// </summary>
+ ///
+ [Test]
+ public void TestFilterLists()
+ {
+ string[] FILTERS = {App.LAST_NAME_LIST, App.FIRST_NAME_LIST, App.EXTENSION_LIST, App.USER_NAME_LIST, App.HIRED_LIST, App.HOURS_LIST};
+ foreach (string filter in FILTERS)
+ {
+ IRequestContext context = catalog.ExecuteRequest(filter);
+ FilterList_Result(context);
+ }
+ }
+
+ /// <summary>
+ /// Excercise entry file and validate key value list.
+ /// </summary>
+ /// <param name="key">ID for list</param>
+ /// <returns>The validated list</returns>
+ ///
+ private IKeyValueList FilterList(string key)
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_FIND);
+ helper.Execute();
+ IKeyValueList list = helper.Criteria[key] as IKeyValueList;
+ Assert.IsNotNull(list, "Expected KeyValueList");
+ return list;
+ }
+
+ /// <summary>
+ /// Exercise Extension List filter.
+ /// </summary>
+ ///
+ [Test]
+ public void TestFilterFormat_extension()
+ {
+ IKeyValueList list = FilterList(App.EXTENSION_LIST);
+ foreach (IKeyValue item in list)
+ {
+ string key = item.Value as string;
+ Assert.IsTrue(key.Length > "1234567890".Length, "Expected formatted extension, not: " + key);
+ }
+ }
+
+ /// <summary>
+ /// Exercise Hired filter.
+ /// </summary>
+ ///
+ [Test]
+ public void TestFilterFormat_hired()
+ {
+ IKeyValueList list = FilterList(App.HIRED_LIST);
+ foreach (IKeyValue item in list)
+ {
+ string key = item.Value as string;
+ bool okay = (key.Length > 0) && (key.Length < "##/##/#### ".Length);
+ Assert.IsTrue(okay, "Expected short date format, not: " + key);
+ }
+ }
+
+ [Test]
+ public void Initial()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_LIST);
+ helper.Criteria["initial"] = "C%";
+ helper.Execute();
+ Assert.IsTrue(helper.IsNominal, helper.AlertsText);
+ IList list = helper.Outcome;
+ Assert.IsTrue(list.Count > 0, "Expected one or more entries");
+ foreach (AppEntry entry in list)
+ {
+ Assert.IsTrue("C".Equals(entry.last_name.Substring(0, 1)), "Expected all to be C*");
+ }
+ int count = Convert.ToInt32(helper.Criteria["item_count"]);
+ Assert.IsTrue(count == list.Count, "Expected counts to match");
+ }
+
+ [Test]
+ public void InitialDistinct()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_INITIAL);
+ helper.Execute();
+ Assert.IsTrue(helper.IsNominal, helper.AlertsText);
+ IList list = helper.Outcome;
+ Assert.IsTrue(list.Count > 0, "Expected one or more entries");
+ string a = list[0] as string;
+ Assert.IsNotNull(a, "Expected letter");
+ Assert.IsTrue("C".Equals(a), "Expected C");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Commands/SelectAllTest.cs b/struts-sandbox/overdrive/PhoneBook/Test/Commands/SelectAllTest.cs
new file mode 100644
index 0000000..f12f091
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Commands/SelectAllTest.cs
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Exercise SelectAll Command per [OVR-5].
+ /// </summary>
+ ///
+ [TestFixture]
+ public class SelectAllTest : BaseTest
+ {
+ /// <summary>
+ /// Assert result of SelectAll, after another method runs the command.
+ /// </summary>
+ /// <param name="context">Context with result to assert.</param>
+ ///
+ private void SelectAll_Result(IRequestContext context)
+ {
+ IList list = AssertListOutcome(context);
+ IDictionary row = list[0] as IDictionary;
+ Assert.IsNotNull(row, "Expected list entry to be an IDictionary.");
+ string[] KEYS = {App.FIRST_NAME, App.LAST_NAME, App.USER_NAME, App.EXTENSION, App.HIRED, App.HOURS, App.EDITOR};
+ bool valid = true;
+ foreach (string key in KEYS)
+ {
+ valid = valid && row.Contains(key);
+ }
+ Assert.IsTrue(valid, "Expected row to contain all keys.");
+ }
+
+
+ /// <summary>
+ /// Filter all and succeed, using catalog.
+ /// </summary>
+ ///
+ [Test]
+ public void SelectAll_Pass()
+ {
+ IRequestContext context = catalog.ExecuteRequest(App.ENTRY_LIST);
+ SelectAll_Result(context);
+ }
+
+ /// <summary>
+ /// Exercise Entry List and validate hired and extension string formatting.
+ /// </summary>
+ ///
+ [Test]
+ public void FilterHelper_Format()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_LIST);
+ helper.Execute();
+ AssertNominal(helper);
+ AppEntryList list = helper.Outcome as AppEntryList;
+ Assert.IsNotNull(list, "Expected list to be AppEntryList");
+ AppEntry row = list[0] as AppEntry;
+ Assert.IsNotNull(row, "Expected rows to be AppEntries");
+
+ string hired = row.hired;
+ Assert.IsNotNull(hired, "Expected each row to have a hired date.");
+ Assert.IsTrue(hired.Length < "##/##/#### ".Length, hired + ": Expected short date format.");
+
+ string extension = row.extension;
+ Assert.IsNotNull(extension, "Expected each row to have an extension.");
+ Assert.IsTrue(extension.Length > "1234567890".Length, extension + ": Expected formatted extension.");
+ }
+
+ /// <summary>
+ /// Exercise custom paging
+ /// (retrieve only visible section of the result se).
+ /// </summary>
+ ///
+ [Test]
+ public void SelectAll_Limit()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_LIST);
+ helper.Criteria[App.ITEM_LIMIT] = 2;
+ helper.Criteria[App.ITEM_OFFSET] = 0;
+ helper.Execute();
+ if (!helper.IsNominal) Assert.Fail(helper.AlertsText);
+ IList list = helper.Outcome;
+ Assert.IsTrue(list.Count == 2, "Expected result set to be limited to two entries.");
+ AppEntry entry = list[0] as AppEntry;
+ helper.Criteria[App.ITEM_LIMIT] = 2;
+ helper.Criteria[App.ITEM_OFFSET] = 3;
+ helper.Execute();
+ IList list2 = helper.Outcome;
+ AppEntry entry2 = list2[0] as AppEntry;
+ Assert.IsFalse(entry.entry_key.Equals(entry2.entry_key), "Expected result sets to be different");
+ int count = Convert.ToInt32(helper.Criteria[App.ITEM_COUNT]);
+ Assert.IsTrue(count > 2, "Expected the overall count to be higher");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Objects.xml b/struts-sandbox/overdrive/PhoneBook/Test/Objects.xml
new file mode 100644
index 0000000..df9abda
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Objects.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <import resource="Resources/AppBase.xml"/>
+ <import resource="Resources/AppConfig.xml"/>
+ <import resource="Resources/AppFields.xml"/>
+ <import resource="Resources/Catalog.xml"/>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppBase.xml b/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppBase.xml
new file mode 100644
index 0000000..dbb11e6
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppBase.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Base element (super parent)-->
+
+ <object id="BaseMapper" abstract="true">
+ <property name="Mapper"><ref object="Mapper"/></property>
+ </object>
+
+ <!-- Base class parents -->
+
+ <object id="BaseChain" type="Nexus.Core.RequestChain, Nexus.Core"/>
+
+ <object id="BaseCount" type="PhoneBook.Core.Commands.BaseCount, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseEntry" type="PhoneBook.Core.Commands.BaseEntry, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFilterList" type="PhoneBook.Core.Commands.BaseFilterList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFieldContext" type="Nexus.Extras.Spring.FieldContext">
+ <property name="MessageSource">
+ <ref object="messageSource" />
+ </property>
+ </object>
+
+ <object id="BaseKeyValueProcessor" type="Nexus.Core.Validators.KeyValueProcessor"/>
+
+ <object id="BaseList" type="PhoneBook.Core.Commands.BaseList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseSave" type="PhoneBook.Core.Commands.BaseSave, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="EntryInitial" type="PhoneBook.Core.Commands.EntryInitial, PhoneBook.Core" parent="BaseMapper"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppConfig.xml b/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppConfig.xml
new file mode 100644
index 0000000..f3bbcbd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppConfig.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Message Source -->
+
+ <object id="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
+ <property name="ResourceManagers">
+ <list>
+ <value>PhoneBook.Core.Messages, PhoneBook.Core</value>
+ <value>Nexus.Web.Messages, Nexus.Web</value>
+ </list>
+ </property>
+ </object>
+
+
+ <!-- Request Processors -->
+
+ <object id="convert_input" type="Nexus.Core.Validators.ConvertInput">
+ <property name="ID"><value>convert_input</value></property>
+ </object>
+
+ <object id="format_output" type="Nexus.Core.Validators.FormatOutput">
+ <property name="ID"><value>format_output</value></property>
+ </object>
+
+ <object id="clear_context" type="Nexus.Core.Validators.ClearContext">
+ <property name="ID"><value>clear_context</value></property>
+ </object>
+
+ <!-- pre-op -->
+
+ <object id="pre-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="convert_input"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- post-op -->
+
+ <object id="post-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="format_output"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- Catalog -->
+
+ <object id="Catalog" type="Nexus.Extras.Spring.Catalog">
+ <property name="FieldTable"><ref object="FieldTable"/></property>
+ <property name="PreOp"><ref object="pre-op"/></property>
+ <property name="PostOp"><ref object="post-op"/></property>
+ <property name="ViewHelper"><object type="Nexus.Web.WebHelper, Nexus.Web" singleton="false"/></property>
+ </object>
+
+<!-- iBATIS Mapper -->
+
+ <object id="Mapper" type="IBatisNet.DataMapper.Mapper, IBatisNet.DataMapper"
+ factory-method="Instance"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppFields.xml b/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppFields.xml
new file mode 100644
index 0000000..303fc2b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Resources/AppFields.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- FieldTable -->
+
+ <object id="FieldTable" type="Nexus.Core.Tables.FieldTable">
+ <property name="AddFieldContexts">
+ <list>
+ <ref object="last_name"/>
+ <ref object="first_name"/>
+ <ref object="extension"/>
+ <ref object="user_name"/>
+ <ref object="hired"/>
+ <ref object="hours"/>
+ <ref object="_entry_list"/>
+ <ref object="_entry_list_count"/>
+ <ref object="_extension_list"/>
+ <ref object="_hired_list"/>
+ </list>
+ </property>
+ <property name="AddProcessors">
+ <list>
+ <ref object="DateTimeProcessor"/>
+ <ref object="TelephoneProcessor"/>
+ <ref object="EntryListProcessor"/>
+ <ref object="ExtensionListProcessor"/>
+ <ref object="HiredListProcessor"/>
+ </list>
+ </property>
+ </object>
+
+ <object id="last_name" parent="BaseFieldContext">
+ <property name="ID"><value>last_name</value></property>
+ </object>
+
+ <object id="first_name" parent="BaseFieldContext">
+ <property name="ID"><value>first_name</value></property>
+ </object>
+
+ <object id="user_name" parent="BaseFieldContext">
+ <property name="ID"><value>user_name</value></property>
+ </object>
+
+ <object id="extension" parent="BaseFieldContext">
+ <property name="ID"><value>extension</value></property>
+ <property name="Processor"><ref object="TelephoneProcessor"/></property>
+ </object>
+
+ <object id="hired" parent="BaseFieldContext">
+ <property name="ID"><value>hired</value></property>
+ <property name="Processor"><ref object="DateTimeProcessor"/></property>
+ </object>
+
+ <object id="hours" parent="BaseFieldContext">
+ <property name="ID"><value>hours</value></property>
+ </object>
+
+ <object id="editor" parent="BaseFieldContext">
+ <property name="ID"><value>editor</value></property>
+ </object>
+
+ <!-- property name="ControlTypeName"><value>CheckBox</value></property -->
+
+ <!-- We need to "hash" the name with "_" to avoid conflict with the filter Command -->
+ <object id="_entry_list" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="Processor"><ref object="EntryListProcessor"/></property>
+ </object>
+
+ <object id="_entry_list_count" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="Processor"><ref object="CollectionProcessor"/></property>
+ </object>
+
+ <object id="_extension_list" parent="BaseFieldContext">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="Processor"><ref object="ExtensionListProcessor"/></property>
+ </object>
+
+ <object id="_hired_list" parent="BaseFieldContext">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="Processor"><ref object="HiredListProcessor"/></property>
+ </object>
+
+ <object id="CollectionProcessor" type="Nexus.Core.Validators.CollectionProcessor, Nexus.Core">
+ <property name="ID"><value>EntryCountProcessor</value></property>
+ </object>
+
+ <!-- "d" is .NET for "short date" -->
+ <object id="DateTimeProcessor" type="Nexus.Core.Validators.DateTimeProcessor">
+ <property name="ID"><value>DateTimeProcessor</value></property>
+ <property name="DataFormat"><value>d</value></property>
+ </object>
+
+ <object id="TelephoneProcessor" type="PhoneBook.Core.TelephoneProcessor">
+ <property name="ID"><value>TelephoneProcessor</value></property>
+ </object>
+
+ <object id="EntryListProcessor" type="PhoneBook.Core.AppEntryListProcessor">
+ <property name="ID"><value>EntryListProcessor</value></property>
+ </object>
+
+ <object id="ExtensionListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>ExtensionListProcessor</value></property>
+ <property name="Key"><value>extension</value></property>
+ </object>
+
+ <object id="HiredListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>HiredListProcessor</value></property>
+ <property name="Key"><value>hired</value></property>
+ </object>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Resources/Catalog.xml b/struts-sandbox/overdrive/PhoneBook/Test/Resources/Catalog.xml
new file mode 100644
index 0000000..d6ae4a0
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Resources/Catalog.xml
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- entry commands -->
+
+ <object id="entry_list_rows" parent="BaseList">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="QueryID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_list_count" parent="BaseCount">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="QueryID"><value>entry_count</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry" parent="BaseEntry">
+ <property name="ID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+
+ <!-- filter list commands -->
+
+ <object id="last_name_list" parent="BaseFilterList">
+ <property name="ID"><value>last_name_list</value></property>
+ <property name="RelatedIDs"><list><value>last_name_list</value></list></property>
+ </object>
+
+ <object id="first_name_list" parent="BaseFilterList">
+ <property name="ID"><value>first_name_list</value></property>
+ <property name="RelatedIDs"><list><value>first_name_list</value></list></property>
+ </object>
+
+ <object id="extension_list" parent="BaseFilterList">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="RelatedIDs"><list><value>extension_list</value></list></property>
+ </object>
+
+ <object id="user_name_list" parent="BaseFilterList">
+ <property name="ID"><value>user_name_list</value></property>
+ <property name="RelatedIDs"><list><value>user_name_list</value></list></property>
+ </object>
+
+ <object id="hired_list" parent="BaseFilterList">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="RelatedIDs"><list><value>hired_list</value></list></property>
+ </object>
+
+ <object id="hours_list" parent="BaseFilterList">
+ <property name="ID"><value>hours_list</value></property>
+ <property name="RelatedIDs"><list><value>hours_list</value></list></property>
+ </object>
+
+ <object id="entry_initial" parent="EntryInitial">
+ <property name="ID">
+ <value>entry_initial</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_initial</value>
+ </list>
+ </property>
+ </object>
+
+ <!-- chains -->
+
+ <object id="entry_list" parent="BaseChain">
+ <property name="ID">
+ <value>entry_list</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="entry_list_count" />
+ <ref object="entry_list_rows" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_find" parent="BaseChain">
+ <property name="ID">
+ <value>entry_find</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="last_name_list" />
+ <ref object="first_name_list" />
+ <ref object="extension_list" />
+ <ref object="user_name_list" />
+ <ref object="hired_list" />
+ <ref object="hours_list" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_save" parent="BaseSave">
+ <property name="ID">
+ <value>entry_save</value>
+ </property>
+ <property name="KeyID">
+ <value>entry_key</value>
+ </property>
+ <property name="InsertID">
+ <value>entry_insert</value>
+ </property>
+ <property name="UpdateID">
+ <value>entry_update</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_key</value>
+ </list>
+ </property>
+ <property name="RequiredIDs">
+ <list>
+ <value>first_name</value>
+ <value>last_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hours</value>
+ <value>hired</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Resources/Queries.xml b/struts-sandbox/overdrive/PhoneBook/Test/Resources/Queries.xml
new file mode 100644
index 0000000..370639f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Resources/Queries.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<sqlMap
+ namespace="phonebook"
+ xmlns="http://ibatis.apache.org/mapping"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
+
+ <parameterMaps>
+
+ <parameterMap id="entry_save_param">
+ <parameter property="last_name"/>
+ <parameter property="first_name"/>
+ <parameter property="extension"/>
+ <parameter property="user_name"/>
+ <parameter property="hired"/>
+ <parameter property="hours"/>
+ <parameter property="editor"/>
+ <parameter property="entry_key"/>
+ </parameterMap>
+
+ </parameterMaps>
+
+ <statements>
+
+ <select id="last_name_list" resultClass="string">
+ SELECT DISTINCT
+ last_name
+ FROM entry
+ ORDER BY last_name
+ </select>
+
+ <select id="first_name_list" resultClass="string">
+ SELECT DISTINCT
+ first_name
+ FROM entry
+ ORDER BY first_name
+ </select>
+
+ <select id="extension_list" resultClass="string">
+ SELECT DISTINCT
+ extension
+ FROM entry
+ ORDER BY extension
+ </select>
+
+ <select id="user_name_list" resultClass="string">
+ SELECT DISTINCT
+ user_name
+ FROM entry
+ ORDER BY user_name
+ </select>
+
+ <select id="hired_list" resultClass="date">
+ SELECT DISTINCT
+ hired
+ FROM entry
+ ORDER BY hired
+ </select>
+
+ <select id="hours_list" resultClass="string">
+ SELECT DISTINCT
+ hours
+ FROM entry
+ ORDER BY hours
+ </select>
+
+ <select id="entry" paramClass="Hashtable" resultClass="Hashtable">
+ SELECT
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry AS entry_key
+ FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ <dynamic>
+ <isNotNull property="item_limit">
+ LIMIT #item_limit# OFFSET #item_offset#
+ </isNotNull>
+ </dynamic>;
+ </select>
+
+ <select id="entry_count" paramClass="Hashtable" resultClass="string">
+ SELECT COUNT(*) FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ </select>
+
+ <select id="entry_initial" paramClass="string" resultClass="string">
+ SELECT COUNT(*)
+ FROM entry
+ WHERE last_name LIKE #value#
+ </select>
+
+ <insert id="entry_insert" parameterMap="entry_save_param">
+ INSERT INTO entry (
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry
+ )
+ VALUES (?,?,?,?, ?,?,?,?)
+ </insert>
+
+ <update id="entry_update" parameterMap="entry_save_param">
+ UPDATE entry SET
+ last_name=?,
+ first_name=?,
+ extension=?,
+ user_name=?,
+ hired=?,
+ hours=?,
+ editor=?
+ WHERE
+ pk_entry=?
+ </update>
+
+ <delete id="entry_delete" paramClass="Hashtable">
+ DELETE FROM entry WHERE pk_entry=#entry_key#;
+ </delete>
+
+ </statements>
+</sqlMap>
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/Test.csproj b/struts-sandbox/overdrive/PhoneBook/Test/Test.csproj
new file mode 100644
index 0000000..611c1de
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/Test.csproj
@@ -0,0 +1,192 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{2F4D056B-4211-4A17-8F47-37901085B3AE}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "PhoneBook.Test"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = "$(SolutionDir)prebuild $(SolutionDir)"
+ PostBuildEvent = ""
+ RootNamespace = "PhoneBook.Core"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = "PhoneBook.Test.xml"
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = "1591"
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "nunit.framework"
+ AssemblyName = "nunit.framework"
+ HintPath = "..\..\..\..\..\..\..\Program Files\NUnit 2.2\bin\nunit.framework.dll"
+ AssemblyFolderKey = "hklm\dn\nunit.framework"
+ />
+ <Reference
+ Name = "Core"
+ Project = "{3150F3E8-9A04-4FED-B16F-CEA57756E934}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ <Reference
+ Name = "Nexus.Core"
+ AssemblyName = "Nexus.Core"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Core.dll"
+ />
+ <Reference
+ Name = "Nexus.Test"
+ AssemblyName = "Nexus.Test"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Test.dll"
+ />
+ <Reference
+ Name = "Agility.Core"
+ AssemblyName = "Agility.Core"
+ HintPath = "..\..\local-cache\Agility\Agility.Core.dll"
+ />
+ <Reference
+ Name = "Nexus.Web"
+ AssemblyName = "Nexus.Web"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Web.dll"
+ />
+ <Reference
+ Name = "Nexus.Extras"
+ AssemblyName = "Nexus.Extras"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Extras.dll"
+ />
+ <Reference
+ Name = "Web"
+ Project = "{948EE344-D033-4358-88E8-77FDE080D93C}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "BaseTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Objects.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "bin\Debug\providers.config"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "bin\Debug\sqlmap.config"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "bin\Debug\sqlmap.config.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Commands\DirectoryViewTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\FilterLists.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Commands\SelectAllTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Resources\AppBase.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\AppConfig.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\AppFields.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\Catalog.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\Queries.xml"
+ BuildAction = "Content"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/providers.config b/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/providers.config
new file mode 100644
index 0000000..e0a5241
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/providers.config
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8"?>
+<providers
+xmlns="http://ibatis.apache.org/providers"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+<clear/>
+<provider
+ name="sqlServer1.0"
+ description="Microsoft SQL Server, provider V1.0.3300.0 in framework .NET V1.0"
+ enabled="false"
+ assemblyName="System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider
+ name="sqlServer1.1"
+ description="Microsoft SQL Server, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ default="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider
+ name="sqlServer2.0"
+ enabled="false"
+ description="Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass=" System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters = "false"
+ useParameterPrefixInSql = "true"
+ useParameterPrefixInParameter = "true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider name="OleDb1.1"
+ description="OleDb, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider name="OleDb2.0"
+ description="OleDb, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc1.1"
+ description="Odbc, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc2.0"
+ description="Odbc, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle9.2"
+ description="Oracle, Oracle provider V9.2.0.401"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=9.2.0.401, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle10.1"
+ description="Oracle, oracle provider V10.1.0.301"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=10.1.0.301, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracleClient1.0"
+ description="Oracle, Microsoft provider V1.0.5000.0"
+ enabled="false"
+ assemblyName="System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.OracleClient.OracleConnection"
+ commandClass="System.Data.OracleClient.OracleCommand"
+ parameterClass="System.Data.OracleClient.OracleParameter"
+ parameterDbTypeClass="System.Data.OracleClient.OracleType"
+ parameterDbTypeProperty="OracleType"
+ dataAdapterClass="System.Data.OracleClient.OracleDataAdapter"
+ commandBuilderClass="System.Data.OracleClient.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ allowMARS="false"
+ />
+ <provider
+ name="ByteFx"
+ description="MySQL, ByteFx provider V0.7.6.15073"
+ enabled="false"
+ assemblyName="ByteFX.MySqlClient, Version=0.7.6.15073, Culture=neutral, PublicKeyToken=f2fef6fed1732fc1" connectionClass="ByteFX.Data.MySqlClient.MySqlConnection"
+ commandClass="ByteFX.Data.MySqlClient.MySqlCommand"
+ parameterClass="ByteFX.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="ByteFX.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="ByteFX.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="ByteFX.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="MySql"
+ description="MySQL, MySQL provider 1.0.7.30072"
+ enabled="true"
+ assemblyName="MySql.Data, Version=1.0.7.30072, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionClass="MySql.Data.MySqlClient.MySqlConnection"
+ commandClass="MySql.Data.MySqlClient.MySqlCommand"
+ parameterClass="MySql.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="MySql.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="MySql.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="MySql.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="?"
+ allowMARS="false"
+ />
+ <provider name="SQLite3"
+ description="SQLite, SQLite.NET provider V0.21.1869.3794"
+ enabled="false"
+ assemblyName="SQLite.NET, Version=0.21.1869.3794, Culture=neutral, PublicKeyToken=c273bd375e695f9c"
+ connectionClass="Finisar.SQLite.SQLiteConnection"
+ commandClass="Finisar.SQLite.SQLiteCommand"
+ parameterClass="Finisar.SQLite.SQLiteParameter"
+ parameterDbTypeClass="System.Data.DbType, System.Data"
+ parameterDbTypeProperty="DbType"
+ dataAdapterClass="Finisar.SQLite.SQLiteDataAdapter"
+ commandBuilderClass="Finisar.SQLite.SQLiteCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ setDbParameterPrecision="false"
+ setDbParameterScale="false"
+ allowMARS="false"
+ />
+ <provider
+ name="Firebird1.7"
+ description="Firebird, Firebird SQL .NET provider V1.7.0.33200"
+ enabled="false"
+ assemblyName="FirebirdSql.Data.Firebird, Version=1.7.0.33200, Culture=neutral, PublicKeyToken=fa843d180294369d" connectionClass="FirebirdSql.Data.Firebird.FbConnection"
+ commandClass="FirebirdSql.Data.Firebird.FbCommand"
+ parameterClass="FirebirdSql.Data.Firebird.FbParameter"
+ parameterDbTypeClass="FirebirdSql.Data.Firebird.FbDbType"
+ parameterDbTypeProperty="FbDbType"
+ dataAdapterClass="FirebirdSql.Data.Firebird.FbDataAdapter"
+ commandBuilderClass="FirebirdSql.Data.Firebird.FbCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="PostgreSql0.99.1.0"
+ description="PostgreSql, Npgsql provider V0.99.1.0"
+ enabled="false"
+ assemblyName="Npgsql, Version=0.99.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"
+ connectionClass="Npgsql.NpgsqlConnection"
+ commandClass="Npgsql.NpgsqlCommand"
+ parameterClass="Npgsql.NpgsqlParameter"
+ parameterDbTypeClass="NpgsqlTypes.NpgsqlDbType"
+ parameterDbTypeProperty="NpgsqlDbType"
+ dataAdapterClass="Npgsql.NpgsqlDataAdapter"
+ commandBuilderClass="Npgsql.NpgsqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ allowMARS="true"
+ />
+ <provider
+ name="iDb2.10"
+ description="IBM DB2 Provider, V 10.0"
+ enabled="false"
+ assemblyName="IBM.Data.DB2.iSeries, Version=10.0.0.0,Culture=neutral, PublicKeyToken=9cdb2ebfb1f93a26, Custom=null" connectionClass="IBM.Data.DB2.iSeries.iDB2Connection"
+ commandClass="IBM.Data.DB2.iSeries.iDB2Command"
+ parameterClass="IBM.Data.DB2.iSeries.iDB2Parameter"
+ parameterDbTypeClass="IBM.Data.DB2.iSeries.iDB2DbType"
+ parameterDbTypeProperty="iDB2DbType"
+ dataAdapterClass="IBM.Data.DB2.iSeries.iDB2DataAdapter"
+ commandBuilderClass="IBM.Data.DB2.iSeries.iDB2CommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Informix"
+ description="Informix NET Provider, 2.81.0.0"
+ enabled="false"
+ assemblyName="IBM.Data.Informix, Version=2.81.0.0, Culture=neutral, PublicKeyToken=7c307b91aa13d208"
+ connectionClass="IBM.Data.Informix.IfxConnection"
+ commandClass="IBM.Data.Informix.IfxCommand"
+ parameterClass="IBM.Data.Informix.IfxParameter"
+ parameterDbTypeClass="IBM.Data.Informix.IfxType"
+ parameterDbTypeProperty="IfxType"
+ dataAdapterClass="IBM.Data.Informix.IfxDataAdapter"
+ commandBuilderClass="IBM.Data.Informix.IfxCommandBuilder"
+ usePositionalParameters = "true"
+ useParameterPrefixInSql = "false"
+ useParameterPrefixInParameter = "false"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+</providers>
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/sqlmap.config b/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/sqlmap.config
new file mode 100644
index 0000000..3c2929f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/sqlmap.config
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" >
+
+ <properties resource="sqlmap.config.xml"/>
+
+ <settings>
+ <setting useStatementNamespaces="false"/>
+ <setting cacheModelsEnabled="true"/>
+ </settings>
+
+ <database>
+ <provider name="${provider}"/>
+ <dataSource name="default" connectionString="${development}"/>
+ </database>
+
+ <sqlMaps>
+ <sqlMap resource="${root}/Resources/Queries.xml"/>
+ </sqlMaps>
+
+</sqlMapConfig>
diff --git a/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/sqlmap.config.xml b/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/sqlmap.config.xml
new file mode 100644
index 0000000..339057a
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Test/bin/Debug/sqlmap.config.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<settings>
+ <add key="root" value="../../" />
+ <add key="provider" value="MySql" />
+ <add key="development" value="Host=CLIFFORD;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+ <add key="production" value="Host=zippy;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+</settings>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/AssemblyInfo.cs b/struts-sandbox/overdrive/PhoneBook/Web/AssemblyInfo.cs
new file mode 100644
index 0000000..fad95dc
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/AssemblyInfo.cs
@@ -0,0 +1,60 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly : AssemblyTitle("")]
+[assembly : AssemblyDescription("")]
+[assembly : AssemblyConfiguration("")]
+[assembly : AssemblyCompany("")]
+[assembly : AssemblyProduct("")]
+[assembly : AssemblyCopyright("")]
+[assembly : AssemblyTrademark("")]
+[assembly : AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly : AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the "project output directory". The location of the project output
+// directory is dependent on whether you are working with a local or web project.
+// For local projects, the project output directory is defined as
+// <Project Directory>\obj\<Configuration>. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// For web projects, the project output directory is defined as
+// %HOMEPATH%\VSWebCache\<Machine Name>\<Project Directory>\obj\<Configuration>.
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly : AssemblyDelaySign(false)]
+[assembly : AssemblyKeyFile("")]
+[assembly : AssemblyKeyName("")]
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx
new file mode 100644
index 0000000..9b11143
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx
@@ -0,0 +1 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="AppGridControl.ascx.cs" Inherits="PhoneBook.Web.Controls.AppGridControl" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx.cs
new file mode 100644
index 0000000..bc2fe04
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx.cs
@@ -0,0 +1,42 @@
+using System;
+using Nexus.Core;
+using Nexus.Web;
+using PhoneBook.Core;
+
+namespace PhoneBook.Web.Controls
+{
+ public class AppGridControl : GridControl
+ {
+ protected override IEntryList NewContextList
+ {
+ get { return new AppEntryList(); }
+ }
+
+ private void Page_Load(object sender, EventArgs e)
+ {
+ // Put user code to initialize the page here
+ }
+
+ #region Web Form Designer generated code
+
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/AppGridControl.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx
new file mode 100644
index 0000000..b0273ca
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx
@@ -0,0 +1,24 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="Finder.ascx.cs" Inherits="PhoneBook.Web.Controls.Finder" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
+<table>
+ <tr>
+ <td colspan="6" >
+ <asp:Button ID="find" Runat="server"></asp:Button>
+ <INPUT onclick="javascript:window.print();" type="button" value="PRINT" name="print" id="print">
+ </td>
+ <tr>
+ <td>Last Name</td>
+ <td>First Name</td>
+ <td>Extension</td>
+ <td>User</td>
+ <td>Hire Date</td>
+ <td>Hours</td>
+ </tr>
+ <tr>
+ <td><asp:DropDownList ID="last_name_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="first_name_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="extension_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="user_name_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="hired_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="hours_list" Runat=server></asp:DropDownList></td>
+ </tr>
+</table>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx.cs
new file mode 100644
index 0000000..ba33dd7
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx.cs
@@ -0,0 +1,190 @@
+using System;
+using System.Web.UI.WebControls;
+using Nexus.Core.Helpers;
+using Nexus.Web;
+using PhoneBook.Core;
+using PhoneBook.Web.Forms;
+using WQD.Core.Controls;
+
+namespace PhoneBook.Web.Controls
+{
+ /// <summary>
+ /// Capture input values to filter a list of directory entries.
+ /// </summary>
+ ///
+ public class Finder : ViewControl
+ {
+ /// <summary>
+ /// Signal update to input filters
+ /// by passing FindArgs with the search critiers.
+ /// </summary>
+ ///
+ public event EventHandler Filter_Changed;
+
+ /// <summary>
+ /// Populate the entry finder's own controls.
+ /// </summary>
+ ///
+ public void Open()
+ {
+ IViewHelper h = ExecuteBind(App.ENTRY_FIND);
+ bool ok = (h.IsNominal);
+ if (!ok)
+ Page_Alert = h;
+ }
+
+ /// <summary>
+ /// Provide runtime instance of last_name_list filter.
+ /// </summary>
+ ///
+ protected DropDownList last_name_list;
+
+ /// <summary>
+ /// Provide runtime instance of first_name_list filter.
+ /// </summary>
+ ///
+ protected DropDownList first_name_list;
+
+ /// <summary>
+ /// Provide runtime instance of extension_list filter.
+ /// </summary>
+ ///
+ protected DropDownList extension_list;
+
+ /// <summary>
+ /// Provide runtime instance of user_name_list filter.
+ /// </summary>
+ ///
+ protected DropDownList user_name_list;
+
+ /// <summary>
+ /// Provide runtime instance of hired_list filter.
+ /// </summary>
+ ///
+ protected DropDownList hired_list;
+
+ /// <summary>
+ /// Provide runtime instance of hours_list filter.
+ /// </summary>
+ ///
+ protected DropDownList hours_list;
+
+ /// <summary>
+ /// Provide runtime instance of find filter.
+ /// </summary>
+ ///
+ protected Button find;
+
+ /// <summary>
+ /// Provide an array for filters so they can be handled as a group (or composite).
+ /// </summary>
+ /// <returns>Array of filter instances</returns>
+ ///
+ private DropDownList[] FilterList()
+ {
+ DropDownList[] lists = {last_name_list, first_name_list, extension_list, user_name_list, hired_list, hours_list};
+ return lists;
+ }
+
+ /// <summary>
+ /// Unselect all but the active filter.
+ /// </summary>
+ /// <param name="except">The active filter</param>
+ ///
+ private void Filter_Reset(DropDownList except)
+ {
+ int exceptIndex = 0;
+ if (except != null) exceptIndex = except.SelectedIndex;
+ foreach (DropDownList filter in FilterList())
+ {
+ filter.SelectedIndex = 0;
+ }
+ if (except != null) except.SelectedIndex = exceptIndex;
+ }
+
+ /// <summary>
+ /// Handle the SelectIndexChanged event for any of the filters
+ /// by capturing its settings
+ /// and raising the Filter_Changed event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void filter_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ IViewHelper helper = Catalog.GetHelperFor(App.ENTRY_LIST);
+ DropDownList list = sender as DropDownList;
+ string id = list.ID;
+ int v = id.LastIndexOf(ListSuffix);
+ string key = id.Substring(0, v);
+ helper.Criteria[key] = list.SelectedValue;
+ Filter_Reset(list);
+ Filter_Changed(this, new FindArgs(e, helper.Criteria));
+ }
+
+ /// <summary>
+ /// Handle the Click event of the Find button
+ /// by resetting the filters
+ /// and raising the Filter Changed event
+ /// so that the presentation will list all entries.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void find_Click(object sender, EventArgs e)
+ {
+ if (Filter_Changed == null) return;
+ Filter_Reset(null);
+ IViewHelper helper = Read(App.ENTRY_FIND);
+ Filter_Changed(this, new ViewArgs(helper));
+ }
+
+ /// <summary>
+ /// Handle page's load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ find.Text = Directory.msg_LIST_ALL_CMD;
+ find.Click += new EventHandler(find_Click);
+
+ foreach (DropDownList filter in FilterList())
+ {
+ filter.AutoPostBack = true;
+ filter.SelectedIndexChanged += new EventHandler(filter_SelectedIndexChanged);
+ }
+
+ if (!IsPostBack) Open();
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ ///
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx
new file mode 100644
index 0000000..5fbacd7
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx
@@ -0,0 +1,26 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="Finder2.ascx.cs" Inherits="PhoneBook.Web.Controls.Finder2" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
+<%@ Register TagPrefix="x" Namespace="Nexus.Web" Assembly="Nexus.Web" %>
+<table>
+ <tr>
+ <td colspan="6" >
+ <asp:Button ID="find" Runat="server"></asp:Button>
+ <INPUT onclick="javascript:window.print();" type="button" value="PRINT" name="cmd_print" id="cmd_print">
+ </td>
+ </tr>
+ <tr>
+ <td><x:TextLabel runat="server" id="last_name_label"></x:TextLabel></td>
+ <td><x:TextLabel runat="server" id="first_name_label"></x:TextLabel></td>
+ <td><x:TextLabel runat="server" id="extension_label"></x:TextLabel></td>
+ <td><x:TextLabel runat="server" id="user_name_label"></x:TextLabel></td>
+ <td><x:TextLabel runat="server" id="hired_label"></x:TextLabel></td>
+ <td><x:TextLabel runat="server" id="hours_label"></x:TextLabel></td>
+ </tr>
+ <tr>
+ <td><asp:DropDownList ID="last_name_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="first_name_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="extension_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="user_name_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="hired_list" Runat=server></asp:DropDownList></td>
+ <td><asp:DropDownList ID="hours_list" Runat=server></asp:DropDownList></td>
+ </tr>
+</table>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx.cs
new file mode 100644
index 0000000..2e23744
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using Nexus.Core.Helpers;
+using Nexus.Web;
+using PhoneBook.Core;
+
+namespace PhoneBook.Web.Controls
+{
+ /// <summary>
+ /// Capture input values to filter a list of directory entries.
+ /// </summary>
+ ///
+ public class Finder2 : ViewControl
+ {
+ /// <summary>
+ /// Signal update to input filters
+ /// by passing FindArgs with the search critiers.
+ /// </summary>
+ ///
+ public event EventHandler Filter_Changed;
+
+ /// <summary>
+ /// Populate the entry finder's own controls.
+ /// </summary>
+ ///
+ public void Open()
+ {
+ IViewHelper h = GetHelperFor(App.ENTRY_FIND);
+ ExecuteBind(h);
+ bool ok = (h.IsNominal);
+ if (!ok)
+ Page_Alert = h;
+ }
+
+ /// <summary>
+ /// Provide runtime instance of find Button.
+ /// </summary>
+ ///
+ protected Button find;
+
+ /// <summary>
+ /// Handle the Click event of the Find button
+ /// by resetting the filters
+ /// and raising the Filter Changed event
+ /// so that the presentation will list all entries.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void find_Click(object sender, EventArgs e)
+ {
+ if (Filter_Changed == null) return;
+ Filter_Reset(null);
+ IViewHelper helper = Read(App.ENTRY_LIST);
+ Filter_Changed(this, new ViewArgs(helper));
+ }
+
+ /// <summary>
+ /// Unselect all but the active filter.
+ /// </summary>
+ /// <param name="except">The active filter</param>
+ ///
+ private void Filter_Reset(DropDownList except)
+ {
+ // Reset filter controls
+ int exceptIndex = 0;
+ if (except != null) exceptIndex = except.SelectedIndex;
+ foreach (Control c in Controls)
+ {
+ if (IsListControl(c))
+ {
+ DropDownList x = (DropDownList) c;
+ x.SelectedIndex = 0;
+ }
+ }
+ if (except != null) except.SelectedIndex = exceptIndex;
+ }
+
+ /// <summary>
+ /// Handle the SelectIndexChanged event for any of the filters
+ /// by capturing its settings
+ /// and raising the Filter_Changed event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void filter_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ IViewHelper helper = Catalog.GetHelperFor(App.ENTRY_LIST);
+ DropDownList list = sender as DropDownList;
+ string id = list.ID;
+ int v = id.LastIndexOf(ListSuffix);
+ string key = id.Substring(0, v);
+ helper.Criteria[key] = list.SelectedValue;
+ Filter_Reset(list);
+ Filter_Changed(this, new ViewArgs(helper));
+ }
+
+ private void Page_Load(object sender, EventArgs e)
+ {
+ find.Click += new EventHandler(find_Click);
+ foreach (Control control in Controls)
+ {
+ if (IsListControl(control))
+ {
+ DropDownList filter = (DropDownList) control;
+ filter.SelectedIndexChanged += new EventHandler(filter_SelectedIndexChanged);
+ filter.AutoPostBack = true;
+ }
+ }
+ }
+
+ #region Web Form Designer generated code
+
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Finder2.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx
new file mode 100644
index 0000000..cb94482
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx
@@ -0,0 +1,10 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="InitialFilter.ascx.cs" Inherits="PhoneBook.Web.Controls.InitialFilter" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
+<asp:repeater id="letters" runat="server">
+ <itemtemplate>
+ <asp:linkbutton id="letter" runat="server"
+ commandname="filter"
+ commandargument='<%# DataBinder.Eval(Container, "DataItem.Letter")%>' >
+ <%# DataBinder.Eval(Container, "DataItem.Letter")%>
+ </asp:linkbutton>
+ </itemtemplate>
+</asp:repeater>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx.cs
new file mode 100644
index 0000000..2a12e60
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx.cs
@@ -0,0 +1,8 @@
+using Nexus.Web.Controls;
+
+namespace PhoneBook.Web.Controls
+{
+ public class InitialFilter : LetterFilter
+ {
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/InitialFilter.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx
new file mode 100644
index 0000000..504cd1f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx
@@ -0,0 +1,13 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="Lister.ascx.cs" Inherits="PhoneBook.Web.Controls.Lister" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
+<asp:DataGrid id="list" Runat="server" AutoGenerateColumns=False>
+ <HeaderStyle CssClass="HeaderStyle" BackColor="#CCCC99"></HeaderStyle>
+ <AlternatingItemStyle CssClass="AlternatingItemStyle" BackColor="#CCCC99"></AlternatingItemStyle>
+ <Columns>
+ <asp:BoundColumn DataField="last_name" HeaderText="Last Name"></asp:BoundColumn>
+ <asp:BoundColumn DataField="first_name" HeaderText="First Name"></asp:BoundColumn>
+ <asp:BoundColumn DataField="extension" HeaderText="Extension"></asp:BoundColumn>
+ <asp:BoundColumn DataField="user_name" HeaderText="User"></asp:BoundColumn>
+ <asp:BoundColumn DataField="hired" HeaderText="Hire Date"></asp:BoundColumn>
+ <asp:BoundColumn DataField="hours" HeaderText="Hours"></asp:BoundColumn>
+ </Columns>
+</asp:DataGrid>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx.cs
new file mode 100644
index 0000000..3d3337e
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections;
+using System.Web.UI.WebControls;
+using Nexus.Core.Helpers;
+using Nexus.Web;
+using PhoneBook.Core;
+
+namespace PhoneBook.Web.Controls
+{
+ /// <summary>
+ /// Present matching directory entries.
+ /// </summary>
+ ///
+ public class Lister : ViewControl
+ {
+ /// <summary>
+ /// Populate the DataGrid with directory entries matching the filter settings.
+ /// </summary>
+ /// <param name="criteria">Filter settings</param>
+ ///
+ public void Open(IDictionary criteria)
+ {
+ IViewHelper helper = ReadExecute(App.ENTRY_LIST, criteria);
+ bool ok = helper.IsNominal;
+ if (!ok) Page_Alert = helper;
+ else
+ {
+ IList result = helper.Outcome;
+ list.DataSource = result;
+ list.DataBind();
+ }
+ }
+
+ /// <summary>
+ /// Provide reference to datagrid instance.
+ /// </summary>
+ ///
+ protected DataGrid list;
+
+ /// <summary>
+ /// Handle page's load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ if (IsPostBack) return;
+ Open(null);
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ ///
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx
new file mode 100644
index 0000000..d63796b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx
@@ -0,0 +1,8 @@
+<%@ Control Language="c#" AutoEventWireup="false" Codebehind="Lister2.ascx.cs" Inherits="PhoneBook.Web.Controls.Lister2" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
+<asp:Label ID="hint" Runat="server"></asp:Label>
+<asp:DataGrid id="list" Runat="server" AutoGenerateColumns="False"
+ PageSize="2" AllowPaging="true" PagerStyle-Mode="NumericPages">
+ <HeaderStyle CssClass="HeaderStyle" BackColor="#CCCC99"></HeaderStyle>
+ <AlternatingItemStyle CssClass="AlternatingItemStyle" BackColor="#CCCC99"></AlternatingItemStyle>
+</asp:DataGrid>
+<p><asp:Button ID="add" Runat="server"></asp:Button></p>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx.cs
new file mode 100644
index 0000000..c305500
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx.cs
@@ -0,0 +1,257 @@
+using System;
+using System.Collections;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using Nexus.Core.Profile;
+using PhoneBook.Core;
+
+namespace PhoneBook.Web.Controls
+{
+ /// <summary>
+ /// Present matching directory entries.
+ /// </summary>
+ public class Lister2 : AppGridControl
+ {
+ /// <summary>
+ /// Provide instance of DataGrid control
+ /// </summary>
+ ///
+ protected DataGrid list;
+
+ /// <summary>
+ /// Provide instance of Add button.
+ /// </summary>
+ ///
+ protected Button add;
+
+ /// <summary>
+ /// Toggle off the add button when adding.
+ /// </summary>
+ ///
+ protected override void list_Add()
+ {
+ base.list_Add();
+ add.Visible = false;
+ }
+
+ /// <summary>
+ /// Toggle off the add button when editing.
+ /// </summary>
+ ///
+ protected override void list_Edit(int index)
+ {
+ base.list_Edit(index);
+ add.Visible = false;
+ }
+
+ protected override IViewHelper Save(string key, ControlCollection controls)
+ {
+ IViewHelper h = base.Save(key, controls);
+ if (h.IsNominal)
+ {
+ bool needEditorValue = (null == h.Criteria[App.EDITOR]);
+ // FIXME: [OVR-24] - Template columns not passed by DataGridCommandEventArgs
+ if (needEditorValue)
+ {
+ h.Criteria[App.EDITOR] = FindControlValue(App.EDITOR);
+ }
+ h.Execute();
+ }
+ return h;
+ }
+
+ public override ControlCollection GetControls(DataGridCommandEventArgs e)
+ {
+ DataGrid grid = Grid;
+ ControlCollection controls = new ControlCollection(grid);
+ foreach (TableCell cell in e.Item.Cells)
+ {
+ for (int i = 0; i < cell.Controls.Count; i++)
+ controls.Add(cell.Controls[i]);
+ }
+
+ /*
+ // What the scripts usually do, but our EDITOR_CELL is null.
+ const int EDITOR_CELL = 8;
+ TableCell o = e.Item.Cells[EDITOR_CELL];
+ DropDownList r = (DropDownList) o.FindControl(App.EDITOR);
+ controls.Add(r);
+ object o = e.Item.FindControl(App.EDITOR);
+
+ // The template is in the DataGrid, just not in the event
+ TableRow item = grid.Items[1];
+ foreach (TableCell cell in item.Cells)
+ {
+ for (int i = 0; i < cell.Controls.Count; i++)
+ controls.Add(cell.Controls[i]);
+ }
+ */
+
+ return controls;
+ }
+
+ /// <summary>
+ /// Toggle add button on and present Grid.
+ /// </summary>
+ /// <returns>True if nominal</returns>
+ ///
+ public override bool Open()
+ {
+ add.Visible = true;
+ return base.Open ();
+ }
+
+ /// <summary>
+ /// Complete loading Grid
+ /// after other members have initialized.
+ /// </summary>
+ ///
+ private void Grid_Load()
+ {
+ AppUserProfile profile = Session[UserProfile.USER_PROFILE] as AppUserProfile;
+ HasEditColumn = profile.IsEditor;
+ }
+
+ private IKeyValueList _EditorKeys = null;
+
+ private IKeyValueList EditorKeyList
+ {
+ get
+ {
+ if (_EditorKeys == null)
+ {
+ IKeyValueList data = new KeyValueList();
+ // FIXME: Obtain from Spring?
+ data.Add(new KeyValue(" ", "--v--"));
+ data.Add(new KeyValue("0", "NO"));
+ data.Add(new KeyValue("1", "YES"));
+ _EditorKeys = data;
+ }
+ return _EditorKeys;
+ }
+ }
+
+ /// <summary>
+ /// ID Token to indicate a Label control.
+ /// </summary>
+ ///
+ private static string LABEL = "_label";
+
+ /// <summary>
+ /// Assemble an IGridConfig for an attribute.
+ /// </summary>
+ /// <param name="dataField">The attribute ID</param>
+ /// <returns>An IGridConfig instance</returns>
+ private IGridConfig GetConfig(string dataField)
+ {
+ string headerText = GetMessage(dataField + LABEL);
+ IGridConfig config = new GridConfig(dataField, headerText);
+ return config;
+ }
+
+ /// <summary>
+ /// Initialize our Grid instance
+ /// by setting the columns, labels,
+ /// and other dynamic attributes.
+ /// </summary>
+ ///
+ private void Grid_Init(DataGrid grid)
+ {
+ Grid = grid;
+ FindCommand = App.ENTRY_FIND;
+ ListCommand = App.ENTRY_LIST;
+ SaveCommand = App.ENTRY_SAVE;
+ DataKeyField = App.ENTRY_KEY;
+ AllowCustomPaging = true;
+ PageSize = 2;
+ // HasEditColumn = true; // Set from profile
+
+ IList cols = new ArrayList(7);
+ cols.Add(GetConfig(App.LAST_NAME));
+ cols.Add(GetConfig(App.FIRST_NAME));
+ cols.Add(GetConfig(App.EXTENSION));
+ cols.Add(GetConfig(App.USER_NAME));
+ cols.Add(GetConfig(App.HIRED));
+ cols.Add(GetConfig(App.HOURS));
+ IGridConfig c = GetConfig(App.EDITOR);
+ c.ItemTemplate = new KeyValueTemplate(App.EDITOR, EditorKeyList);
+ c.EditItemTemplate = new DropDownListTemplate(App.EDITOR, EditorKeyList);
+ cols.Add(c);
+ Configs = cols;
+ }
+
+ /// <summary>
+ /// Provide a runtime instance of the label over the DataGrid.
+ /// </summary>
+ ///
+ public Label hint;
+
+ /// <summary>
+ /// Update the page index hint.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void this_ListPageIndexChanged(object sender, EventArgs e)
+ {
+ ListPageIndexChangedArgs a = e as ListPageIndexChangedArgs;
+ hint.Text = ListPageIndexChanged_Message(a);
+ }
+
+ /// <summary>
+ /// Handle Page Init event by obtaining the user profile
+ /// and initalizing the controls.
+ /// </summary>
+ ///
+ private void Page_Init()
+ {
+ Grid_Init(list);
+
+ ListPageIndexChanged += new EventHandler(this_ListPageIndexChanged);
+ add.Click += new EventHandler(list_Add);
+ }
+
+ /// <summary>
+ /// Handle page's load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ Grid_Load();
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ Page_Init();
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Controls/Lister2.ascx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx
new file mode 100644
index 0000000..d66f7f7
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx
@@ -0,0 +1,34 @@
+<%@ Page language="c#" Codebehind="Directory.aspx.cs" AutoEventWireup="false" Inherits="PhoneBook.Web.Forms.Directory" %>
+<%@ Register TagPrefix="app" TagName="Finder" Src="../Controls/Finder.ascx" %>
+<%@ Register TagPrefix="app" TagName="Lister" Src="../Controls/Lister.ascx" %>
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<HTML>
+ <HEAD>
+ <title>PhoneBook Directory</title>
+ <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
+ <meta name="CODE_LANGUAGE" Content="C#">
+ <meta name="vs_defaultClientScript" content="JavaScript">
+ <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
+ <LINK href="default.css" type="text/css" rel="stylesheet">
+ </HEAD>
+ <body>
+ <h1>PhoneBook Directory</h1>
+ <form id="form1" method="post" runat="server">
+
+ <!-- ERROR -->
+ <asp:Panel id="error_panel" runat="server">
+ <p><asp:Label id="error_label" runat="server"></asp:Label></p>
+ <hr>
+ </asp:Panel>
+
+ <!-- PROMPT -->
+ <p>Select a filter to display fewer entries.</p>
+
+ <app:Finder id="finder" runat="server"></app:Finder>
+
+ <app:Lister id="lister" runat="server"></app:Lister>
+
+ </form>
+ </body>
+</HTML>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx.cs
new file mode 100644
index 0000000..74c57de
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using Nexus.Web;
+using PhoneBook.Web.Controls;
+
+namespace PhoneBook.Web.Forms
+{
+ /// <summary>
+ /// Display a list of employees with their telephone extension [OVR-5].
+ /// </summary>
+ /// <remarks><p>
+ /// This is a starter version of the Directory page
+ /// that presents the list
+ /// without offering more advanced features.
+ /// </p></remarks>
+ ///
+ public class Directory : Page
+ {
+ #region Messages
+
+ /// <summary>
+ /// Provide a message for the List All command.
+ /// </summary>
+ ///
+ public const string msg_LIST_ALL_CMD = "SHOW ALL";
+
+ #endregion
+
+ #region Page Properties
+
+ protected Panel error_panel;
+ protected Label error_label;
+
+ /// <summary>
+ /// Display a list of error messages.
+ /// </summary>
+ public IViewHelper Page_Error
+ {
+ set
+ {
+ error_label.Text = value.AlertsText;
+ error_panel.Visible = true;
+ }
+ }
+
+ /// <summary>
+ /// Provide filed for Catalog property.
+ /// </summary>
+ private IRequestCatalog _Catalog;
+
+ /// <summary>
+ /// Provide reference to the Catalog (object factory) for this application.
+ /// </summary>
+ /// <remarks><p>
+ /// Subclasses adding EventHandlers
+ /// should pass a reference to themselves with a ViewArgs instance,
+ /// encapsulating the Helper.
+ /// </p></remarks>
+ public virtual IRequestCatalog Catalog
+ {
+ get { return _Catalog; }
+ set { _Catalog = value; }
+ }
+
+ #endregion
+
+ #region Event handlers
+
+ /// <summary>
+ /// Present matching directory entries.
+ /// </summary>
+ ///
+ protected Lister lister;
+
+ /// <summary>
+ /// Capture input values to filter a list of directory entries.
+ /// </summary>
+ ///
+ protected Finder finder;
+
+ /// <summary>
+ /// Handle Filter Changed event by opening the Lister control
+ /// and passing through the search criteria
+ /// provided by the event arts.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguements</param>
+ ///
+ protected void finder_FilterChanged(object sender, EventArgs e)
+ {
+ ViewArgs a = e as ViewArgs;
+ IViewHelper helper = a.Helper;
+ lister.Open(helper.Criteria);
+ }
+
+ #endregion
+
+ #region Page Events
+
+ /// <summary>
+ /// Handle View_Error event by presenting the error message
+ /// provided by the Helper class.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void View_Error(object sender, EventArgs e)
+ {
+ ViewArgs v = e as ViewArgs;
+ if (v == null) throw new ArgumentException("View_Error: !(e is ViewArgs)");
+ IViewHelper helper = v.Helper;
+ if (helper != null) Page_Error = helper;
+ else throw new ArgumentException("View_Error: (e.helper==null)");
+ }
+
+ /// <summary>
+ /// Initialize controls by registering for View Error events
+ /// and passing through our Catalog instance.
+ /// </summary>
+ /// <param name="c">Control to initialize</param>
+ ///
+ private void View_Init(ViewControl c)
+ {
+ c.View_Alert += new EventHandler(View_Error);
+ c.Catalog = Catalog; // ISSUE: Why isn't control injection working?
+ }
+
+ /// <summary>
+ /// Handle Page Init event by initalizing the controls.
+ /// </summary>
+ ///
+ private void Page_Init()
+ {
+ View_Init(finder);
+ View_Init(lister);
+ }
+
+ /// <summary>
+ /// Handle page's load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ error_panel.Visible = false;
+ }
+
+ #endregion
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ Page_Init();
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ ///
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory.aspx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx
new file mode 100644
index 0000000..f7e982f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx
@@ -0,0 +1,41 @@
+<%@ Register TagPrefix="app" TagName="Finder" Src="../Controls/Finder2.ascx" %>
+<%@ Register TagPrefix="app" TagName="Lister" Src="../Controls/Lister2.ascx" %>
+<%@ Register TagPrefix="app" TagName="Filter" Src="../Controls/InitialFilter.ascx" %>
+<%@ Page language="c#" Codebehind="Directory2.aspx.cs" AutoEventWireup="false" Inherits="PhoneBook.Web.Forms.Directory2" %>
+<%@ Register TagPrefix="ovr" Namespace="Nexus.Web" Assembly="Nexus.Web" %>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<HTML>
+ <HEAD>
+ <title runat="server" id="title"></title>
+ <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
+ <meta name="CODE_LANGUAGE" Content="C#">
+ <meta name="vs_defaultClientScript" content="JavaScript">
+ <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
+ <LINK href="default.css" type="text/css" rel="stylesheet">
+ </HEAD>
+ <body>
+ <h1 id="heading" runat="server"></h1>
+ <form id="form1" method="post" runat="server">
+ <p><asp:Label ID="greeting" Runat="server"></asp:Label>
+ <asp:Label ID="profile_label" Runat="server"></asp:Label></p>
+ <!-- ERROR -->
+ <asp:Panel ID="error_panel" Runat="server">
+ <P>
+ <asp:Label id="error_label" Runat="server"></asp:Label></P>
+ <HR>
+ </asp:Panel>
+ <!-- PROMPT -->
+ <asp:Panel ID="prompt_panel" Runat="server">
+ <P>
+ <asp:Label id="prompt_label" Runat="server"></asp:Label></P>
+ <HR>
+ </asp:Panel>
+ <!-- FINDER -->
+ <app:Finder id="finder" Runat="server"></app:Finder>
+ <!-- LETTER FILTER -->
+ <app:Filter id="letter_filter" Runat="server"></app:Filter>
+ <!-- LISTER -->
+ <app:Lister id="lister" runat="server"></app:Lister>
+ </form>
+ </body>
+</HTML>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx.cs b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx.cs
new file mode 100644
index 0000000..9fa28bc
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx.cs
@@ -0,0 +1,305 @@
+using System;
+using System.Security.Principal;
+using System.Web.UI.HtmlControls;
+using System.Web.UI.WebControls;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using Nexus.Core.Profile;
+using Nexus.Web;
+using PhoneBook.Core;
+using PhoneBook.Web.Controls;
+using Spring.Web.UI;
+using WQD.Core.Controls;
+
+namespace PhoneBook.Web.Forms
+{
+ /// <summary>
+ /// Maintain a list of employees with their telephone extension [OVR-5].
+ /// </summary>
+ /// <remarks><p>
+ /// This version of the directory page supports paging and editing
+ /// through use of the Nexus GridControl.
+ /// </p></remarks>
+ ///
+ public class Directory2 : Page
+ {
+ #region Base Page members
+
+ /// <summary>
+ /// Provide field for AppUserProfile property.
+ /// </summary>
+ ///
+ private AppUserProfile _Profile;
+
+ /// <summary>
+ /// Expose the user's profile.
+ /// </summary>
+ ///
+ protected AppUserProfile Profile
+ {
+ set
+ {
+ if (value == null)
+ _Profile = NewProfile();
+ else
+ _Profile = value;
+
+ }
+ get { return _Profile; }
+ }
+
+ /// <summary>
+ /// Create or retrieve an AppUserProfile
+ /// based on the client's WindowsIdentity.
+ /// </summary>
+ /// <returns>A new or prexisting AppUserProfile</returns>
+ ///
+ protected AppUserProfile NewProfile()
+ {
+ WindowsIdentity id = WindowsIdentity.GetCurrent();
+ AppUserProfile profile = new AppUserProfile(id);
+ Session[UserProfile.USER_PROFILE] = profile;
+
+ IViewHelper helper = Catalog.GetHelperFor(App.ENTRY);
+ helper.Criteria[App.USER_NAME] = profile.UserId;
+ helper.Execute();
+ if (helper.IsNominal)
+ {
+ string editor = helper.Criteria[App.EDITOR] as string;
+ // ISSUE: Need constant for "1" (true)
+ bool isEditor = ((editor != null) && (editor.Equals("1")));
+ profile.IsEditor = isEditor;
+ if (editor != null)
+ {
+ AppEntry entry = new AppEntry();
+ entry.AddAll(helper.Criteria);
+ profile.Entry = entry;
+ }
+ }
+ return profile;
+ }
+
+ /// <summary>
+ /// Present a list of error messages.
+ /// </summary>
+ ///
+ protected IViewHelper Page_Error
+ {
+ set
+ {
+ error_label.Text = value.AlertsText;
+ error_panel.Visible = true;
+ }
+ }
+
+ protected Panel prompt_panel;
+ protected Label prompt_label;
+
+ /// <summary>
+ /// Display a Prompt message.
+ /// </summary>
+ ///
+ protected string Page_Prompt
+ {
+ set { prompt_label.Text = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for Catalog property.
+ /// </summary>
+ ///
+ private IRequestCatalog _Catalog;
+
+ /// <summary>
+ /// Expose the Catalog (object factory) for this application.
+ /// </summary>
+ /// <remarks><p>
+ /// Subclasses adding EventHandlers
+ /// should pass a reference to themselves with a ViewArgs instance,
+ /// encapsulating the Helper.
+ /// </p></remarks>
+ ///
+ public virtual IRequestCatalog Catalog
+ {
+ get { return _Catalog; }
+ set { _Catalog = value; }
+ }
+
+ /// <summary>
+ /// Handle View Error
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void View_Error(object sender, EventArgs e)
+ {
+ ViewArgs v = e as ViewArgs;
+ if (v == null) throw new ArgumentException("View_Error: !(e is ViewArgs)");
+ IViewHelper helper = v.Helper;
+ if (helper != null) Page_Error = helper;
+ else throw new ArgumentException("View_Error: (e.helper==null)");
+ }
+
+ /// <summary>
+ /// Initialize User Controls by handling View Error events
+ /// and passing through our Catalog reference.
+ /// </summary>
+ /// <param name="c">Control to initialize</param>
+ ///
+ private void View_Init(ViewControl c)
+ {
+ c.View_Alert += new EventHandler(View_Error);
+ c.Catalog = Catalog; // ISSUE: Why isn't control injection working?
+ }
+
+ private void Page_PreRender(object sender, EventArgs e)
+ {
+ greeting.Text = GetMessage(greeting.ID);
+ title.InnerText = GetMessage(App.DIRECTORY_TITLE);
+ heading.InnerText = GetMessage(App.DIRECTORY_HEADING);
+ }
+
+ #endregion
+
+ #region Event handlers
+
+ /// <summary>
+ /// Filter Lister for Directory
+ /// </summary>
+ ///
+ protected InitialFilter letter_filter;
+
+ /// <summary>
+ /// Apply letter filter to WNE Facilty List.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguments</param>
+ ///
+ private void letter_filter_View_Filter(object sender, EventArgs e)
+ {
+ FindArgs a = e as FindArgs;
+ lister.Read(a.Criteria);
+ lister.Reset();
+ }
+
+ /// <summary>
+ /// List matching directory entries.
+ /// </summary>
+ ///
+ protected Lister2 lister;
+
+ /// <summary>
+ /// Capture input values to filter a list of directory entries.
+ /// </summary>
+ ///
+ protected Finder2 finder;
+
+ /// <summary>
+ /// Handle Filter Changed event by opening the Lister control
+ /// and passing through the search criteria
+ /// provided by the event args,
+ /// so that the Lister control can present the matching entities.
+ /// </summary>
+ /// <remarks>
+ /// </remarks>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime arguements</param>
+ ///
+ protected void finder_Filter_Changed(object sender, EventArgs e)
+ {
+ ViewArgs a = e as ViewArgs;
+ IViewHelper helper = a.Helper;
+ lister.Reset(helper.Criteria); // Runs the list command with new criteria
+ }
+
+ #endregion
+
+ #region Page Properties
+
+ protected HtmlGenericControl title;
+ protected HtmlGenericControl heading;
+ protected Label greeting;
+ protected Label profile_label;
+ protected Panel error_panel;
+ protected Label error_label;
+
+ #endregion
+
+ #region Page Events
+
+ /// <summary>
+ /// Handle Page Init event by obtaining the user profile
+ /// and initalizing the controls.
+ /// </summary>
+ ///
+ private void Page_Init()
+ {
+ Profile = Session[UserProfile.USER_PROFILE] as AppUserProfile;
+ PreRender += new EventHandler(Page_PreRender);
+
+ View_Init(finder);
+
+ View_Init(letter_filter);
+ letter_filter.View_Filter += new EventHandler(letter_filter_View_Filter);
+ IViewHelper helper = Catalog.GetHelperFor(App.ENTRY_INITIAL);
+
+ helper.Execute();
+ letter_filter.Open(helper.Outcome);
+
+ View_Init(lister);
+ finder.Filter_Changed += new EventHandler(finder_Filter_Changed);
+ }
+
+ /// <summary>
+ /// Handle page's load event.
+ /// </summary>
+ /// <param name="sender">Event source</param>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ private void Page_Load(object sender, EventArgs e)
+ {
+ error_panel.Visible = false;
+ if (!IsPostBack)
+ {
+ Page_Prompt = GetMessage(App.DIRECTORY_PROMPT);
+ string name = Profile.FullName;
+ if (name == null)
+ profile_label.Text = Profile.UserId;
+ else
+ profile_label.Text = name;
+ // UserLocale = Profile.Locale;
+ finder.Open();
+ }
+ }
+
+ #endregion
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Initialize components.
+ /// </summary>
+ /// <param name="e">Runtime parameters</param>
+ ///
+ protected override void OnInit(EventArgs e)
+ {
+ //
+ // CODEGEN: This call is required by the ASP.NET Web Form Designer.
+ //
+ InitializeComponent();
+ base.OnInit(e);
+ Page_Init();
+ }
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ ///
+ private void InitializeComponent()
+ {
+ this.Load += new EventHandler(this.Page_Load);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx.resx b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Directory2.aspx.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/Web.config b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Web.config
new file mode 100644
index 0000000..e8626e7
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/Web.config
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+
+ <configSections>
+ <sectionGroup name="spring">
+ <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
+ </sectionGroup>
+ </configSections>
+
+ <spring>
+
+ <context type="Spring.Context.Support.WebApplicationContext, Spring.Web">
+ <resource uri="config://spring/objects"/>
+ </context>
+
+ <objects xmlns="http://www.springframework.net">
+
+ <object id="Directory" type="Directory.aspx">
+ <property name="Catalog">
+ <ref object="Catalog"/>
+ </property>
+ </object>
+
+ <object id="Directory2" type="Directory2.aspx">
+ <property name="Catalog">
+ <ref object="Catalog"/>
+ </property>
+ </object>
+
+ <!-- User Controls -->
+
+ <object id="ViewControl" abstract="true">
+ <property name="Catalog">
+ <ref object="Catalog"/>
+ </property>
+ </object>
+ <object id="PhoneBook.Web.Controls.Finder" abstract="true" parent="ViewControl"/>
+ <object id="PhoneBook.Web.Controls.Lister" abstract="true" parent="ViewControl"/>
+
+ </objects>
+
+ </spring>
+</configuration>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Forms/default.css b/struts-sandbox/overdrive/PhoneBook/Web/Forms/default.css
new file mode 100644
index 0000000..a3e9c97
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Forms/default.css
@@ -0,0 +1,115 @@
+body
+{
+ background: #FFFFFF;
+ color: black;
+ margin: 0% 5% 0% 10%;
+ font-family: sans-serif;
+}
+
+A:hover { font-weight:bold; }
+
+h1, h2, h3, h4, h5, h6
+{
+ font-family: Verdana,Arial,Helvetica,sans-serif;
+ color:#003399;
+}
+
+h1
+{
+ font-size:18pt;
+}
+
+.HeaderStyle
+{
+ background-color:#003399;
+ color:#FFFFFF;
+ font-weight:bold;
+ padding: 30px 10px;
+}
+
+.ItemStyle
+{
+ background-color:#EEEEEE;
+ color:#000000;
+ border-top-width: thin;
+ border-right-width: thin;
+ border-bottom-width: thin;
+ border-left-width: thin;
+ border-top-style: none;
+ border-right-style: solid;
+ border-bottom-style: none;
+ border-left-style: solid;
+ border-top-color: #000000;
+ border-right-color: #000000;
+ border-bottom-color: #000000;
+ border-left-color: #000000;
+ padding: 10px;
+}
+
+.AlternatingItemStyle
+{
+ background-color:#DDDDDD;
+ color:#000000;
+ padding: 10px;
+}
+
+.SelectedItemStyle
+{
+ background-color:#9999FF;
+ font-style:italic;
+ color:#000000;
+}
+
+.EditItemStyle
+{
+ background-color:#FF9F9F;
+ font-style:italic;
+}
+
+.PagerStyle a
+{
+ font-style:italic;
+ font-size:18px;
+ text-decoration:none;
+}
+
+.HighlightedItemStyle
+{
+ background-color:#9999CC;
+ cursor:pointer;
+}
+
+td.readonly
+{
+ font-weight:bold;
+}
+
+td.hint {
+ font-size:80%;
+ font-family:Verdana,Arial,Helvetica,sans-serif;
+ font-weight:normal;
+}
+
+td.subtitle {
+ background-color:#FFFFFF;
+ font-family:Verdana,Arial,Helvetica,sans-serif;
+ font-weight:bold;
+}
+
+td.title {
+ font-size:140%;
+ font-family:Verdana,Arial,Helvetica,sans-serif;
+ font-weight:bold;
+}
+.DataGridStyle {
+ margin: 0px;
+ padding: 10px;
+}
+td {
+ padding: 0px 10px;
+}
+
+.app_name
+{
+ font-size:10pt;
+}
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Global.asax b/struts-sandbox/overdrive/PhoneBook/Web/Global.asax
new file mode 100644
index 0000000..f24d725
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="PhoneBook.Global" %>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Global.asax.cs b/struts-sandbox/overdrive/PhoneBook/Web/Global.asax.cs
new file mode 100644
index 0000000..392e32f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Global.asax.cs
@@ -0,0 +1,67 @@
+using System;
+using System.ComponentModel;
+using System.Web;
+
+namespace PhoneBook
+{
+ /// <summary>
+ /// Summary description for Global.
+ /// </summary>
+ public class Global : HttpApplication
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private IContainer components = null;
+
+ public Global()
+ {
+ InitializeComponent();
+ }
+
+ protected void Application_Start(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Session_Start(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_BeginRequest(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_EndRequest(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_AuthenticateRequest(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_Error(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Session_End(Object sender, EventArgs e)
+ {
+ }
+
+ protected void Application_End(Object sender, EventArgs e)
+ {
+ }
+
+ #region Web Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.components = new Container();
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Global.asax.resx b/struts-sandbox/overdrive/PhoneBook/Web/Global.asax.resx
new file mode 100644
index 0000000..dd0ea4d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Global.asax.resx
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Objects-Web.xml b/struts-sandbox/overdrive/PhoneBook/Web/Objects-Web.xml
new file mode 100644
index 0000000..a0c1a45
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Objects-Web.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <import resource="web://~/Resources/AppBase.xml"/>
+ <import resource="web://~/Resources/AppConfig.xml"/>
+ <import resource="web://~/Resources/AppFields.xml"/>
+ <import resource="web://~/Resources/Catalog.xml"/>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Objects.xml b/struts-sandbox/overdrive/PhoneBook/Web/Objects.xml
new file mode 100644
index 0000000..0173b9e
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Objects.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <import resource="web://~/Resources/AppBase.xml"/>
+ <import resource="web://~/Resources/AppConfig.xml"/>
+ <import resource="web://~/Resources/AppFields.xml"/>
+ <import resource="web://~/Resources/Catalog.xml"/>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/PhoneBook.ashx b/struts-sandbox/overdrive/PhoneBook/Web/PhoneBook.ashx
new file mode 100644
index 0000000..3c5cc46
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/PhoneBook.ashx
@@ -0,0 +1,98 @@
+<%@ WebHandler Class="JayrockWeb.PhoneBook" Language="C#" %>
+
+using System;
+using System.Collections;
+using Agility.Extras.Spring;
+using Jayrock.JsonRpc;
+using Jayrock.JsonRpc.Web;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using PhoneBook.Core;
+using Spring.Context;
+
+namespace JayrockWeb
+{
+ public class PhoneBook : JsonRpcHandler
+ {
+
+ private IRequestCatalog catalog = null;
+
+ private IRequestCatalog GetCatalog()
+ {
+ if (catalog == null)
+ {
+ IApplicationContext factory = Objects.Factory();
+ catalog = factory.GetObject(App.CATALOG_KEY) as IRequestCatalog;
+ }
+ return catalog;
+ }
+
+ private RequestContext Execute(string command)
+ {
+ return (RequestContext) GetCatalog().ExecuteRequest(command);
+ }
+
+ [JsonRpcMethod(App.LAST_NAME_LIST, Idempotent = true)]
+ [JsonRpcHelp("Returns Last Name List as an array.")]
+ public string[] last_name_list()
+ {
+ RequestContext context = Execute(App.LAST_NAME_LIST);
+ KeyValueList list = context.Outcome as KeyValueList;
+ ArrayList names = new ArrayList(list.Count);
+ foreach (KeyValue k in list)
+ {
+ names.Add(k.Value);
+ }
+ return (string[]) names.ToArray(typeof (String));
+ }
+
+ [JsonRpcMethod(App.ENTRY_LIST, Idempotent = true)]
+ [JsonRpcHelp("Returns the complete directory as an array of formatted IDictionary objects.")]
+ public AppEntryList entry_list()
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY_LIST);
+ helper.Execute();
+ // if helper.IsNominal ...
+ AppEntryList list = helper.Outcome as AppEntryList;
+ return list;
+ }
+
+ [JsonRpcMethod(App.ENTRY, Idempotent = true)]
+ [JsonRpcHelp("Returns an entry by key.")]
+ public AppEntry entry(string key)
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY);
+ helper.Criteria[App.ENTRY_KEY] = key;
+ helper.Execute();
+ // if helper.IsNominal ...
+ AppEntry entry = new AppEntry(helper.Criteria);
+ return entry;
+ }
+
+ [JsonRpcMethod(App.ENTRY_SAVE, Idempotent = true)]
+ [JsonRpcHelp("Saves the entry, insert or updating as appropriate.")]
+ public AppEntry entry_save(IDictionary input)
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY_SAVE);
+ helper.Read(input,true);
+ helper.Execute();
+ // if helper.IsNominal ...
+ AppEntry entry = new AppEntry(helper.Criteria);
+ return entry;
+ }
+
+ [JsonRpcMethod(App.ENTRY_DELETE, Idempotent = true)]
+ [JsonRpcHelp("Deletes an entry by key.")]
+ public AppEntry entry_delete(string key)
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY_DELETE);
+ helper.Criteria[App.ENTRY_KEY] = key;
+ helper.Execute();
+ // if helper.IsNominal ...
+ AppEntry entry = new AppEntry(helper.Criteria);
+ return entry;
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/PhoneBook.html b/struts-sandbox/overdrive/PhoneBook/Web/PhoneBook.html
new file mode 100644
index 0000000..2a67415
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/PhoneBook.html
@@ -0,0 +1,293 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <title>PhoneBook</title>
+ <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
+ <meta name=ProgId content=VisualStudio.HTML>
+ <meta name=Originator content="Microsoft Visual Studio .NET 7.1">
+ <script language="javascript" src="PhoneBook.ashx?proxy&v=2"></script>
+ <script language="javascript" src="js/dojo/dojo.js"></script>
+ <script language="javascript">
+ dojo.require("dojo.io.*");
+ dojo.require("dojo.event.*");
+ dojo.require("dojo.html.*");
+ dojo.require("dojo.json");
+ dojo.require("dojo.widget.FilteringTable");
+ dojo.hostenv.writeIncludes();
+
+ /* call server */
+
+ function server(call)
+ {
+ var bindArgs = {
+ url: call.url+'?rpc',
+ error: function(type, data, evt){alert("Error Communicating with Server: " + data.result);},
+ method: "POST",
+ mimetype: "text/json",
+ handle: call.callback,
+ postContent: dojo.json.serialize(call.request)
+ };
+ var req = dojo.io.bind(bindArgs);
+ dojo.event
+ return req;
+ }
+
+ /* lister */
+
+ function entry_list_result(type, data, evt)
+ {
+ var w = dojo.widget.byId("entry_list");
+ w.store.setData(data.result);
+ }
+ function entry_list()
+ {
+ PhoneBook.rpc.entry_list(entry_list_result).call(server);
+ }
+ dojo.addOnLoad(entry_list);
+
+ function entry_list_select_edit(evt) {
+ var table = dojo.widget.byId("entry_list");
+ entry_edit(table.getSelectedData().entry_key);
+ }
+ function entry_list_select_delete(evt) {
+ var table = dojo.widget.byId("entry_list");
+ entry_delete(table.getSelectedData().entry_key);
+ }
+
+ function entry_list_select() {
+ dojo.event.connect(dojo.byId("entry_list"), "onSelect", entry_list_select_edit);
+ }
+ dojo.addOnLoad(entry_list_select);
+
+ /* lister filters */
+
+ function dateFilter(hired) {
+ return (hired == '5/29/1987' || hired == '11/18/1984');
+ }
+ function applyDate(id){
+ dojo.widget.byId(id).setFilter("hired", dateFilter);
+ }
+
+ function nameFilter(last_name){
+ return (last_name.charAt(0) >= 'M' && last_name.charAt(0) <= 'Z');
+ }
+ function applyName(id){
+ dojo.widget.byId(id).setFilter("last_name", nameFilter);
+ }
+
+ function clearFilters(id){
+ dojo.widget.byId(id).clearFilters();
+ }
+ function reloadData(id){
+ dojo.widget.byId(id).store.clearData();
+ entry_list();
+ }
+
+ /* editor */
+
+ function setHired(hired) {
+ var dpHired = dojo.widget.byId("dpHired");
+ dpHired.setDate(hired);
+ }
+
+ function entry_edit_result(type, data, evt)
+ {
+ var w = dojo.widget.byId("entry_form");
+ w.setValues(data.result);
+ var part = new Array();
+ part = data.result.hired.split('/',3); // mm/dd/yyyy
+ var yyyy = part[2];
+ var mm = part[0];
+ var dd = part[1];
+ if (mm.length==1) mm = new String().concat('0',mm);
+ if (dd.length==1) dd = new String().concat('0',dd);
+ var hired = new String().concat( yyyy,'-',mm,'-',dd );
+ setHired(hired);
+ }
+ function entry_edit(entry_key)
+ {
+ PhoneBook.rpc.entry(entry_key,entry_edit_result).call(server);
+ }
+
+ function entry_save_result() {
+ reloadData('entry_list');
+ entry_reset();
+ }
+ function entry_save_update_result(type, data, evt)
+ {
+ alert ( "Edited: " + data.result.user_name + " (" + data.result.entry_key + ")" );
+ entry_save_result();
+ }
+ function entry_save_insert_result(type, data, evt)
+ {
+ alert ( "Added: " + data.result.user_name + " (" + data.result.entry_key + ")" );
+ entry_save_result();
+ }
+ function entry_save()
+ {
+ var w = dojo.widget.byId("entry_form");
+ var values = w.getValues();
+ if (values.entry_key)
+ PhoneBook.rpc.entry_save(values,entry_save_update_result).call(server);
+ else
+ PhoneBook.rpc.entry_save(values,entry_save_insert_result).call(server);
+ }
+
+ function entry_reset() {
+ var w = dojo.widget.byId("entry_form");
+ var values = w.getValues();
+ values.first_name = "";
+ values.last_name = "";
+ values.extension = "";
+ values.user_name = "";
+ values.hours = "37.5";
+ values.entry_key = "";
+ w.setValues(values);
+ var today = new Date();
+ setHired(today);
+ }
+
+ function entry_add()
+ {
+ entry_reset();
+ }
+
+ function entry_delete_result(type, data, evt)
+ {
+ alert ( "Deleted: (" + data.result.entry_key + ")" );
+ entry_save_result();
+ }
+ function entry_delete(entry_key)
+ {
+ if (entry_key) {
+ confirm ( "Delete entry?" );
+ PhoneBook.rpc.entry_delete(entry_key,entry_delete_result).call(server);
+ }
+ }
+
+ </script>
+
+ <style type="text/css">
+ /***
+ The following is just an example of how to use the table.
+ You can override any class names to be used if you wish.
+ ***/
+ table {
+ font-family:Lucida Grande, Verdana;
+ font-size:0.8em;
+ width:100%;
+ border:1px solid #ccc;
+ border-collapse:collapse;
+ cursor:default;
+ }
+ table td,
+ table th{
+ padding:2px;
+ font-weight:normal;
+ }
+ table thead td, table thead th {
+ background-image:url(images/ft-head.gif);
+ background-repeat:no-repeat;
+ background-position:top right;
+ }
+ table thead td.selectedUp, table thead th.selectedUp {
+ background-image:url(images/ft-headup.gif);
+ }
+ table thead td.selectedDown, table thead th.selectedDown {
+ background-image:url(images/ft-headdown.gif);
+ }
+
+ table tbody tr td{
+ border-bottom:1px solid #ddd;
+ }
+ table tbody tr.alt td{
+ background: #e3edfa;
+ }
+ table tbody tr.selected td{
+ background: yellow;
+ }
+ table tbody tr:hover td{
+ background: #a6c2e7;
+ }
+ table tbody tr.selected:hover td{
+ background:#ff9;
+ }
+
+ #inputArea{
+ margin:1em 0;
+ padding:1em;
+ background-color:#eef;
+ }
+ #updateTestInput{
+ border:1px solid #ccc;
+ width:100%;
+ height:80px;
+ font-family:serif;
+ font-size:0.9em;
+ overflow:auto;
+ }
+ </style>
+ </head>
+ <body>
+
+ <div id="finder" />
+
+ <div id="lister">
+
+ <table id="filter_menu"><tr><td>
+ <input type="button" onclick="applyDate('entry_list');" value="Show only hires between 1/1/1984 and 1/1/1987" ID="Button1" NAME="Button1"/>
+ <input type="button" onclick="applyName('entry_list');" value="Show only names between M and Z" ID="Button2" NAME="Button2"/>
+ <input type="button" value="Show All Entries" onclick="clearFilters('entry_list');" ID="Button3" NAME="Button3"/>
+ <input type="button" value="Reload Entries" onclick="reloadData('entry_list');" ID="Button4" NAME="Button4"/>
+ </td></tr></table>
+
+ <table id="entry_list"
+ dojoType="filteringTable" alternateRows="true" valueField="user_name" >
+ <thead>
+ <tr>
+ <th field="last_name" sort="asc">Last Name</th>
+ <th field="first_name">First Name</th>
+ <th field="extension">Extension</th>
+ <th field="user_name">User</th>
+ <th field="hired" align="center">Hired</th>
+ <th field="hours" align="center">Hours</th>
+ </tr>
+ </thead>
+ </table>
+
+ <table id="edit_menu"><tr><td>
+ <input type="button" value="Edit Entry" onclick="entry_list_select_edit('entry_list');" ID="Button5" NAME="Button5"/>
+ <input type="button" value="Add Entry" onclick="entry_add('entry_list');" ID="Button6" NAME="Button6"/>
+ <input type="button" value="Delete Entry" onclick="entry_list_select_delete('entry_list');" ID="Button7" NAME="Button7"/>
+ </td></tr></table>
+
+ </div>
+
+ <div id="viewer" />
+
+ <div id="editor">
+
+ <form id="entry_form" dojoType="Form">
+ <table ID="Table1"><tr>
+ <td>First Name</td><td><input name="first_name" ID="Text1"/></td>
+ </tr><tr>
+ <td>Last Name</td><td><input name="last_name" ID="Text2"/></td>
+ </tr><tr>
+ <td>Extension</td><td><input name="extension" ID="Text3"/></td>
+ </tr><tr>
+ <td>User Name</td><td><input name="user_name" ID="Text4"/></td>
+ </tr><tr>
+ <td>Hired</td><td><input name="hired" widgetid="dpHired" dojoType="dropdowndatepicker" displayFormat="MM/dd/yyyy" ID="Text5"/></td>
+ </tr><tr>
+ <td>Hours</td><td><input name="hours" ID="Text6"/></td>
+ </tr><tr>
+ <td rowspan="2"><input type="button" onClick="entry_save();" value="SAVE" ID="Button8" NAME="Button8"/>
+ <input type="hidden" name="editor" value="1" ID="editor"/>
+ <input type="hidden" name="entry_key" ID="entry_key"/>
+ </td>
+ </tr></table>
+ </form>
+ </div>
+
+ </body>
+</html>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppBase.xml b/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppBase.xml
new file mode 100644
index 0000000..e60c441
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppBase.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Base element (super parent)-->
+
+ <object id="BaseMapper" abstract="true">
+ <property name="Mapper"><ref object="Mapper"/></property>
+ </object>
+
+ <!-- Base class parents -->
+
+ <object id="BaseChain" type="Nexus.Core.RequestChain, Nexus.Core"/>
+
+ <object id="BaseCount" type="PhoneBook.Core.Commands.BaseCount, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseDelete" type="PhoneBook.Core.Commands.BaseDelete, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseEntry" type="PhoneBook.Core.Commands.BaseEntry, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFilterList" type="PhoneBook.Core.Commands.BaseFilterList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFieldContext" type="Nexus.Extras.Spring.FieldContext">
+ <property name="MessageSource">
+ <ref object="messageSource" />
+ </property>
+ </object>
+
+ <object id="BaseKeyValueProcessor" type="Nexus.Core.Validators.KeyValueProcessor"/>
+
+ <object id="BaseList" type="PhoneBook.Core.Commands.BaseList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseSave" type="PhoneBook.Core.Commands.BaseSave, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="EntryInitial" type="PhoneBook.Core.Commands.EntryInitial, PhoneBook.Core" parent="BaseMapper"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppConfig.xml b/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppConfig.xml
new file mode 100644
index 0000000..f3bbcbd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppConfig.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Message Source -->
+
+ <object id="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
+ <property name="ResourceManagers">
+ <list>
+ <value>PhoneBook.Core.Messages, PhoneBook.Core</value>
+ <value>Nexus.Web.Messages, Nexus.Web</value>
+ </list>
+ </property>
+ </object>
+
+
+ <!-- Request Processors -->
+
+ <object id="convert_input" type="Nexus.Core.Validators.ConvertInput">
+ <property name="ID"><value>convert_input</value></property>
+ </object>
+
+ <object id="format_output" type="Nexus.Core.Validators.FormatOutput">
+ <property name="ID"><value>format_output</value></property>
+ </object>
+
+ <object id="clear_context" type="Nexus.Core.Validators.ClearContext">
+ <property name="ID"><value>clear_context</value></property>
+ </object>
+
+ <!-- pre-op -->
+
+ <object id="pre-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="convert_input"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- post-op -->
+
+ <object id="post-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="format_output"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- Catalog -->
+
+ <object id="Catalog" type="Nexus.Extras.Spring.Catalog">
+ <property name="FieldTable"><ref object="FieldTable"/></property>
+ <property name="PreOp"><ref object="pre-op"/></property>
+ <property name="PostOp"><ref object="post-op"/></property>
+ <property name="ViewHelper"><object type="Nexus.Web.WebHelper, Nexus.Web" singleton="false"/></property>
+ </object>
+
+<!-- iBATIS Mapper -->
+
+ <object id="Mapper" type="IBatisNet.DataMapper.Mapper, IBatisNet.DataMapper"
+ factory-method="Instance"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppFields.xml b/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppFields.xml
new file mode 100644
index 0000000..303fc2b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Resources/AppFields.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- FieldTable -->
+
+ <object id="FieldTable" type="Nexus.Core.Tables.FieldTable">
+ <property name="AddFieldContexts">
+ <list>
+ <ref object="last_name"/>
+ <ref object="first_name"/>
+ <ref object="extension"/>
+ <ref object="user_name"/>
+ <ref object="hired"/>
+ <ref object="hours"/>
+ <ref object="_entry_list"/>
+ <ref object="_entry_list_count"/>
+ <ref object="_extension_list"/>
+ <ref object="_hired_list"/>
+ </list>
+ </property>
+ <property name="AddProcessors">
+ <list>
+ <ref object="DateTimeProcessor"/>
+ <ref object="TelephoneProcessor"/>
+ <ref object="EntryListProcessor"/>
+ <ref object="ExtensionListProcessor"/>
+ <ref object="HiredListProcessor"/>
+ </list>
+ </property>
+ </object>
+
+ <object id="last_name" parent="BaseFieldContext">
+ <property name="ID"><value>last_name</value></property>
+ </object>
+
+ <object id="first_name" parent="BaseFieldContext">
+ <property name="ID"><value>first_name</value></property>
+ </object>
+
+ <object id="user_name" parent="BaseFieldContext">
+ <property name="ID"><value>user_name</value></property>
+ </object>
+
+ <object id="extension" parent="BaseFieldContext">
+ <property name="ID"><value>extension</value></property>
+ <property name="Processor"><ref object="TelephoneProcessor"/></property>
+ </object>
+
+ <object id="hired" parent="BaseFieldContext">
+ <property name="ID"><value>hired</value></property>
+ <property name="Processor"><ref object="DateTimeProcessor"/></property>
+ </object>
+
+ <object id="hours" parent="BaseFieldContext">
+ <property name="ID"><value>hours</value></property>
+ </object>
+
+ <object id="editor" parent="BaseFieldContext">
+ <property name="ID"><value>editor</value></property>
+ </object>
+
+ <!-- property name="ControlTypeName"><value>CheckBox</value></property -->
+
+ <!-- We need to "hash" the name with "_" to avoid conflict with the filter Command -->
+ <object id="_entry_list" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="Processor"><ref object="EntryListProcessor"/></property>
+ </object>
+
+ <object id="_entry_list_count" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="Processor"><ref object="CollectionProcessor"/></property>
+ </object>
+
+ <object id="_extension_list" parent="BaseFieldContext">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="Processor"><ref object="ExtensionListProcessor"/></property>
+ </object>
+
+ <object id="_hired_list" parent="BaseFieldContext">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="Processor"><ref object="HiredListProcessor"/></property>
+ </object>
+
+ <object id="CollectionProcessor" type="Nexus.Core.Validators.CollectionProcessor, Nexus.Core">
+ <property name="ID"><value>EntryCountProcessor</value></property>
+ </object>
+
+ <!-- "d" is .NET for "short date" -->
+ <object id="DateTimeProcessor" type="Nexus.Core.Validators.DateTimeProcessor">
+ <property name="ID"><value>DateTimeProcessor</value></property>
+ <property name="DataFormat"><value>d</value></property>
+ </object>
+
+ <object id="TelephoneProcessor" type="PhoneBook.Core.TelephoneProcessor">
+ <property name="ID"><value>TelephoneProcessor</value></property>
+ </object>
+
+ <object id="EntryListProcessor" type="PhoneBook.Core.AppEntryListProcessor">
+ <property name="ID"><value>EntryListProcessor</value></property>
+ </object>
+
+ <object id="ExtensionListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>ExtensionListProcessor</value></property>
+ <property name="Key"><value>extension</value></property>
+ </object>
+
+ <object id="HiredListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>HiredListProcessor</value></property>
+ <property name="Key"><value>hired</value></property>
+ </object>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Resources/Catalog.xml b/struts-sandbox/overdrive/PhoneBook/Web/Resources/Catalog.xml
new file mode 100644
index 0000000..bd89c45
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Resources/Catalog.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- entry commands -->
+
+ <object id="entry_list_rows" parent="BaseList">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="QueryID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_list_count" parent="BaseCount">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="QueryID"><value>entry_count</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry" parent="BaseEntry">
+ <property name="ID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_delete" parent="BaseDelete">
+ <property name="ID">
+ <value>entry_delete</value>
+ </property>
+ <property name="RequiredIDs">
+ <list>
+ <value>entry_key</value>
+ </list>
+ </property>
+ </object>
+
+ <!-- filter list commands -->
+
+ <object id="last_name_list" parent="BaseFilterList">
+ <property name="ID"><value>last_name_list</value></property>
+ <property name="RelatedIDs"><list><value>last_name_list</value></list></property>
+ </object>
+
+ <object id="first_name_list" parent="BaseFilterList">
+ <property name="ID"><value>first_name_list</value></property>
+ <property name="RelatedIDs"><list><value>first_name_list</value></list></property>
+ </object>
+
+ <object id="extension_list" parent="BaseFilterList">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="RelatedIDs"><list><value>extension_list</value></list></property>
+ </object>
+
+ <object id="user_name_list" parent="BaseFilterList">
+ <property name="ID"><value>user_name_list</value></property>
+ <property name="RelatedIDs"><list><value>user_name_list</value></list></property>
+ </object>
+
+ <object id="hired_list" parent="BaseFilterList">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="RelatedIDs"><list><value>hired_list</value></list></property>
+ </object>
+
+ <object id="hours_list" parent="BaseFilterList">
+ <property name="ID"><value>hours_list</value></property>
+ <property name="RelatedIDs"><list><value>hours_list</value></list></property>
+ </object>
+
+ <object id="entry_initial" parent="EntryInitial">
+ <property name="ID">
+ <value>entry_initial</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_initial</value>
+ </list>
+ </property>
+ </object>
+
+ <!-- chains -->
+
+ <object id="entry_list" parent="BaseChain">
+ <property name="ID">
+ <value>entry_list</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="entry_list_count" />
+ <ref object="entry_list_rows" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_find" parent="BaseChain">
+ <property name="ID">
+ <value>entry_find</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="last_name_list" />
+ <ref object="first_name_list" />
+ <ref object="extension_list" />
+ <ref object="user_name_list" />
+ <ref object="hired_list" />
+ <ref object="hours_list" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_save" parent="BaseSave">
+ <property name="ID">
+ <value>entry_save</value>
+ </property>
+ <property name="KeyID">
+ <value>entry_key</value>
+ </property>
+ <property name="InsertID">
+ <value>entry_insert</value>
+ </property>
+ <property name="UpdateID">
+ <value>entry_update</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_key</value>
+ </list>
+ </property>
+ <property name="RequiredIDs">
+ <list>
+ <value>first_name</value>
+ <value>last_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hours</value>
+ <value>hired</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Resources/Queries.xml b/struts-sandbox/overdrive/PhoneBook/Web/Resources/Queries.xml
new file mode 100644
index 0000000..370639f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Resources/Queries.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<sqlMap
+ namespace="phonebook"
+ xmlns="http://ibatis.apache.org/mapping"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
+
+ <parameterMaps>
+
+ <parameterMap id="entry_save_param">
+ <parameter property="last_name"/>
+ <parameter property="first_name"/>
+ <parameter property="extension"/>
+ <parameter property="user_name"/>
+ <parameter property="hired"/>
+ <parameter property="hours"/>
+ <parameter property="editor"/>
+ <parameter property="entry_key"/>
+ </parameterMap>
+
+ </parameterMaps>
+
+ <statements>
+
+ <select id="last_name_list" resultClass="string">
+ SELECT DISTINCT
+ last_name
+ FROM entry
+ ORDER BY last_name
+ </select>
+
+ <select id="first_name_list" resultClass="string">
+ SELECT DISTINCT
+ first_name
+ FROM entry
+ ORDER BY first_name
+ </select>
+
+ <select id="extension_list" resultClass="string">
+ SELECT DISTINCT
+ extension
+ FROM entry
+ ORDER BY extension
+ </select>
+
+ <select id="user_name_list" resultClass="string">
+ SELECT DISTINCT
+ user_name
+ FROM entry
+ ORDER BY user_name
+ </select>
+
+ <select id="hired_list" resultClass="date">
+ SELECT DISTINCT
+ hired
+ FROM entry
+ ORDER BY hired
+ </select>
+
+ <select id="hours_list" resultClass="string">
+ SELECT DISTINCT
+ hours
+ FROM entry
+ ORDER BY hours
+ </select>
+
+ <select id="entry" paramClass="Hashtable" resultClass="Hashtable">
+ SELECT
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry AS entry_key
+ FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ <dynamic>
+ <isNotNull property="item_limit">
+ LIMIT #item_limit# OFFSET #item_offset#
+ </isNotNull>
+ </dynamic>;
+ </select>
+
+ <select id="entry_count" paramClass="Hashtable" resultClass="string">
+ SELECT COUNT(*) FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ </select>
+
+ <select id="entry_initial" paramClass="string" resultClass="string">
+ SELECT COUNT(*)
+ FROM entry
+ WHERE last_name LIKE #value#
+ </select>
+
+ <insert id="entry_insert" parameterMap="entry_save_param">
+ INSERT INTO entry (
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry
+ )
+ VALUES (?,?,?,?, ?,?,?,?)
+ </insert>
+
+ <update id="entry_update" parameterMap="entry_save_param">
+ UPDATE entry SET
+ last_name=?,
+ first_name=?,
+ extension=?,
+ user_name=?,
+ hired=?,
+ hours=?,
+ editor=?
+ WHERE
+ pk_entry=?
+ </update>
+
+ <delete id="entry_delete" paramClass="Hashtable">
+ DELETE FROM entry WHERE pk_entry=#entry_key#;
+ </delete>
+
+ </statements>
+</sqlMap>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Web.config b/struts-sandbox/overdrive/PhoneBook/Web/Web.config
new file mode 100644
index 0000000..f81e509
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Web.config
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+
+ <configSections>
+ <sectionGroup name="spring">
+ <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
+ </sectionGroup>
+ </configSections>
+
+ <spring>
+ <context type="Spring.Context.Support.WebApplicationContext, Spring.Web">
+ <resource uri="~/Objects-Web.xml"/>
+ </context>
+ </spring>
+
+ <system.web>
+
+ <!-- AUTOMATIC CONTEXT LOADING WITH SPRING
+ Spring.Web uses custom PageHandlerFactory to load appropriate
+ application context, which is in turn used to find appropriate page to
+ execute.
+http://opensource.atlassian.com/confluence/spring/display/NET/Automatic+context+loading+and+hierarchical+contexts
+ -->
+
+ <httpHandlers>
+ <add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
+ </httpHandlers>
+
+ <!-- DYNAMIC DEBUG COMPILATION
+ Set compilation debug="true" to enable ASPX debugging. Otherwise, setting this value to
+ false will improve runtime performance of this application.
+ Set compilation debug="true" to insert debugging symbols (.pdb information)
+ into the compiled page. Because this creates a larger file that executes
+ more slowly, you should set this value to true only when debugging and to
+ false at all other times. For more information, refer to the documentation about
+ debugging ASP.NET files.
+ -->
+ <compilation
+ defaultLanguage="c#"
+ debug="true"
+ />
+
+ <!-- CUSTOM ERROR MESSAGES
+ Set customErrors mode="On" or "RemoteOnly" to enable custom error messages, "Off" to disable.
+ Add <error> tags for each of the errors you want to handle.
+
+ "On" Always display custom (friendly) messages.
+ "Off" Always display detailed ASP.NET error information.
+ "RemoteOnly" Display custom (friendly) messages only to users not running
+ on the local Web server. This setting is recommended for security purposes, so
+ that you do not display application detail information to remote clients.
+ -->
+ <customErrors
+ mode="RemoteOnly"
+ />
+
+ <!-- AUTHENTICATION
+ This section sets the authentication policies of the application. Possible modes are "Windows",
+ "Forms", "Passport" and "None"
+
+ "None" No authentication is performed.
+ "Windows" IIS performs authentication (Basic, Digest, or Integrated Windows) according to
+ its settings for the application. Anonymous access must be disabled in IIS.
+ "Forms" You provide a custom form (Web page) for users to enter their credentials, and then
+ you authenticate them in your application. A user credential token is stored in a cookie.
+ "Passport" Authentication is performed via a centralized authentication service provided
+ by Microsoft that offers a single logon and core profile services for member sites.
+ -->
+ <authentication mode="Windows" />
+ <identity impersonate="true" />
+
+ <!-- AUTHORIZATION
+ This section sets the authorization policies of the application. You can allow or deny access
+ to application resources by user or role. Wildcards: "*" mean everyone, "?" means anonymous
+ (unauthenticated) users.
+ -->
+
+ <authorization>
+ <allow users="*" /> <!-- Allow all users -->
+ <!-- <allow users="[comma separated list of users]"
+ roles="[comma separated list of roles]"/>
+ <deny users="[comma separated list of users]"
+ roles="[comma separated list of roles]"/>
+ -->
+ </authorization>
+
+ <!-- APPLICATION-LEVEL TRACE LOGGING
+ Application-level tracing enables trace log output for every page within an application.
+ Set trace enabled="true" to enable application trace logging. If pageOutput="true", the
+ trace information will be displayed at the bottom of each page. Otherwise, you can view the
+ application trace log by browsing the "trace.axd" page from your web application
+ root.
+ -->
+ <trace
+ enabled="false"
+ requestLimit="10"
+ pageOutput="false"
+ traceMode="SortByTime"
+ localOnly="true"
+ />
+
+ <!-- SESSION STATE SETTINGS
+ By default ASP.NET uses cookies to identify which requests belong to a particular session.
+ If cookies are not available, a session can be tracked by adding a session identifier to the URL.
+ To disable cookies, set sessionState cookieless="true".
+ -->
+ <sessionState
+ mode="InProc"
+ stateConnectionString="tcpip=127.0.0.1:42424"
+ sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
+ cookieless="false"
+ timeout="20"
+ />
+
+ <!-- GLOBALIZATION
+ This section sets the globalization settings of the application.
+ -->
+ <globalization
+ requestEncoding="utf-8"
+ responseEncoding="utf-8"
+ />
+
+ </system.web>
+
+</configuration>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Web.csproj b/struts-sandbox/overdrive/PhoneBook/Web/Web.csproj
new file mode 100644
index 0000000..84b291c
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Web.csproj
@@ -0,0 +1,6199 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Web"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{948EE344-D033-4358-88E8-77FDE080D93C}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "PhoneBook.Web"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Library"
+ PreBuildEvent = "$(SolutionDir)prebuild $(SolutionDir)"
+ PostBuildEvent = ""
+ RootNamespace = "PhoneBook.Web"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = "PhoneBook.Web.xml"
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = "1591"
+ Optimize = "false"
+ OutputPath = "bin\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Drawing"
+ AssemblyName = "System.Drawing"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Drawing.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.Web"
+ AssemblyName = "System.Web"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Web.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ <Reference
+ Name = "Nexus.Core"
+ AssemblyName = "Nexus.Core"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Core.dll"
+ />
+ <Reference
+ Name = "Core"
+ Project = "{3150F3E8-9A04-4FED-B16F-CEA57756E934}"
+ Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+ />
+ <Reference
+ Name = "Nexus.Web"
+ AssemblyName = "Nexus.Web"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Web.dll"
+ />
+ <Reference
+ Name = "Spring.Core"
+ AssemblyName = "Spring.Core"
+ HintPath = "..\..\local-cache\SpringNet\Spring.Core.dll"
+ />
+ <Reference
+ Name = "Spring.Web"
+ AssemblyName = "Spring.Web"
+ HintPath = "..\..\local-cache\SpringNet\Spring.Web.dll"
+ />
+ <Reference
+ Name = "Agility.Core"
+ AssemblyName = "Agility.Core"
+ HintPath = "..\..\local-cache\Agility\Agility.Core.dll"
+ />
+ <Reference
+ Name = "Nexus.Extras"
+ AssemblyName = "Nexus.Extras"
+ HintPath = "..\..\local-cache\Nexus\Nexus.Extras.dll"
+ />
+ <Reference
+ Name = "MySql.Data"
+ AssemblyName = "MySql.Data"
+ HintPath = "..\..\local-cache\iBatisNet\MySql.Data.dll"
+ />
+ <Reference
+ Name = "Jayrock.Json"
+ AssemblyName = "Jayrock.Json"
+ HintPath = "..\..\local-cache\jayrock\Jayrock.Json.dll"
+ />
+ <Reference
+ Name = "Jayrock"
+ AssemblyName = "Jayrock"
+ HintPath = "..\..\local-cache\jayrock\Jayrock.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "AssemblyInfo.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "default.htm"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Global.asax"
+ SubType = "Component"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Global.asax.cs"
+ DependentUpon = "Global.asax"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Global.asax.resx"
+ DependentUpon = "Global.asax.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Objects.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Objects-Web.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "PhoneBook.ashx"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "PhoneBook.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "providers.config"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "sqlmap.config"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "sqlmap.config.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Web.config"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\AppGridControl.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\AppGridControl.ascx.cs"
+ DependentUpon = "AppGridControl.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\AppGridControl.ascx.resx"
+ DependentUpon = "AppGridControl.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Controls\Finder.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\Finder.ascx.cs"
+ DependentUpon = "Finder.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\Finder.ascx.resx"
+ DependentUpon = "Finder.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Controls\Finder2.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\Finder2.ascx.cs"
+ DependentUpon = "Finder2.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\Finder2.ascx.resx"
+ DependentUpon = "Finder2.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Controls\InitialFilter.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\InitialFilter.ascx.cs"
+ DependentUpon = "InitialFilter.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\InitialFilter.ascx.resx"
+ DependentUpon = "InitialFilter.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Controls\Lister.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\Lister.ascx.cs"
+ DependentUpon = "Lister.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\Lister.ascx.resx"
+ DependentUpon = "Lister.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Controls\Lister2.ascx"
+ SubType = "UserControl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Controls\Lister2.ascx.cs"
+ DependentUpon = "Lister2.ascx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Controls\Lister2.ascx.resx"
+ DependentUpon = "Lister2.ascx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Forms\default.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Forms\Directory.aspx"
+ SubType = "Form"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Forms\Directory.aspx.cs"
+ DependentUpon = "Directory.aspx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Forms\Directory.aspx.resx"
+ DependentUpon = "Directory.aspx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Forms\Directory2.aspx"
+ SubType = "Form"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Forms\Directory2.aspx.cs"
+ DependentUpon = "Directory2.aspx"
+ SubType = "ASPXCodeBehind"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "Forms\Directory2.aspx.resx"
+ DependentUpon = "Directory2.aspx.cs"
+ BuildAction = "EmbeddedResource"
+ />
+ <File
+ RelPath = "Forms\Web.config"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\build.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\dojo.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\dojo.js.uncompressed.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\flash6_gateway.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\iframe_history.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\LICENSE"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\README"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\storage_dialog.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\Storage_version6.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\Storage_version8.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\de2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\demoEngine.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\demoEngine.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\demoRegistry.json"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\demos\dojoDemos.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\viewDemo.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\gfx\circles.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\gfx\clock.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\gfx\images\clock_face.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_AccordionThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_ButtonThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_ChartThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_CheckboxThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_CiviCrmDateTimePickerThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_ColorPaletteThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_ComboBoxThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_ContentPaneThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_DatePickerThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_DatePickerThumb.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_DialogThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_DragDropThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_DragHandleThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_DragMoveThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_EditorThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_EffectsThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_FisheyeThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_FormBindThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_FormTourThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_GoogleMapThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_InlineEditThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_JSONRPCThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_LayoutContainerThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_LayoutThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_MailThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_MenuThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_MoxieThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_NoThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_RoundedThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_SlideShowThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_SortableTableThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_SplitContainerThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_TabContainerThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_TimePickerThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_TitlePaneThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_TooltipThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_TreeThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_ValidationThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_WindowThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_WizardThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\screenshots\test_YahooMapThumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\storage\editor.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\storage\editor.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\accordionContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\comboBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\contentPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\datePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\dialog.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Editor.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Fisheye.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Form.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\layoutContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Panes.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\rounded.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\splitContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\tabContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\tooltip.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\tree.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_browser.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_browser.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_calendar.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_calendar.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_email.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_email.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_texteditor.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_texteditor.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_update.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_update.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_users.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\icon_users.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\images\roundedbg.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Bob.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\cancel.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\checkmark.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Deleted.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\folder_documents.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\folder_inbox.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\folder_sent_mail.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Friends.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Inbox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Jack.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Lunch.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\mail.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\mail.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\mail_get.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\mail_new.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\MailAccount.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\mailbox1.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Meeting.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\NewMessage.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\ok.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Paint.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\RemainingWork.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\SavedMail.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\SentMail.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\trashcan_full.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Mail\Work.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\createChild"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\getChildren"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\move"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\removeNode"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\tree.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\create.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\createsmall.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\down.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\downsmall.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\loading.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\recyclebin.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\removesmall.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\up.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\demos\widget\Tree\static\upsmall.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\release\dojo\tests\flash\resources\HelloWorld_version6.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\release\dojo\tests\flash\resources\HelloWorld_version8.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\release\dojo\tests\flash\resources\UnitTestsComm_version6.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\release\dojo\tests\flash\resources\UnitTestsComm_version8.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\a11y.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\AdapterRegistry.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\animation.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\behavior.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\bootstrap1.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\bootstrap2.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\browser_debug.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\date.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\debug.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\Deferred.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\DeferredList.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\docs.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dom.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\event.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\experimental.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\flash.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_adobesvg.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_browser.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_dashboard.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_jsc.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_rhino.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_spidermonkey.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_svg.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\hostenv_wsh.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\iCalendar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\json.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\loader.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\loader_xd.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\math.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\ns.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\profile.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\regexp.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\storage.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\string.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\style.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\svg.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\animation\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\animation\Animation.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\animation\AnimationEvent.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\animation\AnimationSequence.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\animation\Timer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\cal\iCalendar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\cal\textDirectory.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\Axis.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\Chart.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\Plot.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\PlotArea.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\Plotters.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\README.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\Series.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\svg\Axis.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\svg\PlotArea.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\svg\Plotters.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\vml\Axis.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\vml\PlotArea.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\charting\vml\Plotters.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\ArrayList.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\BinaryTree.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\Collections.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\Dictionary.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\Graph.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\Queue.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\Set.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\SkipList.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\SortedList.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\Stack.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\collections\Store.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto\Blowfish.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto\LICENSE"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto\MD5.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto\Rijndael.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto\SHA1.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\crypto\SHA256.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\CsvStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\OpmlStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\RdfStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\YahooStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\core\Read.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\core\RemoteStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\core\Result.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\core\Write.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\Attribute.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\Item.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\Kind.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\Observable.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\ResultSet.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\to_do.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\Type.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\Value.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\format\Csv.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\format\Json.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\provider\Base.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\provider\Delicious.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\provider\FlatFile.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\provider\JotSpot.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\data\old\provider\MySql.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\date\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\date\format.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\date\serialize.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\date\supplemental.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\debug\arrow_hide.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\debug\arrow_show.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\debug\console.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\debug\deep.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\debug\Firebug.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\debug\spacer.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\DragAndDrop.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\HtmlDragAndDrop.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\HtmlDragCopy.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\HtmlDragManager.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\HtmlDragMove.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\Sortable.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\TreeDragAndDrop.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\dnd\TreeDragAndDropV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\event\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\event\browser.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\event\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\event\topic.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\flash\flash6\DojoExternalInterface.as"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\flash\flash6\flash6_gateway.fla"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\flash\flash8\DojoExternalInterface.as"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\flash\flash8\ExpressInstall.as"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\color.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\Colorspace.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\matrix.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\path.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\shape.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\svg.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\vml.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\color\hsl.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\gfx\color\hsv.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\graphics\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\graphics\color.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\graphics\Colorspace.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\graphics\color\hsl.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\graphics\color\hsv.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\color.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\display.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\iframe.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\layout.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\metrics.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\selection.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\shadow.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\style.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\util.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowB.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowBL.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowBR.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowL.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowR.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowT.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowTL.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\html\images\shadowTR.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\number.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\gregorianExtras.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\README"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\de\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\en\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\es\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\fi\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\fr\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\hu\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\it\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\ja\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\ja\gregorianExtras.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\ko\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\nl\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\pt\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\pt-br\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\sv\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\zh\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\zh\gregorianExtras.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\zh-cn\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\zh-hk\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\calendar\nls\zh-tw\gregorian.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\EUR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\GBP.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\INR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\ITL.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\JPY.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\README"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\USD.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\en\EUR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\en\GBP.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\en\INR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\en\ITL.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\en\JPY.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\en\USD.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\en-us\USD.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\hi\EUR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\hi\GBP.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\hi\INR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\hi\ITL.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\hi\JPY.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\hi\USD.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\ja\EUR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\ja\GBP.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\ja\INR.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\ja\ITL.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\ja\JPY.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\i18n\currency\nls\ja\USD.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\BrowserIO.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\cometd.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\cookie.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\IframeIO.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\RepubsubIO.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\RhinoIO.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\ScriptSrcIO.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\XhrIframeProxy.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\xip_client.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\io\xip_server.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\array.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\assert.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\declare.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\extras.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\func.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\repr.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\type.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\timing\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\timing\Streamer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lang\timing\Timer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lfx\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lfx\Animation.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lfx\extras.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lfx\html.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lfx\rounded.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lfx\shadow.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\lfx\toggle.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\logging\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\logging\ConsoleLogger.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\logging\Logger.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\math\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\math\curves.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\math\matrix.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\math\points.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\namespaces\dojo.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\rpc\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\rpc\Deferred.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\rpc\JotService.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\rpc\JsonService.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\rpc\RpcService.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\rpc\yahoo.smd"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\rpc\YahooService.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\selection\Selection.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\storage\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\storage\browser.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\storage\Storage.as"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\storage\storage_dialog.fla"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\src\string\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\string\Builder.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\string\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\string\extras.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\text\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\text\textDirectory.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\undo\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\undo\browser.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\undo\Manager.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uri\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uri\Uri.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uuid\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uuid\LightweightGenerator.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uuid\NameBasedGenerator.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uuid\NilGenerator.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uuid\RandomGenerator.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uuid\TimeBasedGenerator.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\uuid\Uuid.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\check.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\creditCard.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\datetime.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\de.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\jp.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\us.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\validate\web.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\AccordionContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\AnimatedPng.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Button.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Chart.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Checkbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Clock.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ColorPalette.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ComboBox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ContentPane.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\CurrencyTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DatePicker.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DateTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DebugConsole.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Dialog.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DocPane.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DomWidget.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DropdownContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DropdownDatePicker.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\DropdownTimePicker.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Toolbar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\FilteringTable.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\FisheyeList.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\FloatingPane.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Form.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\GoogleMap.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\HtmlWidget.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\InlineEditBox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\IntegerTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\InternetTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\LayoutContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\LinkPane.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Manager.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Menu2.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\MonthlyCalendar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\PageContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Parse.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\PopupContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ProgressBar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\RadioGroup.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\RealNumberTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\RegexpTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\RemoteTabController.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Repeater.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ResizableTextarea.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ResizeHandle.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\RichText.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Rounded.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Select.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Show.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ShowAction.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ShowSlide.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Slider.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\SlideShow.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\SortableTable.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Spinner.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\SplitContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\SvgButton.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\SvgWidget.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\SwtWidget.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TabContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TaskBar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Textbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TimePicker.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TitlePane.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Toaster.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Toggler.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Toolbar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Tooltip.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Tree.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeBasicController.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeBasicControllerV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeCommon.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeContextMenu.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeContextMenuV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeControllerExtension.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeDemo.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeDeselectOnDblselect.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeDisableWrapExtension.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeDndControllerV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeDocIconExtension.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeEditor.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeEmphasizeOnSelect.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeExpandToNodeOnSelect.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeExtension.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeLinkExtension.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeLoadingController.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeLoadingControllerV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeNode.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeNodeV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeRPCController.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeRpcControllerV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeSelector.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeSelectorV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeTimeoutIterator.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeToggleOnSelect.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeV3.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\TreeWithNode.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\UsTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\validate.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\ValidationTextbox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Widget.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Wizard.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\YahooMap.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\DemoContainer.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\DemoItem.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\DemoNavigator.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\DemoPane.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\SourcePane.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoContainer.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoItem.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoItem.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoNavigator.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoNavigator.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoPane.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\DemoPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\general.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\SourcePane.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\SourcePane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\images\test_thumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\demoEngine\templates\images\viewDemo.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\AlwaysShowToolbar.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\ContextMenu.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\CreateLinkDialog.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\FindReplace.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\FindReplaceDialog.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\InsertImageDialog.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\InsertTableDialog.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\SimpleSignalCommands.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\TableOperation.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\Editor2Plugin\ToolbarDndSupport.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\html\layout.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\html\loader.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\html\stabile.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\nls\DropdownDatePicker.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\nls\DropdownTimePicker.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\nls\TimePicker.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\nls\validate.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\nls\fr\validate.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\nls\ja\validate.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\nls\zh-cn\validate.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\svg\Chart.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\AccordionPane.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\AccordionPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ButtonTemplate.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ButtonTemplate.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\check.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Checkbox.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Checkbox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\CheckboxA11y.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\CiviCrmDatePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ComboBox.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ComboBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ComboButtonTemplate.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\DatePicker.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\DatePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\decrementMonth.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\decrementWeek.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\DemoEngine.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Dialog.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\DocPane.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\DocPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\DropDownButtonTemplate.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\EditorToolbar.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\EditorToolbar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\EditorToolbarOneline.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\FisheyeList.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\FloatingPane.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\FloatingPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\grabCorner.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\incrementMonth.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\incrementWeek.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\InlineEditBox.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\InlineEditBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Menu.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Menu2.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\MonthlyCalendar.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\MonthlyCalendar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\PopUpButton.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ProgressBar.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ProgressBar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\RemoteTabControl.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ResizableTextarea.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ResizableTextarea.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ResizeHandle.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\richtextframe.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Show.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Show.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ShowSlide.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ShowSlide.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Slider.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Slider.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\SliderHorizontal.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\SliderVertical.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\SlideShow.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\SlideShow.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Spinner.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Spinner.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\SplitContainer.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TabContainer.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TabContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TabContainerA11y.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TaskBar.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TaskBarItemTemplate.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Textbox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TimePicker.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TimePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TitlePane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Toaster.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Toolbar.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TooltipTemplate.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Tree.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TreeDisableWrap.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TreeDocIcon.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TreeEditor.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\TreeV3.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Validate.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\ValidationTextbox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Wizard.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Wizard.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\aggregate.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\backcolor.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\bg-fade.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\bold.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\cancel.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\copy.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\createlink.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\cut.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\delete.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\forecolor.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\hilitecolor.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\indent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\inserthorizontalrule.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\insertimage.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\insertorderedlist.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\inserttable.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\insertunorderedlist.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\italic.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\justifycenter.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\justifyfull.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\justifyleft.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\justifyright.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\left_to_right.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\list_bullet_indent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\list_bullet_outdent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\list_num_indent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\list_num_outdent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\outdent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\paste.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\redo.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\removeformat.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\right_to_left.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\save.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\sep.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\space.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\strikethrough.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\subscript.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\superscript.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\underline.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\undo.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\buttons\wikiword.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\EditorDialog.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\EditorToolbar_FontName.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\EditorToolbar_FontSize.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\EditorToolbar_FormatBlock.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\showtableborder_gecko.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\showtableborder_ie.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\Dialog\createlink.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\Dialog\find.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\Dialog\insertimage.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\Dialog\inserttable.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\Editor2\Dialog\replace.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\bar.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\bdYearBg.1.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\bdYearBg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\blank.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\clock.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\combo_box_arrow.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dateIcon.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\decrementMonth.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\decrementMonth.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpBg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpCurveBL.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpCurveBR.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpCurveTL.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpCurveTR.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpHorizLine.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpHorizLineFoot.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpMonthBg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpMonthBg.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpMonthBg2.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpVertLine.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpYearBg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dpYearBg.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dropdownButtonsArrow.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\dropdownButtonsArrow-disabled.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\floatingPaneClose.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\floatingPaneMaximize.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\floatingPaneMinimize.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\floatingPaneRestore.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\h-bar.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\incrementMonth.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\incrementMonth.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\no.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\no.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\scBackground.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider_down_arrow.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider_left_arrow.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider_right_arrow.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider_up_arrow.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider-bg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider-bg-progress-vert.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider-bg-vert.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider-button.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider-button-horz.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\slider-button-vert.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaAccordionOff.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaAccordionSelected.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaActive-c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaActive-l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaActive-r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaBarBg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaButton-c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaButton-l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaButton-r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaDisabled-c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaDisabled-l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaDisabled-r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaMenuBg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaPressed-c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaPressed-l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\soriaPressed-r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\spinnerDecrement.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\spinnerIncrement.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\submenu_disabled.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\submenu_off.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\submenu_on.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_bot_left.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_bot_left_curr.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_bot_right.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_bot_right_curr.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_close.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_close_h.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_left.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_left_r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_left_r_curr.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_right.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_right_r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_right_r_curr.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_top_left.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\tab_top_right.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\timeIcon.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\toolbar-bg.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\transparent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_blank.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_child.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_expand_minus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_expand_plus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_p.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_t.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_v.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_x.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_y.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_grid_z.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\treenode_node.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\verticalbar.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\whiteDownArrow.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\blank.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\closed.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\document.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\minus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\plus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\transparent.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\Tree.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_blank.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_child.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_expand_minus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_expand_plus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_p.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_t.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_v.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_x.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_y.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_grid_z.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_loading.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\Tree\treenode_loading.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\closed.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\document.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\expand_leaf.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\expand_loading.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\expand_minus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\expand_plus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\i.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\i_bhalf.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\i_half.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\i_long.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\minus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\open.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\plus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\t.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\templates\images\TreeV3\x.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\widget\vml\Chart.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\xml\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\xml\Parse.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\src\xml\XslTransform.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\_bootstrap.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\deferredList.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\epilogue.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\jsunit_browser.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\MockXMLHttpRequest.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\prologue.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_behavior.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_bootstrap.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_bootstrap.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_calendar.ics"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_deferred.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_docs.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_dojo.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_dojo.xsl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_dojo_double.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_dom.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_dom.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_embedded_html.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_fix_ecma.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_hostenv_adobesvg.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_hostenv_browser.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_html.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_html_content.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_html_selection.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_iCalendar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_math.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_MockXMLHttpRequest.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_MockXMLHttpRequest.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_ns.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\test_placeOnScreen.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\animation\test_accelleration_demo.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\animation\test_animation.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\animation\test_wipe.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\charting\test_engine.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_ArrayList.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_Dictionary.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_DictionaryEntry.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_Queue.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_Set.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_SortedList.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_Stack.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\collections\test_Store.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\compat\test_compat.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\crypto\test_Blowfish.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\crypto\test_Blowfish.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\crypto\test_MD5.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\crypto\test_Rijndael.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\crypto\test_SHA.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\crypto\test_SHA256.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\crypto\TESTVALUES.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\books.csv"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\displayFilteringTable.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\displayViaDojoDebug.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\filteringTableStyles.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\geography.opml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\movies.csv"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\rss_feeds.opml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_CsvStore_in_FilteringTable.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_OpmlStore.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_OpmlStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_RdfStore.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_RdfStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_RemoteStore_in_FilteringTable.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_YahooStore_paging.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\test_YahooStore_paging.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\core\test_RemoteStore.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\core\test_RemoteStore.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\BindingHack.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\data_set_four.json"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\movies.csv"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\states_with_header_row.json"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\states_with_keywords.json"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\test_data.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\test_data.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\test_data_binding.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\test_data_binding.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\test_delicious.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\data\old\test_delicious.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\date\test_date.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\date\test_format.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\date\test_serialize.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\date\test_supplemental.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\debug\test_debug.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\debug\test_debug_console.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\debug\test_debug_Firebug.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_container.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_dragcopy.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_dragdropparent.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_draghandle.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_draghandle_2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_dragmove.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_dragmoveparent.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_nested_drop_targets.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\dnd\test_simple.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\empty.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_browserevent.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_Event.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_getEventTarget.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_ie_runtime_usage.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_iframes.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_multiconnect.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_multidisconnect.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_rate_limited_events.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_topic.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_Topic.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\event\test_topic2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\HelloWorld.as"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\test_comm_simple.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\unit_tests_comm.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\UnitTestsComm.as"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\resources\HelloWorld_version6.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\resources\HelloWorld_version8.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\resources\test.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\resources\testBook.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\resources\UnitTestsComm_version6.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\flash\resources\UnitTestsComm_version8.swf"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_arc.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_bezier.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_color.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_Colorspace.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_gfx.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_gfx12.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_group.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_image.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_matrix.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_pattern.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_poly.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_setPath.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\test_transform.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\hsv\test_hsv.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\images\error.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\images\placeholder.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\gfx\images\rect.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\graphics\test_color.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\graphics\test_Colorspace.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\html\ie_byId_bug.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\html\test_csshack.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\html\test_metrics.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\test_currency.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\test_number.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\test_strings.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\test_strings2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\ar\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\cs\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\de\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\el\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\en-au\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\en-us-hawaii\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\en-us-new_york-brooklyn\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\en-us-texas\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\es\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\fa\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\fr\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\he\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\hi\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\it\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\ja\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\ko\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\pl\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\pt\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\ru\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\sw\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\th\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\tr\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\yi\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\zh-cn\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\i18n\nls\zh-tw\salutations.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\button.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\data.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\data-json.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\frag.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\IframeIOResponse.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\IframeIOResponse.text.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\reflector.cgi"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.cache.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.formNode.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.frag.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.javascript.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.json.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.loadProblem.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.method.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.timeout.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO.updateNode.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO_abort.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO_cacheData.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO_cacheData2.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO_data.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_BrowserIO_thread.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_Cookies.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_IframeIO.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_IframeIO.html.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_IframeIO.noform.html.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_IframeIO.text.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_IframeIO.xml.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_postResponse.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_RhinoIO.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\test_ScriptSrcIO.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\timeout.cgi"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\updateNode.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\upload.cgi"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\iframeproxy\test_BrowserIO_ifp.error.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\iframeproxy\test_BrowserIO_ifp.frag.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\iframeproxy\test_BrowserIO_ifp.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\iframeproxy\test_BrowserIO_ifp.method.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\iframeproxy\test_BrowserIO_ifp.timeout.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\scriptsrc\Test.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\scriptsrc\TestJsonp.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\io\scriptsrc\TestMultipart.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\jslink\lib.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\jslink\link-and-run.sh"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\jslink\program.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_array.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_assert.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_declare.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_declare.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_declare_benchmark.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_declare_mixins.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_declare_more.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_lang.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_superclass_benchmark.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lang\test_type.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\mce.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\test_fades.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\test_lfx.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\test_nostart.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\test_rounded.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\test_scale.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\test_wipes.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\lfx\test_wipes2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\bigtext.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\hang.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\img1.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\img2.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\img3.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\img4.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\img5.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\loader\1640\nohang.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\logging\test_Logger.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\math\test_curves.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\math\test_matrix.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\rpc\erroringClass.smd"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\rpc\JSON.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\rpc\test_JsonRPCMediator.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\rpc\test_JsonService.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\rpc\test_YahooService.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\rpc\testClass.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\rpc\testClass.smd"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\storage\storage_test.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\storage\test_storage.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\storage\resources\testBook.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\string\test_Builder.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\string\test_common.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\string\test_extras.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_absolutePosition.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_absolutePositionStrict.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_sizing.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_style_css_insert.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_style_getBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_style_metrics.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_style_setBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\style\test_style_showHideDisplayVisible.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\test_browser.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\test_browser_bookmark.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\test_Manager.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\browser\ApplicationState.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\browser\xhr1.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\browser\xhr2.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\browser\xhr3.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\undo\browser\xhr4.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\uri\test_Uri.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\uuid\test_uuid.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\validate\test_creditCard.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\validate\test_validate.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\buttonProperties.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\comboBoxData.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\comboBoxDataKeyValue.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\dialogContents.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\doc0.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\doc0.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\doc1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\doc2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\external_widget_example_foo.zip"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\googlemaps.api.dojotoolkit.txt"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\loading1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\remoteComboBoxData.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\scriptScope.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\showPost.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tab1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tab2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_AccordionContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_AnimatedPng.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Button.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Button.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Button_static.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Button2.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Calendar.ics"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Chart.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Checkbox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Clock.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ColorPalette.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ComboBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ComboBox.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ContentPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ContentPane_executeScripts.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_createWidget.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_createWidget_parse.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Custom_Widget_Debugging.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Custom_Widget_Inline.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_DatePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_DebugConsole.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_defineWidget.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Dialog.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Dialog_createWidget.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Dialog2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Dialog3.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_DialogRemote.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_DomWidget.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_DropdownContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_DropdownDatePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_DropdownTimePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_FilteringTable.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_FilteringTable_programmatic.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_FisheyeList.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_FloatingPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_FloatingPane_events.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_FloatingPaneCode.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Form.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_funcArgs.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_getWidgetsByFilter.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_GoogleMap.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_HtmlLoader.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_InlineEditBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Layout.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Layout1950.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_LayoutCode.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_LayoutContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_LayoutContainer_2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_LayoutContainer_3.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Menu2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Menu2_Around_Position.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Menu2_Node.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Menu2_Node_Code.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Menu2_Position.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Menu2Code.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ModalFloatingPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_MonthlyCalendar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_PageContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Parser_propertyset.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ProgressBar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_RadioGroup.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_RadioGroup_tabs.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_RemotePane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_RemoteTabController.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_RemoteTabController_programmatic.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ResizeableTextarea.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_ResizeHandle.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_searchids.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Select.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_SelectNLS.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Show.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Slider.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_SlideShow.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_SlideShow2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_SortableTable.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Spinner.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_SplitContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_SplitContainer_2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_SplitContainer_programmatic.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_TabContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_TabContainer_lazyLoad.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_TabContainer_noLayout.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_TabStrict.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_TaskBar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_TimePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_TitlePane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Toaster.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Toggler.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Toolbar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Tooltip.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_validate.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Widget.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_WidgetPackageList.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_widgetsInTemplate.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_Wizard.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\test_YahooMap.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\testRemoteTabController.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\__package__.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\Button.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\README"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\RemotePaths_test.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\test_ExecError.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\test_RemoteAcmeButton.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\test_RemoteAcmeButtonAuto.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\test_RemotePaths.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\test_RemotePaths.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\userActive-c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\userActive-l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\userActive-r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\user-c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\user-l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\userPressed-c.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\userPressed-l.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\userPressed-r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\acme\user-r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Chart\test_area.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Chart\test_bar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Chart\test_fromScript.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Chart\test_line.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\css\demos.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\demoRegistry.json"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\test_demoContainer.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\test_demoItem.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\test_demoNavigator.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\test_demoPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\test_sourcePane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\images\dojoDemos.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\images\test_thumb.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\demoEngine\images\viewDemo.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\deprecated\test_Button_lots.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\deprecated\test_Button_lots2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\EditorToolbarLight.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor_from_textarea.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor2_replace.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor2_shared.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor2Code.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor2InsideDialog.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor2InsideFloatingPane.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_Editor2Toolbar.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_richtext.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_RichText.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_richtext_other.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\Editor\test_RichTextStyleSheets.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\1.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\2.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\3.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\4.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\5.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\6.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\animatedpng_frames.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\animatedpng_static.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\arrowSmall.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\check.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\create.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\createsmall.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\customTabLeft.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\customTabRight.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\down.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\downsmall.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\fisheye_1.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\fisheye_2.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\fisheye_3.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\fisheye_4.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\flatScreen.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\forward.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\ft-head.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\ft-headdown.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\ft-headup.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\graph.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\loading.jpg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\note.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\note.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\openFolder.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\plus.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\question.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\recyclebin.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\removesmall.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\reply.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tab_left.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tab_left_r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tab_left_r_curr.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tab_right.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tab_right_r.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tab_right_r_curr.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\Thumbs.db"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tools.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tube.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\tubeTall.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\up.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\upsmall.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\images\x.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\test_more_widgets.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\test_myns.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\test_myns_dynamic.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\myns\manifest.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\myns\widget\check.gif"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\myns\widget\Check.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\myns\widget\CheckBox.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\namespaces\myns\widget\CheckBox.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\createChild"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\getChildren"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\move"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\removeNode"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_0.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_tree_10.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_3.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_4.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_5.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_5_1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_6.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_7.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_8.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\tree\test_Tree_9.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\bench_lazyChildren2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\copy.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\create_other.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\demo.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\destroy.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\disableWrap.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\dnd_other.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\dnd1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\dndselector.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\docIcon1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\eagerCreate1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\eagerCreate2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\eagerCreateCompare.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\editor.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\editor_rpc.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\expandLevel1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\go.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\largednd.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\largedndmenu.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\largeNoWrap.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\links.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\loading1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\loading2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\loadingExpandAll.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\loadingPhp.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\makeTree.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\makeTree.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\markup_noscript.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\markup_noscript_2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\markup1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\markup2.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\markup3.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\memory.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\menu1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\program1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\programTree.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\removeClass.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\rpc.php"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\rpc1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\selectedMarkup1.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\selector.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\selectorNoMulti.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\thin.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\treeStyle.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\xtree_bench.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\blank.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\file.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\foldericon.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\I.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\L.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\LICENSE"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\Lminus.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\Lplus.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\new.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\openfoldericon.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\pspbrwse.jbf"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\T.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\Tminus.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\images\Tplus.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\clone"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\createChild"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\destroyChild"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\detach"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\editLabelFinishCancel"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\editLabelSave"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\editLabelStart"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\getChildren"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\local\move"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\xtree\LICENSE"
+ BuildAction = "None"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\xtree\xtree.css"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\widget\treeV3\xtree\xtree.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\doc0.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_forceXDomainLocal.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_remote.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_remoteDelayed.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_remoteFail.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_remoteLocalMix.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_xdomainDropdownDatePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_xdomainFisheyeList.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_xdomainSimpleDropdownDatePicker.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\test_xdomainTooltip.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\browser\xhr1.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\browser\xhr2.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\browser\xhr3.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\browser\xhr4.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\images\fisheye_1.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\images\fisheye_2.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\images\fisheye_3.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xdomain\images\fisheye_4.png"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\full-page.xsl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\hello-world.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\nav-tree.xsl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\placeholder.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\simple.xsl"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\site.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\test_ECMA_E4X.js"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\test_parse.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\test_svgScope.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\test_svgScope.svg"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "js\dojo\tests\xml\test_XslTransform.html"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\AppBase.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\AppConfig.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\AppFields.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\Catalog.xml"
+ BuildAction = "Content"
+ />
+ <File
+ RelPath = "Resources\Queries.xml"
+ BuildAction = "Content"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/Web.csproj.webinfo b/struts-sandbox/overdrive/PhoneBook/Web/Web.csproj.webinfo
new file mode 100644
index 0000000..6f77159
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/Web.csproj.webinfo
@@ -0,0 +1,4 @@
+<VisualStudioUNCWeb>
+ <Web URLPath = "http://localhost/PhoneBook/Web.csproj" />
+</VisualStudioUNCWeb>
+
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/default.htm b/struts-sandbox/overdrive/PhoneBook/Web/default.htm
new file mode 100644
index 0000000..15a1a22
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/default.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=./Forms/Directory.aspx">
+ </head>
+ <body>
+ <p>Loading...</p>
+ </body>
+</html>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/providers.config b/struts-sandbox/overdrive/PhoneBook/Web/providers.config
new file mode 100644
index 0000000..e0a5241
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/providers.config
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8"?>
+<providers
+xmlns="http://ibatis.apache.org/providers"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+<clear/>
+<provider
+ name="sqlServer1.0"
+ description="Microsoft SQL Server, provider V1.0.3300.0 in framework .NET V1.0"
+ enabled="false"
+ assemblyName="System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider
+ name="sqlServer1.1"
+ description="Microsoft SQL Server, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ default="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider
+ name="sqlServer2.0"
+ enabled="false"
+ description="Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass=" System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters = "false"
+ useParameterPrefixInSql = "true"
+ useParameterPrefixInParameter = "true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider name="OleDb1.1"
+ description="OleDb, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider name="OleDb2.0"
+ description="OleDb, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc1.1"
+ description="Odbc, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc2.0"
+ description="Odbc, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle9.2"
+ description="Oracle, Oracle provider V9.2.0.401"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=9.2.0.401, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle10.1"
+ description="Oracle, oracle provider V10.1.0.301"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=10.1.0.301, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracleClient1.0"
+ description="Oracle, Microsoft provider V1.0.5000.0"
+ enabled="false"
+ assemblyName="System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.OracleClient.OracleConnection"
+ commandClass="System.Data.OracleClient.OracleCommand"
+ parameterClass="System.Data.OracleClient.OracleParameter"
+ parameterDbTypeClass="System.Data.OracleClient.OracleType"
+ parameterDbTypeProperty="OracleType"
+ dataAdapterClass="System.Data.OracleClient.OracleDataAdapter"
+ commandBuilderClass="System.Data.OracleClient.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ allowMARS="false"
+ />
+ <provider
+ name="ByteFx"
+ description="MySQL, ByteFx provider V0.7.6.15073"
+ enabled="false"
+ assemblyName="ByteFX.MySqlClient, Version=0.7.6.15073, Culture=neutral, PublicKeyToken=f2fef6fed1732fc1" connectionClass="ByteFX.Data.MySqlClient.MySqlConnection"
+ commandClass="ByteFX.Data.MySqlClient.MySqlCommand"
+ parameterClass="ByteFX.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="ByteFX.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="ByteFX.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="ByteFX.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="MySql"
+ description="MySQL, MySQL provider 1.0.7.30072"
+ enabled="true"
+ assemblyName="MySql.Data, Version=1.0.7.30072, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionClass="MySql.Data.MySqlClient.MySqlConnection"
+ commandClass="MySql.Data.MySqlClient.MySqlCommand"
+ parameterClass="MySql.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="MySql.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="MySql.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="MySql.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="?"
+ allowMARS="false"
+ />
+ <provider name="SQLite3"
+ description="SQLite, SQLite.NET provider V0.21.1869.3794"
+ enabled="false"
+ assemblyName="SQLite.NET, Version=0.21.1869.3794, Culture=neutral, PublicKeyToken=c273bd375e695f9c"
+ connectionClass="Finisar.SQLite.SQLiteConnection"
+ commandClass="Finisar.SQLite.SQLiteCommand"
+ parameterClass="Finisar.SQLite.SQLiteParameter"
+ parameterDbTypeClass="System.Data.DbType, System.Data"
+ parameterDbTypeProperty="DbType"
+ dataAdapterClass="Finisar.SQLite.SQLiteDataAdapter"
+ commandBuilderClass="Finisar.SQLite.SQLiteCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ setDbParameterPrecision="false"
+ setDbParameterScale="false"
+ allowMARS="false"
+ />
+ <provider
+ name="Firebird1.7"
+ description="Firebird, Firebird SQL .NET provider V1.7.0.33200"
+ enabled="false"
+ assemblyName="FirebirdSql.Data.Firebird, Version=1.7.0.33200, Culture=neutral, PublicKeyToken=fa843d180294369d" connectionClass="FirebirdSql.Data.Firebird.FbConnection"
+ commandClass="FirebirdSql.Data.Firebird.FbCommand"
+ parameterClass="FirebirdSql.Data.Firebird.FbParameter"
+ parameterDbTypeClass="FirebirdSql.Data.Firebird.FbDbType"
+ parameterDbTypeProperty="FbDbType"
+ dataAdapterClass="FirebirdSql.Data.Firebird.FbDataAdapter"
+ commandBuilderClass="FirebirdSql.Data.Firebird.FbCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="PostgreSql0.99.1.0"
+ description="PostgreSql, Npgsql provider V0.99.1.0"
+ enabled="false"
+ assemblyName="Npgsql, Version=0.99.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"
+ connectionClass="Npgsql.NpgsqlConnection"
+ commandClass="Npgsql.NpgsqlCommand"
+ parameterClass="Npgsql.NpgsqlParameter"
+ parameterDbTypeClass="NpgsqlTypes.NpgsqlDbType"
+ parameterDbTypeProperty="NpgsqlDbType"
+ dataAdapterClass="Npgsql.NpgsqlDataAdapter"
+ commandBuilderClass="Npgsql.NpgsqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ allowMARS="true"
+ />
+ <provider
+ name="iDb2.10"
+ description="IBM DB2 Provider, V 10.0"
+ enabled="false"
+ assemblyName="IBM.Data.DB2.iSeries, Version=10.0.0.0,Culture=neutral, PublicKeyToken=9cdb2ebfb1f93a26, Custom=null" connectionClass="IBM.Data.DB2.iSeries.iDB2Connection"
+ commandClass="IBM.Data.DB2.iSeries.iDB2Command"
+ parameterClass="IBM.Data.DB2.iSeries.iDB2Parameter"
+ parameterDbTypeClass="IBM.Data.DB2.iSeries.iDB2DbType"
+ parameterDbTypeProperty="iDB2DbType"
+ dataAdapterClass="IBM.Data.DB2.iSeries.iDB2DataAdapter"
+ commandBuilderClass="IBM.Data.DB2.iSeries.iDB2CommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Informix"
+ description="Informix NET Provider, 2.81.0.0"
+ enabled="false"
+ assemblyName="IBM.Data.Informix, Version=2.81.0.0, Culture=neutral, PublicKeyToken=7c307b91aa13d208"
+ connectionClass="IBM.Data.Informix.IfxConnection"
+ commandClass="IBM.Data.Informix.IfxCommand"
+ parameterClass="IBM.Data.Informix.IfxParameter"
+ parameterDbTypeClass="IBM.Data.Informix.IfxType"
+ parameterDbTypeProperty="IfxType"
+ dataAdapterClass="IBM.Data.Informix.IfxDataAdapter"
+ commandBuilderClass="IBM.Data.Informix.IfxCommandBuilder"
+ usePositionalParameters = "true"
+ useParameterPrefixInSql = "false"
+ useParameterPrefixInParameter = "false"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+</providers>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/sqlmap.config b/struts-sandbox/overdrive/PhoneBook/Web/sqlmap.config
new file mode 100644
index 0000000..fa86239
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/sqlmap.config
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" >
+
+ <properties resource="sqlmap.config.xml"/>
+
+ <settings>
+ <setting useStatementNamespaces="false"/>
+ <setting cacheModelsEnabled="true"/>
+ </settings>
+
+ <database>
+ <provider name="${provider}"/>
+ <dataSource name="default" connectionString="${development}"/>
+ </database>
+
+ <sqlMaps>
+ <sqlMap resource="${root}Resources/Queries.xml"/>
+ </sqlMaps>
+
+</sqlMapConfig>
diff --git a/struts-sandbox/overdrive/PhoneBook/Web/sqlmap.config.xml b/struts-sandbox/overdrive/PhoneBook/Web/sqlmap.config.xml
new file mode 100644
index 0000000..0946f18
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/Web/sqlmap.config.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<settings>
+ <add key="root" value="./" />
+ <add key="provider" value="MySql" />
+ <add key="development" value="Host=CLIFFORD;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+ <add key="production" value="Host=zippy;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+</settings>
diff --git a/struts-sandbox/overdrive/PhoneBook/prebuild.bat b/struts-sandbox/overdrive/PhoneBook/prebuild.bat
new file mode 100644
index 0000000..ba6e89d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook/prebuild.bat
@@ -0,0 +1 @@
+XCOPY %1Test\Resources\*.* %1Web\Resources\*.* /M /Y
diff --git a/struts-sandbox/overdrive/PhoneBook2/PhoneBook2.csproj b/struts-sandbox/overdrive/PhoneBook2/PhoneBook2.csproj
new file mode 100644
index 0000000..4a8187b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/PhoneBook2.csproj
@@ -0,0 +1,62 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>PhoneBook2</RootNamespace>
+ <AssemblyName>PhoneBook2</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/PhoneBook2.sln b/struts-sandbox/overdrive/PhoneBook2/PhoneBook2.sln
new file mode 100644
index 0000000..fb39283
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/PhoneBook2.sln
@@ -0,0 +1,89 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneBook2", "PhoneBook2.csproj", "{EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "projects\Core\Core.csproj", "{F65FCC91-C9CB-40CE-87A6-C0CB00F73592}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "projects\Test\Test.csproj", "{C461D986-BC3C-4A48-8B6F-B4EFA47033E6}"
+EndProject
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "C:\...\Web\", "projects\Web\", "{055ABF30-6F91-48EB-B457-2D9274F0D34F}"
+ ProjectSection(WebsiteProperties) = preProject
+ ProjectReferences = "{F65FCC91-C9CB-40CE-87A6-C0CB00F73592}|PhoneBook.Core.dll;"
+ Debug.AspNetCompiler.VirtualPath = "/Web"
+ Debug.AspNetCompiler.PhysicalPath = "projects\Web\"
+ Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\Web\"
+ Debug.AspNetCompiler.Updateable = "true"
+ Debug.AspNetCompiler.ForceOverwrite = "true"
+ Debug.AspNetCompiler.FixedNames = "false"
+ Debug.AspNetCompiler.Debug = "True"
+ Release.AspNetCompiler.VirtualPath = "/Web"
+ Release.AspNetCompiler.PhysicalPath = "projects\Web\"
+ Release.AspNetCompiler.TargetPath = "PrecompiledWeb\Web\"
+ Release.AspNetCompiler.Updateable = "true"
+ Release.AspNetCompiler.ForceOverwrite = "true"
+ Release.AspNetCompiler.FixedNames = "false"
+ Release.AspNetCompiler.Debug = "False"
+ VWDPort = "3594"
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F5B697F2-0FFC-4459-BCBB-5F6F4DB01D64}"
+ ProjectSection(SolutionItems) = preProject
+ ..\Nexus\Core\Validators\DateTimeProcessor.cs = ..\Nexus\Core\Validators\DateTimeProcessor.cs
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|.NET = Debug|.NET
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Release|.NET = Release|.NET
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Release|.NET.ActiveCfg = Release|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {EB1F252E-0AA5-4485-966D-9D7AAC18AC5E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Release|.NET.ActiveCfg = Release|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Debug|.NET.ActiveCfg = Debug|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Release|.NET.ActiveCfg = Release|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Debug|.NET.ActiveCfg = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Debug|.NET.Build.0 = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Debug|Any CPU.ActiveCfg = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Debug|Mixed Platforms.ActiveCfg = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Debug|Mixed Platforms.Build.0 = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Release|.NET.ActiveCfg = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Release|.NET.Build.0 = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Release|Any CPU.ActiveCfg = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Release|Mixed Platforms.ActiveCfg = Debug|.NET
+ {055ABF30-6F91-48EB-B457-2D9274F0D34F}.Release|Mixed Platforms.Build.0 = Debug|.NET
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/struts-sandbox/overdrive/PhoneBook2/Properties/AssemblyInfo.cs b/struts-sandbox/overdrive/PhoneBook2/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c3e1563
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PhoneBook2")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PhoneBook2")]
+[assembly: AssemblyCopyright("Copyright © 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e7d22efd-af8a-4a6c-ab93-3afb71e1c7f7")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/App.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/App.cs
new file mode 100644
index 0000000..39c5e07
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/App.cs
@@ -0,0 +1,205 @@
+/*
+* Copyright 2005 The Apache Software Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Tokens representing context keys.
+ /// </summary>
+ ///
+ public class App
+ {
+ private App()
+ {
+ // No need to construct static helper class
+ }
+
+ #region Properties
+
+ /// <summary>
+ /// Token for Catalog property.
+ /// </summary>
+ ///
+ public const string CATALOG_KEY = "Catalog";
+
+ /// <summary>
+ /// Token for entry_key property.
+ /// </summary>
+ ///
+ public const string ENTRY_KEY = "entry_key";
+
+ /// <summary>
+ /// Token for first_name property.
+ /// </summary>
+ ///
+ public const string FIRST_NAME = "first_name";
+
+ /// <summary>
+ /// Token for last_name property.
+ /// </summary>
+ ///
+ public const string LAST_NAME = "last_name";
+
+ /// <summary>
+ /// Token for user_name property.
+ /// </summary>
+ ///
+ public const string USER_NAME = "user_name";
+
+ /// <summary>
+ /// Token for extension property.
+ /// </summary>
+ ///
+ public const string EXTENSION = "extension";
+
+ /// <summary>
+ /// Token for hired property.
+ /// </summary>
+ ///
+ public const string HIRED = "hired";
+
+ /// <summary>
+ /// Token for hours property.
+ /// </summary>
+ ///
+ public const string HOURS = "hours";
+
+ /// <summary>
+ /// Token for editor property.
+ /// </summary>
+ ///
+ public const string EDITOR = "editor";
+
+ #endregion
+
+ #region Commands
+
+ public const string FROM_DATE = "from_date";
+
+ public const string THRU_DATE = "thru_date";
+
+ /// <summary>
+ /// Token for SQL LIMIT clause.
+ /// </summary>
+ ///
+ public const string ITEM_LIMIT = "item_limit";
+
+ /// <summary>
+ /// Token for SQL OFFSET clause.
+ /// </summary>
+ ///
+ public const string ITEM_OFFSET = "item_offset";
+
+ /// <summary>
+ /// Token for SQL COUNT clause.
+ /// </summary>
+ ///
+ public const string ITEM_COUNT = "item_count";
+
+ /// <summary>
+ /// Token for select one command.
+ /// </summary>
+ ///
+ public const string ENTRY = "entry";
+
+ /// <summary>
+ /// Token for list all command.
+ /// </summary>
+ ///
+ public const string ENTRY_LIST = "entry_list";
+
+ /// <summary>
+ /// Token for Entry Initial command.
+ /// </summary>
+ ///
+ public const string ENTRY_INITIAL = "entry_initial";
+
+ /// <summary>
+ /// Token for List Last Names command.
+ /// </summary>
+ ///
+ public const string LAST_NAME_LIST = "last_name_list";
+
+ /// <summary>
+ /// Token for List Last Names command.
+ /// </summary>
+ ///
+ public const string FIRST_NAME_LIST = "first_name_list";
+
+ /// <summary>
+ /// Token for List Extensions command.
+ /// </summary>
+ ///
+ public const string EXTENSION_LIST = "extension_list";
+
+ /// <summary>
+ /// Token for List UserNames command.
+ /// </summary>
+ ///
+ public const string USER_NAME_LIST = "user_name_list";
+
+ /// <summary>
+ /// Token for List Hire Dates command.
+ /// </summary>
+ ///
+ public const string HIRED_LIST = "hired_list";
+
+ /// <summary>
+ /// Token for List Hours command.
+ /// </summary>
+ ///
+ public const string HOURS_LIST = "hours_list";
+
+ /// <summary>
+ /// Token for Entry Find command.
+ /// </summary>
+ ///
+ public const string ENTRY_FIND = "entry_find";
+
+ /// <summary>
+ /// Token for Entry Save command.
+ /// </summary>
+ ///
+ public const string ENTRY_SAVE = "entry_save";
+
+ /// <summary>
+ /// Token for Entry Delete command.
+ /// </summary>
+ ///
+ public const string ENTRY_DELETE = "entry_delete";
+
+ #endregion
+
+ #region Messages
+
+ /// <summary>
+ /// Token for Directory page title.
+ /// </summary>
+ public const string DIRECTORY_TITLE = "directory_title";
+
+ /// <summary>
+ /// Token for Directory directory page heading.
+ /// </summary>
+ public const string DIRECTORY_HEADING = "directory_heading";
+
+ /// <summary>
+ /// Token for Directory page prompt.
+ /// </summary>
+ public const string DIRECTORY_PROMPT = "directory_prompt";
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntry.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntry.cs
new file mode 100644
index 0000000..4a0557d
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntry.cs
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use _Store file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Expose field attributes as public properties.
+ /// </summary>
+ ///
+ [Serializable]
+ public class AppEntry : EntryDictionary
+ {
+
+ public AppEntry()
+ {
+ // Default contstructor
+ }
+
+ public AppEntry(IDictionary sources)
+ {
+ AddAll(sources);
+ }
+
+ public AppEntry(AppEntry row)
+ {
+ AddAll(row);
+ }
+
+ /// <summary>
+ /// Add each source entry to our internal store.
+ /// </summary>
+ /// <remarks><p>
+ /// Entries with keys that match the property names will be exposed.
+ /// Other entries may be added, but can only be retrieved via Get.
+ /// </p></remarks>
+ /// <param name="row">Entries to add</param>
+ ///
+ public void AddAll(AppEntry row)
+ {
+ ICollection keys = row.Keys;
+ foreach (string key in keys)
+ {
+ Add(key, row.Get(key));
+ }
+ }
+
+ /*
+ public string Property
+ {
+ get { return Get(App.PROPERTY); }
+ set { Set(App.PROPERTY, value); }
+ }
+ */
+
+ public string entry_key
+ {
+ get { return Get(App.ENTRY_KEY); }
+ set { Set(App.ENTRY_KEY, value); }
+ }
+
+ public string first_name
+ {
+ get { return Get(App.FIRST_NAME); }
+ set { Set(App.FIRST_NAME, value); }
+ }
+
+ public string last_name
+ {
+ get { return Get(App.LAST_NAME); }
+ set { Set(App.LAST_NAME, value); }
+ }
+
+ public string extension
+ {
+ get { return Get(App.EXTENSION); }
+ set { Set(App.EXTENSION, value); }
+ }
+
+ public string user_name
+ {
+ get { return Get(App.USER_NAME); }
+ set { Set(App.USER_NAME, value); }
+ }
+
+ public string hired
+ {
+ get { return Get(App.HIRED); }
+ set { Set(App.HIRED, value); }
+ }
+
+ public string hours
+ {
+ get { return Get(App.HOURS); }
+ set { Set(App.HOURS, value); }
+ }
+
+ public string editor
+ {
+ get { return Get(App.EDITOR); }
+ set { Set(App.EDITOR, value); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntryList.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntryList.cs
new file mode 100644
index 0000000..8a865bc
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntryList.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Implement Nexus.Core.IEntryList for AppEntry objects.
+ /// </summary>
+ ///
+ public class AppEntryList : ArrayList, IEntryList
+ {
+ public object Insert(string key)
+ {
+ AppEntry entry = new AppEntry();
+ entry.entry_key = key;
+ Insert(0, entry);
+ return entry;
+ }
+
+ public void AddEntry(IDictionary row)
+ {
+ AppEntry entry = new AppEntry();
+ foreach (DictionaryEntry col in row)
+ {
+ string key = Convert.ToString(col.Key);
+ string value = Convert.ToString(col.Value);
+ entry.Add(key, value);
+ }
+ Add(entry);
+ }
+
+ public AppEntry[] ToAppEntryArray()
+ {
+ return (AppEntry[])ToArray(typeof(AppEntry));
+ }
+ }
+}
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntryListProcessor.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntryListProcessor.cs
new file mode 100644
index 0000000..f9f8e38
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppEntryListProcessor.cs
@@ -0,0 +1,17 @@
+using Nexus.Core;
+using Nexus.Core.Validators;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Implement Nexus.Core.Validators.EntryListProcess for AppEntryList.
+ /// </summary>
+ ///
+ public class AppEntryListProcessor : EntryListProcessor
+ {
+ public override IEntryList NewEntryList()
+ {
+ return new AppEntryList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppUserProfile.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppUserProfile.cs
new file mode 100644
index 0000000..0d0dac8
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/AppUserProfile.cs
@@ -0,0 +1,84 @@
+using System.Security.Principal;
+using System.Text;
+using Nexus.Core.Profile;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Extend UserProfile to include properties specific to this application,
+ /// such as IsEditor.
+ /// </summary>
+ ///
+ public class AppUserProfile : UserProfile
+ {
+ /// <summary>
+ /// Provide a field for IsEditor property.
+ /// </summary>
+ private bool _IsEditor = false;
+
+ /// <summary>
+ /// Indicate whether user has editing priveleges.
+ /// </summary>
+ ///
+ public bool IsEditor
+ {
+ get { return _IsEditor; }
+ set { _IsEditor = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for Entry property.
+ /// </summary>
+ ///
+ private AppEntry _Entry;
+
+
+ /// <summary>
+ /// Record directory entry for user.
+ /// </summary>
+ ///
+ public AppEntry Entry
+ {
+ get { return _Entry; }
+ set
+ {
+ _Entry = value;
+ if (_Entry != null)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(_Entry.first_name);
+ sb.Append(" ");
+ sb.Append(Entry.last_name);
+ FullName = sb.ToString().Trim();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provide a field for FullName property.
+ /// </summary>
+ ///
+ private string _FullName;
+
+ /// <summary>
+ /// Record the user's full name (first and last names).
+ /// </summary>
+ ///
+ public string FullName
+ {
+ get { return _FullName; }
+ set { _FullName = value; }
+ }
+
+ /// <summary>
+ /// Instantiate from an IIdentity.
+ /// </summary>
+ /// <param name="id">Identity to copy for this profile.</param>
+ ///
+ public AppUserProfile(IIdentity id)
+ {
+ Principal = new UserPrincipal(id);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Class1.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Class1.cs
new file mode 100644
index 0000000..e7a82d0
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Class1.cs
@@ -0,0 +1,7 @@
+
+namespace PhoneBook2.Core
+{
+ public class Class1
+ {
+ }
+}
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/AppCommand.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/AppCommand.cs
new file mode 100644
index 0000000..faeb838
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/AppCommand.cs
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using IBatisNet.DataMapper;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Extend RequestCommand with data access methods.
+ /// </summary>
+ ///
+ public abstract class BaseMapper : RequestCommand
+ {
+ /// <summary>
+ /// Provide a field for Mapper property.
+ /// </summary>
+ ///
+ private SqlMapper _Mapper;
+
+ /// <summary>
+ /// Expose a preconfigured SqlMapper instance that Commands can use to run statements.
+ /// </summary>
+ /// <remarks><p>
+ /// Commands use Mapper to invoke SqlMap statements, such as
+ /// <code>
+ /// object row = Mapper.QueryForObject (QueryID, context);
+ /// </code>.
+ /// </p><p>
+ /// Any SqlMapper API method may be called.
+ /// </p><p>
+ /// The default behavior of BAseNexusCommand is to use the
+ /// command ID if the QueryID is null.
+ /// </p></remarks>
+ /// <returns>Preconfigured Mapper instance</returns>
+ ///
+ public SqlMapper Mapper
+ {
+ get { return _Mapper; }
+ set { _Mapper = value; }
+
+ }
+
+ /// <summary>
+ /// Indicate whether string is null or zero length.
+ /// </summary>
+ /// <param name="input">Input to validate</param>
+ /// <returns>True if string is nyull or zero length</returns>
+ ///
+ public bool IsEmpty(string input)
+ {
+ return ((input == null) || (input.Equals(String.Empty)));
+ }
+
+ /// <summary>
+ /// Create new Global Universal Identifer as a formatted string.
+ /// </summary>
+ /// <returns>String representing a new GUID</returns>
+ /// <remarks><p>
+ /// No two calls to this method will ever return duplicate strings.
+ /// </p></remarks>
+ ///
+ public string GuidString()
+ {
+ Guid guid = Guid.NewGuid();
+ string gs = guid.ToString();
+ return gs;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseCommand.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseCommand.cs
new file mode 100644
index 0000000..109f9ea
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseCommand.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Text;
+using Agility.Core;
+using IBatisNet.DataMapper;
+using Nexus.Core;
+using Spring.Objects.Factory;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Provide an abtract extension of BaseNexusCommand
+ /// with shared members for WNE Commands,
+ /// including a SqlMapper factory method.
+ /// </summary>
+ /// <remarks><p>
+ /// Superclasses must implement a NexusExecute method (inherited from BaseNexusCommand.
+ /// </p><p>
+ /// Concrete subclasses are expected to be created by a IOC Container, like Spring.NET.
+ /// Most concrete subclasses will be "decorator" classes designed to behave
+ /// differently based on what properties are set when the class is created.
+ /// Others may be custom classes with predefined behaviors.
+ /// </p><p>
+ /// The Spring catalog provides the versatility we need to mix-and-match
+ /// base commands with custom commands, as needed,
+ /// and call either from the client in exactly the same way.
+ /// </p><p>
+ /// NOTE that subclasses should NOT use the Outcome property of
+ /// the Nexus context since they may be subcommands in a Chain.
+ /// All BaseCommands should use the idiom
+ /// <code>context[ID] = object</code>
+ /// to store output.
+ /// </p><p>
+ /// NOTE after using the ReShaper code reformatter,
+ /// the Mapper method needs to be edited.
+ /// ReSharper removes an absolute reference that we actually need.
+ /// (Our Mapper method calls the IBatisNet Mapper method.)
+ /// The correct line of code is maintained as a comment,
+ /// so that it can <b>copied</b> over the reformatted version.
+ /// </p></remarks>
+ public abstract class BaseCommand : RequestCommand, IObjectNameAware
+ {
+ /// <summary>
+ /// If an ID is not provided, default to the ObjectName.
+ /// </summary>
+ public override string ID
+ {
+ get
+ {
+ string _ID = base.ID;
+ if (null == _ID) return ObjectName;
+ else return _ID;
+ }
+ set { base.ID = value; }
+ }
+
+ private string _ObjectName;
+
+ /// <summary>
+ /// Provide a field for the Spring object name (set by Spring).
+ /// </summary>
+ public string ObjectName
+ {
+ get { return _ObjectName; }
+ set { _ObjectName = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for the Remark property.
+ /// </summary>
+ private string _Remark;
+
+ /// <summary>
+ /// Accept an arbitrary comment about a command
+ /// -- more for use in the XML document.
+ /// </summary>
+ ///
+ public string Remark
+ {
+ get { return _Remark; }
+ set { _Remark = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for the Mapper property.
+ /// </summary>
+ ///
+ private SqlMapper _Mapper;
+
+ /// <summary>
+ /// Expose a preconfigured SqlMapper instance that Commands can use to run statements.
+ /// </summary>
+ /// <remarks><p>
+ /// Commands use Mapper to invoke SqlMap statements, such as
+ /// <code>
+ /// object row = Mapper ().QueryForObject (QueryID, context);
+ /// </code>.
+ /// </p><p>
+ /// Any SqlMapper API method may be called.
+ /// </p><p>
+ /// The default behavior of BAseNexusCommand is to use the
+ /// command ID if the QueryID is null.
+ /// </p></remarks>
+ /// <returns>Preconfigured Mapper</returns>
+ ///
+ public SqlMapper Mapper
+ {
+ get { return _Mapper; }
+ set { _Mapper = value; }
+ }
+
+ /// <summary>
+ /// Indicate whether string is null or zero length.
+ /// </summary>
+ /// <param name="input">Input to validate</param>
+ /// <returns>True if string is nyull or zero length</returns>
+ ///
+ protected bool IsEmpty(string input)
+ {
+ return ((input == null) || (input.Equals(String.Empty)));
+ }
+
+ /// <summary>
+ /// Create new Global Universal Identifer as a formatted string.
+ /// </summary>
+ /// <returns>String representing a new GUID</returns>
+ /// <remarks><p>
+ /// No two calls to this method will ever return duplicate strings.
+ /// </p></remarks>
+ ///
+ protected string GuidString()
+ {
+ Guid guid = Guid.NewGuid();
+ string gs = guid.ToString();
+ return gs;
+ }
+
+ /// <summary>
+ /// Document the wildcard character used by SQL queries.
+ /// </summary>
+ public const string WILDCARD = "%";
+
+ /// <summary>
+ /// Prepare an attribute for use with a SQL wildcard ("LIKE") operation.
+ /// </summary>
+ /// <remarks><p>
+ /// A wildcard is prepended and appended for a full, scan-across match,
+ /// so that the string will found in any part of the field.
+ /// </p></remarks>
+ /// <param name="context">Context with attribute to escape</param>
+ /// <param name="id">Name of attribute to escape</param>
+ protected void LikeMe(IContext context, string id)
+ {
+ string param = context[id] as string;
+ if (null != param)
+ {
+ StringBuilder sb = new StringBuilder(WILDCARD);
+ sb.Append(param);
+ sb.Append(WILDCARD);
+ context[id] = sb.ToString();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseCount.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseCount.cs
new file mode 100644
index 0000000..8540d9e
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseCount.cs
@@ -0,0 +1,17 @@
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Invoke a query that returns the count of a result set.
+ /// </summary>
+ public class BaseCount : BaseMapper
+ {
+ public override bool RequestExecute(IRequestContext context)
+ {
+ object result = Mapper.QueryForObject(QueryID, context);
+ context[App.ITEM_COUNT] = result;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseDelete.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseDelete.cs
new file mode 100644
index 0000000..1ac248c
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseDelete.cs
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Execute delete statement indicated by QueryID
+ /// for a single entity.
+ /// </summary>
+ ///
+ public class BaseDelete : BaseMapper
+ {
+ public override bool RequestExecute(IRequestContext context)
+ {
+ int count = Mapper.Delete(QueryID, context);
+ if (count == 0) throw new ApplicationException("Delete: Record not found.");
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseEntry.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseEntry.cs
new file mode 100644
index 0000000..f7f69d1
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseEntry.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Execute database statement indicated by QueryID
+ /// for a single object,
+ /// returning each attribute in the main context.
+ /// </summary>
+ ///
+ public class BaseEntry : BaseMapper
+ {
+ public override bool RequestExecute(IRequestContext context)
+ {
+ object o = Mapper.QueryForObject(QueryID, context);
+ IDictionary result = o as IDictionary;
+
+ ICollection keys = result.Keys;
+ foreach (string key in keys)
+ {
+ context[key] = result[key];
+ }
+
+ AppEntry entry = new AppEntry(result);
+ context[ID] = entry;
+
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseFilterList.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseFilterList.cs
new file mode 100644
index 0000000..5774b59
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseFilterList.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Execute database statement indicated by QueryID
+ /// and wrap result in KeyValue objects
+ /// so that lists can be displayed by standard methods.
+ /// </summary>
+ ///
+ public class BaseFilterList : BaseMapper
+ {
+ public override bool RequestExecute(IRequestContext context)
+ {
+ IList rows = Mapper.QueryForList(QueryID, null);
+ IKeyValueList list = new KeyValueList();
+ foreach (object key in rows)
+ {
+ list.Add(new KeyValue(key.ToString(), key));
+ }
+ context[ID] = list;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseList.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseList.cs
new file mode 100644
index 0000000..ee91d82
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseList.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections;
+using Nexus.Core;
+using PhoneBook.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Run the select query indicated by QueryID,
+ /// first escaping any LikeIDs and extending any date ranges,
+ /// and return the result as an IList,
+ /// </summary>
+ public class BaseList : BaseCommand
+ {
+ private IList _LikeIDs = null;
+
+ /// <summary>
+ /// Names of key fields to escape for a "like" search.
+ /// </summary>
+ public IList LikeIDs
+ {
+ get { return _LikeIDs; }
+ set { _LikeIDs = value; }
+ }
+
+ /// <summary>
+ /// Generate an array from the IDs.
+ /// </summary>
+ /// <returns>Array of LikeIDs</returns>
+ protected string[] GetArray(string IDs)
+ {
+ string csv = IDs;
+ bool noLike = ((null == csv) || (string.Empty.Equals(csv)));
+ if (noLike)
+ return new string[0];
+ else
+ {
+ string[] _Array = csv.Split(',');
+ return _Array;
+ }
+ }
+
+ /// <summary>
+ /// Document the last second of the day
+ /// so as to calculate values for concepts like today and tomorrow.
+ /// </summary>
+ private string LAST_TICK = " 23:59";
+
+ /// <summary>
+ /// If ThruDate is set to the minimum time (00:00),
+ /// set to the maximum time instead (23:59).
+ /// </summary>
+ /// <param name="context"></param>
+ private void ExtendThruDate(IRequestContext context)
+ {
+ bool have = context.Contains(App.THRU_DATE);
+ if (!have) return;
+ DateTime thruDate = DateTime.MinValue;
+ try
+ {
+ thruDate = (DateTime) context[App.THRU_DATE];
+ }
+ catch (Exception e)
+ {
+ if (e != null) return; // Placate Resharper
+ }
+ bool defaultTime = (thruDate.Hour == 0) && (thruDate.Minute == 0) && (thruDate.Second == 0) &&
+ (thruDate.Millisecond == 0);
+ if (defaultTime)
+ {
+ string strThruDate = thruDate.ToShortDateString() + LAST_TICK;
+ DateTime newThruDate = Convert.ToDateTime(strThruDate);
+ context.Remove(App.THRU_DATE);
+ context.Add(App.THRU_DATE, newThruDate);
+ }
+ }
+
+ /// <summary>
+ /// Prepare special attributes for the query.
+ /// </summary>
+ /// <param name="context">The context we are processing</param>
+ protected void PreProcess(IRequestContext context)
+ {
+ // Escape any "like" fields
+ IList likes = LikeIDs;
+ if (likes != null)
+ {
+ IEnumerator e = likes.GetEnumerator();
+ while (e.MoveNext())
+ LikeMe(context, e.Current as string);
+ }
+
+ // Extend any "thru_date" to midnight
+ ExtendThruDate(context);
+
+ // Ensure that list_item and list_offset are numeric
+ object limit = context[App.ITEM_LIMIT];
+ if (limit != null)
+ {
+ context[App.ITEM_LIMIT] = Convert.ToInt32(limit);
+ object offset = context[App.ITEM_OFFSET];
+ context[App.ITEM_OFFSET] = Convert.ToInt32(offset);
+ }
+ }
+
+ /// <summary>
+ /// Provide a default, convenience implementation that will run a "QueryForList"
+ /// using a data mapping statement of the same ID as the Command;
+ /// override as needed.
+ /// </summary>
+ /// <param name="context">The INexusContext we are processing.</param>
+ /// <returns>CONTINUE, if an Exception is not thrown.</returns>
+ public override bool RequestExecute(IRequestContext context)
+ {
+ PreProcess(context);
+
+ IList rows = Mapper.QueryForList(QueryID, context);
+ context[ID] = rows;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseSave.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseSave.cs
new file mode 100644
index 0000000..081fdac
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/BaseSave.cs
@@ -0,0 +1,92 @@
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Store an entity for future reference.
+ /// </summary>
+ ///
+ public class BaseSave : BaseMapper
+ {
+ /// <summary>
+ /// Provide a field for KeyID property.
+ /// </summary>
+ ///
+ private string _KeyID = null;
+
+ /// <summary>
+ /// Record the unique identifier for the entity.
+ /// </summary>
+ ///
+ public string KeyID
+ {
+ get { return _KeyID; }
+ set { _KeyID = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for InsertID property.
+ /// </summary>
+ private string _InsertID = null;
+
+ /// <summary>
+ /// Record the name of the "insert" mapping for the entity.
+ /// </summary>
+ ///
+ public string InsertID
+ {
+ get { return _InsertID; }
+ set { _InsertID = value; }
+ }
+
+ /// <summary>
+ /// Provide a field for UpdateID property.
+ /// </summary>
+ ///
+ private string _UpdateID = null;
+
+ /// <summary>
+ /// Record the name of the "update" mapping for the entity.
+ /// </summary>
+ ///
+ public string UpdateID
+ {
+ get { return _UpdateID; }
+ set { _UpdateID = value; }
+ }
+
+ /// <summary>
+ /// Insert or update an entity to the persistent store.
+ /// </summary>
+ /// <remark><p>
+ /// If the "fieldID" is empty, use the insertID statement,
+ /// otherwise, use the updateID statement.
+ /// </p></remark>
+ /// <param name="context">The INexusContext we are processing.</param>
+ /// <param name="fieldID">The name of the key field.</param>
+ /// <param name="insertID">The name of the "insert" mapping for the Entity.</param>
+ /// <param name="updateID">The name of the "update" mapping for the Entity.</param>
+ /// <returns>False</returns>
+ ///
+ protected bool Save(IRequestContext context, string fieldID, string insertID, string updateID)
+ {
+ bool insert = IsEmpty(context[fieldID] as string);
+
+ if (insert)
+ {
+ context[fieldID] = GuidString();
+ Mapper.Insert(insertID, context);
+ }
+ else
+ Mapper.Update(updateID, context);
+
+ return CONTINUE;
+ }
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ return Save(context, KeyID, InsertID, UpdateID);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/EntryInitial.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/EntryInitial.cs
new file mode 100644
index 0000000..a3083b0
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Commands/EntryInitial.cs
@@ -0,0 +1,46 @@
+using System.Collections;
+using Nexus.Core;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Create list of initial letters for Facility Names.
+ /// </summary>
+ public class EntryInitial : BaseMapper
+ {
+ /// <summary>
+ /// Document token representing match all entries.
+ /// </summary>
+ public const string ALL = "[*]";
+
+ /// <summary>
+ /// Document the wildcard character used by SQL queries.
+ /// </summary>
+ public const string WILDCARD = "%";
+
+ public override bool RequestExecute(IRequestContext context)
+ {
+ const string ZERO = "0";
+
+ string[] input = {
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y", "Z"
+ };
+
+ IList output = new ArrayList(26);
+
+ foreach (string letter in input)
+ {
+ string initial = letter + WILDCARD;
+ object result = Mapper.QueryForObject(QueryID, initial);
+ if (ZERO.Equals(result)) continue;
+ output.Add(letter);
+ }
+
+ output.Add(ALL);
+ context.Outcome = output;
+ return CONTINUE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.csproj b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.csproj
new file mode 100644
index 0000000..aaf483b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.csproj
@@ -0,0 +1,97 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F65FCC91-C9CB-40CE-87A6-C0CB00F73592}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>PhoneBook.Core</RootNamespace>
+ <AssemblyName>PhoneBook.Core</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Agility.Core, Version=1.0.2355.25640, Culture=neutral">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\Agility\Agility.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="IBatisNet.DataMapper, Version=1.5.1.0, Culture=neutral, PublicKeyToken=ed781d9fc396c6ca, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\iBatisNet\IBatisNet.DataMapper.dll</HintPath>
+ </Reference>
+ <Reference Include="Nexus.Core, Version=1.0.2539.22197, Culture=neutral">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\Nexus\Nexus.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="Spring.Core, Version=1.1.0.2, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\SpringNet\Spring.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="App.cs" />
+ <Compile Include="AppEntry.cs" />
+ <Compile Include="AppEntryList.cs" />
+ <Compile Include="AppEntryListProcessor.cs" />
+ <Compile Include="Commands\AppCommand.cs" />
+ <Compile Include="Commands\BaseCommand.cs" />
+ <Compile Include="Commands\BaseCount.cs" />
+ <Compile Include="Commands\BaseDelete.cs" />
+ <Compile Include="Commands\BaseEntry.cs" />
+ <Compile Include="Commands\BaseFilterList.cs" />
+ <Compile Include="Commands\BaseList.cs" />
+ <Compile Include="Commands\BaseSave.cs" />
+ <Compile Include="Commands\EntryInitial.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TelephoneProcessor.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Messages.resx">
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.csproj.user b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.csproj.user
new file mode 100644
index 0000000..b875c0c
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.csproj.user
@@ -0,0 +1,5 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <ProjectView>ProjectFiles</ProjectView>
+ </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.resharper.user b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.resharper.user
new file mode 100644
index 0000000..b4f0bf4
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.resharper.user
@@ -0,0 +1,27 @@
+<Configuration>
+ <CompletionStatisticsManager />
+ <EditorManager>
+ <RecentFiles>
+ <File id="F65FCC91-C9CB-40CE-87A6-C0CB00F73592/f:Class1.cs" caret="133" visual-x="0" visual-y="0" />
+ </RecentFiles>
+ </EditorManager>
+ <FileStructureView>
+ <AutoScrollToSource>False</AutoScrollToSource>
+ <TrackCaretLocation>False</TrackCaretLocation>
+ </FileStructureView>
+ <NAntValidationSettings>
+ <NAntPath value="" />
+ </NAntValidationSettings>
+ <ReFormatCode>
+ <OptimizeUsings>False</OptimizeUsings>
+ <RemoveRedundantThis>False</RemoveRedundantThis>
+ <ShortenReferences>False</ShortenReferences>
+ <DecorateModifiers>False</DecorateModifiers>
+ </ReFormatCode>
+ <SharedSolutionDisabledTemplatesManager>
+ <DisabledTemplates />
+ </SharedSolutionDisabledTemplatesManager>
+ <UserSolutionDisabledTemplatesManager>
+ <DisabledTemplates />
+ </UserSolutionDisabledTemplatesManager>
+</Configuration>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.sln b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.sln
new file mode 100644
index 0000000..dae23c8
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core.csproj", "{F65FCC91-C9CB-40CE-87A6-C0CB00F73592}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F65FCC91-C9CB-40CE-87A6-C0CB00F73592}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.suo b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.suo
new file mode 100644
index 0000000..07a9c1a
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Core.suo
Binary files differ
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Messages.resx b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Messages.resx
new file mode 100644
index 0000000..9e2b2bd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Messages.resx
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="ResMimeType">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="Version">
+ <value>1.0.0.0</value>
+ </resheader>
+ <resheader name="Reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="Writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+
+ <data name="page_index_hint">
+ <value>Viewing {0}-{1} of {2}.</value>
+ </data>
+
+ <!-- command labels -->
+
+ <data name="find">
+ <value>LIST ALL</value>
+ </data>
+
+ <data name="add">
+ <value>ADD</value>
+ </data>
+
+ <!-- field alerts -->
+
+ <data name="_alert">
+ <value>{0} is invalid.</value>
+ </data>
+
+ <data name="_required">
+ <value>{0} is required.</value>
+ </data>
+
+ <data name="DateTimeProcessor_alert">
+ <value>{0} must be a valid date.</value>
+ </data>
+
+ <data name="TelephoneProcessor_alert">
+ <value>{0} must be a telephone extension.</value>
+ </data>
+
+
+ <!-- field labels -->
+
+ <data name="last_name_label">
+ <value>Last Name</value>
+ </data>
+
+ <data name="first_name_label">
+ <value>First Name</value>
+ </data>
+
+ <data name="extension_label">
+ <value>Extension</value>
+ </data>
+
+ <data name="user_name_label">
+ <value>User Name</value>
+ </data>
+
+ <data name="hired_label">
+ <value>Hired</value>
+ </data>
+
+ <data name="hours_label">
+ <value>Hours</value>
+ </data>
+
+ <data name="editor_label">
+ <value>Editor?</value>
+ </data>
+
+
+ <!-- prompts -->
+
+ <data name="greeting">
+ <value>Welcome, </value>
+ </data>
+
+ <data name="directory_title">
+ <value>Directory (2)</value>
+ </data>
+
+ <data name="directory_heading">
+ <value>Directory</value>
+ </data>
+
+ <data name="directory_prompt">
+ <value>Select a filter to display fewer entries</value>
+ </data>
+
+ <data name="not_found_hint">
+ <value>No matching entries found.</value>
+ </data>
+
+</root>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/Properties/AssemblyInfo.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d4d2e3f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Core")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Core")]
+[assembly: AssemblyCopyright("Copyright © 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e5f56cab-000a-42bd-9f13-9f50039e3f80")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Core/TelephoneProcessor.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Core/TelephoneProcessor.cs
new file mode 100644
index 0000000..f45c883
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Core/TelephoneProcessor.cs
@@ -0,0 +1,65 @@
+using System.Text;
+using Nexus.Core.Validators;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Remove punctuation on input and insert punctuation on output.
+ /// </summary>
+ /// <remarks><p>
+ /// Null input or output is passed thorugh as null.
+ /// Non-null input or output must be strings.
+ /// Output is formatted for local or long distane US telephone numbers.
+ /// Output strings that are too short or too long are passed through.
+ /// </p></remarks>
+ public class TelephoneProcessor : Processor
+ {
+ public override bool ConvertInput(IProcessorContext incoming)
+ {
+ object source = incoming.Source;
+ if (source == null) return true;
+
+ string input = source as string;
+ if (input == null) return false;
+
+ char[] marks = {'-'};
+ string[] splits = input.Split(marks);
+ StringBuilder sb = new StringBuilder(input.Length);
+ foreach (string s in splits)
+ {
+ sb.Append(s);
+ }
+ incoming.Target = sb.ToString();
+ return true;
+ }
+
+ public override bool FormatOutput(IProcessorContext outgoing)
+ {
+ object source = outgoing.Source;
+ if (source == null) return true;
+
+ string output = source as string;
+ if (output == null) return false;
+
+ string mark = "-";
+ if (output == null) return false;
+ string buffer;
+
+ if (output.Length == 10)
+ {
+ // 012-345-6789
+ string buffer1 = output.Insert(6, mark);
+ buffer = buffer1.Insert(3, mark);
+ }
+ else if (output.Length == 7)
+ {
+ // 012-3456
+ buffer = output.Insert(3, mark);
+ }
+ else buffer = output;
+
+ outgoing.Target = buffer;
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/BaseTest.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/BaseTest.cs
new file mode 100644
index 0000000..1fdeddd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/BaseTest.cs
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+using NUnit.Framework;
+
+namespace PhoneBook.Core
+{
+ /// <summary>
+ /// Provide base class so unit tests can share utility.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class BaseTest : CatalogBaseTest
+ {
+ /// <summary>
+ /// Confirm that the outcome is a non-null, non-empty list.
+ /// </summary>
+ /// <param name="context">Context to confirm</param>
+ /// <returns>The non-null, non-empty list</returns>
+ ///
+ protected IList AssertListOutcome(IRequestContext context)
+ {
+ AssertNominal(context);
+ Assert.IsTrue(context.HasOutcome, "Expected command to set an Outcome.");
+ IList list = context.Outcome as IList;
+ bool notEmpty = ((list != null) && (list.Count > 0));
+ Assert.IsTrue(notEmpty, "Expected outcome to be a not-empty list");
+ return list;
+ }
+
+ /// <summary>
+ /// Exercise the testing infrastructure.
+ /// </summary>
+ ///
+ [Test]
+ public void Pass()
+ {
+ }
+
+ /// <summary>
+ /// Exercise GUID creation,
+ /// and provide a device for generating GUIDs if needed.
+ /// </summary>
+ ///
+ [Test]
+ public void GuidString()
+ {
+ IDictionary test = new Hashtable();
+ for (int i = 0; i < 10; i++)
+ {
+ string key = Guid.NewGuid().ToString();
+ Assert.IsNotNull(key);
+ Assert.IsTrue(36 == key.Length);
+ test.Add(key, key); // Add throws an exception on duplicate keys
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Class1.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Class1.cs
new file mode 100644
index 0000000..f45ccd5
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Class1.cs
@@ -0,0 +1,24 @@
+using PhoneBook2.Core;
+using NUnit.Framework;
+
+namespace PhoneBook2.Core
+{
+ [TestFixture]
+ public class Class1Fixture
+ {
+
+ Class1 class1;
+
+ [SetUp]
+ public void SetUp()
+ {
+ class1 = new Class1();
+ }
+
+ [Test]
+ public void Class1Test ()
+ {
+ Assert.IsNotNull(class1,"SetUp failed!");
+ }
+ }
+}
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/DirectoryViewTest.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/DirectoryViewTest.cs
new file mode 100644
index 0000000..d1d29f3
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/DirectoryViewTest.cs
@@ -0,0 +1,43 @@
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Exercise Directory View Command.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class EntryFindTest : BaseTest
+ {
+ /// <summary>
+ /// Confirm that Context contains the expected attributes for the list filter-0ps.
+ /// </summary>
+ ///
+ [Test]
+ public void ContainsFilters()
+ {
+ IRequestContext context = catalog.ExecuteRequest(App.ENTRY_FIND);
+ AssertNominal(context);
+ string[] FILTERS = {App.LAST_NAME_LIST, App.FIRST_NAME_LIST, App.EXTENSION_LIST, App.USER_NAME_LIST, App.HIRED_LIST, App.HOURS_LIST};
+ foreach (string filter in FILTERS)
+ {
+ Assert.IsTrue(context.Contains(filter), filter + ": Expected context to contain key.");
+ }
+ }
+
+ /// <summary>
+ /// Confirm that Helper contains the expected command.
+ /// </summary>
+ ///
+ [Test]
+ public void HelperContains()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_FIND);
+ IRequestCommand command = helper.Command;
+ Assert.IsNotNull(command, "Expected Helper to have a Command");
+ Assert.AreEqual(App.ENTRY_FIND, command.ID, "Expected Helper to have View Command.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/EditFixture.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/EditFixture.cs
new file mode 100644
index 0000000..835181a
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/EditFixture.cs
@@ -0,0 +1,43 @@
+using System.Collections;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Exercise editing commands.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class EditFixture : BaseTest
+ {
+
+ public const string ENTRY_KEY_VALUE = "12345678-1234-123456789-1234567890AB";
+ public const string FIRST_NAME_VALUE = App.FIRST_NAME;
+ public const string LAST_NAME_VALUE = App.LAST_NAME;
+ public const string USER_NAME_VALUE = App.USER_NAME;
+ public const string EXTENSION_VALUE = "1234567890";
+ public const string HIRED_VALUE = "2002-07-31";
+ public const string HOURS_VALUE = "20";
+ public const string EDITOR_VALUE = "1";
+
+ protected override void Populate(IDictionary context)
+ {
+ context[App.ENTRY_KEY] = ENTRY_KEY_VALUE;
+ context[App.FIRST_NAME] = FIRST_NAME_VALUE;
+ context[App.LAST_NAME] = LAST_NAME_VALUE;
+ context[App.USER_NAME] = USER_NAME_VALUE;
+ context[App.EXTENSION] = EXTENSION_VALUE;
+ context[App.HIRED] = HIRED_VALUE;
+ context[App.HOURS] = HOURS_VALUE;
+ context[App.EDITOR] = EDITOR_VALUE;
+ }
+
+
+ [Test]
+ public void InsertDelete()
+ {
+ AssertInsertDelete(App.ENTRY_SAVE, App.ENTRY_KEY, ENTRY_KEY_VALUE, App.ENTRY_DELETE);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/FilterLists.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/FilterLists.cs
new file mode 100644
index 0000000..a7161c5
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/FilterLists.cs
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Exercise the various lists of distinct values
+ /// that are used to filter the directory.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class FilterListsTest : BaseTest
+ {
+ /// <summary>
+ /// Confirm that a list is returned as the outcome,
+ /// and that each item on the list is not-empty and unique.
+ /// </summary>
+ /// <param name="context">Context returned by command</param>
+ ///
+ private void FilterList_Result(IRequestContext context)
+ {
+ IList list = AssertListOutcome(context);
+ foreach (IKeyValue item in list)
+ {
+ Assert.IsNotNull(item, "Expected each item to be non-null");
+ object key = item.Value;
+ Assert.IsNotNull(key, "Expected each key to be non-null");
+ string keystring = key.ToString();
+ Assert.IsTrue(keystring.Length > 0, "Expected each key to be non-empty");
+ }
+ IDictionary keys = new Hashtable(list.Count);
+ foreach (IKeyValue item in list)
+ {
+ string key = item.Value.ToString();
+ if (keys.Contains(key)) Assert.Fail(key + ": Expected each item to be unique");
+ keys.Add(key, key);
+ }
+ }
+
+ /// <summary>
+ /// Exercise the filter commands.
+ /// </summary>
+ ///
+ [Test]
+ public void TestFilterLists()
+ {
+ string[] FILTERS = {App.LAST_NAME_LIST, App.FIRST_NAME_LIST, App.EXTENSION_LIST, App.USER_NAME_LIST, App.HIRED_LIST, App.HOURS_LIST};
+ foreach (string filter in FILTERS)
+ {
+ IRequestContext context = catalog.ExecuteRequest(filter);
+ FilterList_Result(context);
+ }
+ }
+
+ /// <summary>
+ /// Excercise entry file and validate key value list.
+ /// </summary>
+ /// <param name="key">ID for list</param>
+ /// <returns>The validated list</returns>
+ ///
+ private IKeyValueList FilterList(string key)
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_FIND);
+ helper.Execute();
+ IKeyValueList list = helper.Criteria[key] as IKeyValueList;
+ Assert.IsNotNull(list, "Expected KeyValueList");
+ return list;
+ }
+
+ /// <summary>
+ /// Exercise Extension List filter.
+ /// </summary>
+ ///
+ [Test]
+ public void TestFilterFormat_extension()
+ {
+ IKeyValueList list = FilterList(App.EXTENSION_LIST);
+ foreach (IKeyValue item in list)
+ {
+ string key = item.Value as string;
+ Assert.IsTrue(key.Length > "1234567890".Length, "Expected formatted extension, not: " + key);
+ }
+ }
+
+ /// <summary>
+ /// Exercise Hired filter.
+ /// </summary>
+ ///
+ [Test]
+ public void TestFilterFormat_hired()
+ {
+ IKeyValueList list = FilterList(App.HIRED_LIST);
+ foreach (IKeyValue item in list)
+ {
+ string key = item.Value as string;
+ bool okay = (key.Length > 0) && (key.Length < "##/##/#### ".Length);
+ Assert.IsTrue(okay, "Expected short date format, not: " + key);
+ }
+ }
+
+ [Test]
+ public void Initial()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_LIST);
+ helper.Criteria["initial"] = "C%";
+ helper.Execute();
+ Assert.IsTrue(helper.IsNominal, helper.AlertsText);
+ IList list = helper.Outcome;
+ Assert.IsTrue(list.Count > 0, "Expected one or more entries");
+ foreach (AppEntry entry in list)
+ {
+ Assert.IsTrue("C".Equals(entry.last_name.Substring(0, 1)), "Expected all to be C*");
+ }
+ int count = Convert.ToInt32(helper.Criteria["item_count"]);
+ Assert.IsTrue(count == list.Count, "Expected counts to match");
+ }
+
+ [Test]
+ public void InitialDistinct()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_INITIAL);
+ helper.Execute();
+ Assert.IsTrue(helper.IsNominal, helper.AlertsText);
+ IList list = helper.Outcome;
+ Assert.IsTrue(list.Count > 0, "Expected one or more entries");
+ string a = list[0] as string;
+ Assert.IsNotNull(a, "Expected letter");
+ Assert.IsTrue("C".Equals(a), "Expected C");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/FormatEntry.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/FormatEntry.cs
new file mode 100644
index 0000000..e693190
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/FormatEntry.cs
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+
+ /// <summary>
+ /// Exercise formatting processors.
+ /// </summary>
+ ///
+ [TestFixture]
+ public class FormatEntry : BaseTest
+ {
+
+ public const string ENTRY_KEY_VALUE_FORMAT = "c5b6bbb1-66d6-49cb-9db6-743af6627828";
+
+ private AppEntry getAppEntry()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY);
+ helper.Criteria[App.ENTRY_KEY] = ENTRY_KEY_VALUE_FORMAT;
+ helper.Execute();
+ AssertNominal(helper);
+ AppEntry entry = new AppEntry(helper.Criteria);
+ return entry;
+ }
+
+ [Test]
+ public void Hired()
+ {
+ AppEntry entry = getAppEntry();
+ string hired = entry.hired;
+ Assert.IsNotNull(hired, "Expected row to have a hired date in string format.");
+ Assert.IsTrue(hired.Length < "##/##/#### ".Length, hired + ": Expected short date format.");
+ }
+
+ [Test]
+ public void extension()
+ {
+ AppEntry entry = getAppEntry();
+ string extension = entry.extension;
+ Assert.IsNotNull(extension, "Expected each row to have an extension.");
+ Assert.IsTrue(extension.Length > "1234567890".Length, extension + ": Expected formatted extension.");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/SelectAllTest.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/SelectAllTest.cs
new file mode 100644
index 0000000..f12f091
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Commands/SelectAllTest.cs
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+using System.Collections;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using NUnit.Framework;
+
+namespace PhoneBook.Core.Commands
+{
+ /// <summary>
+ /// Exercise SelectAll Command per [OVR-5].
+ /// </summary>
+ ///
+ [TestFixture]
+ public class SelectAllTest : BaseTest
+ {
+ /// <summary>
+ /// Assert result of SelectAll, after another method runs the command.
+ /// </summary>
+ /// <param name="context">Context with result to assert.</param>
+ ///
+ private void SelectAll_Result(IRequestContext context)
+ {
+ IList list = AssertListOutcome(context);
+ IDictionary row = list[0] as IDictionary;
+ Assert.IsNotNull(row, "Expected list entry to be an IDictionary.");
+ string[] KEYS = {App.FIRST_NAME, App.LAST_NAME, App.USER_NAME, App.EXTENSION, App.HIRED, App.HOURS, App.EDITOR};
+ bool valid = true;
+ foreach (string key in KEYS)
+ {
+ valid = valid && row.Contains(key);
+ }
+ Assert.IsTrue(valid, "Expected row to contain all keys.");
+ }
+
+
+ /// <summary>
+ /// Filter all and succeed, using catalog.
+ /// </summary>
+ ///
+ [Test]
+ public void SelectAll_Pass()
+ {
+ IRequestContext context = catalog.ExecuteRequest(App.ENTRY_LIST);
+ SelectAll_Result(context);
+ }
+
+ /// <summary>
+ /// Exercise Entry List and validate hired and extension string formatting.
+ /// </summary>
+ ///
+ [Test]
+ public void FilterHelper_Format()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_LIST);
+ helper.Execute();
+ AssertNominal(helper);
+ AppEntryList list = helper.Outcome as AppEntryList;
+ Assert.IsNotNull(list, "Expected list to be AppEntryList");
+ AppEntry row = list[0] as AppEntry;
+ Assert.IsNotNull(row, "Expected rows to be AppEntries");
+
+ string hired = row.hired;
+ Assert.IsNotNull(hired, "Expected each row to have a hired date.");
+ Assert.IsTrue(hired.Length < "##/##/#### ".Length, hired + ": Expected short date format.");
+
+ string extension = row.extension;
+ Assert.IsNotNull(extension, "Expected each row to have an extension.");
+ Assert.IsTrue(extension.Length > "1234567890".Length, extension + ": Expected formatted extension.");
+ }
+
+ /// <summary>
+ /// Exercise custom paging
+ /// (retrieve only visible section of the result se).
+ /// </summary>
+ ///
+ [Test]
+ public void SelectAll_Limit()
+ {
+ IViewHelper helper = catalog.GetHelperFor(App.ENTRY_LIST);
+ helper.Criteria[App.ITEM_LIMIT] = 2;
+ helper.Criteria[App.ITEM_OFFSET] = 0;
+ helper.Execute();
+ if (!helper.IsNominal) Assert.Fail(helper.AlertsText);
+ IList list = helper.Outcome;
+ Assert.IsTrue(list.Count == 2, "Expected result set to be limited to two entries.");
+ AppEntry entry = list[0] as AppEntry;
+ helper.Criteria[App.ITEM_LIMIT] = 2;
+ helper.Criteria[App.ITEM_OFFSET] = 3;
+ helper.Execute();
+ IList list2 = helper.Outcome;
+ AppEntry entry2 = list2[0] as AppEntry;
+ Assert.IsFalse(entry.entry_key.Equals(entry2.entry_key), "Expected result sets to be different");
+ int count = Convert.ToInt32(helper.Criteria[App.ITEM_COUNT]);
+ Assert.IsTrue(count > 2, "Expected the overall count to be higher");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Objects.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Objects.xml
new file mode 100644
index 0000000..ffd7d9b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Objects.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <import resource="Resources/AppBase.xml"/>
+ <import resource="Resources/AppConfig.xml"/>
+ <import resource="Resources/AppFields.xml"/>
+ <import resource="Resources/Catalog.xml"/>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Properties/AssemblyInfo.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2bf28b7
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Test")]
+[assembly: AssemblyCopyright("Copyright © 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("91b59cae-8eba-40d7-b2ae-fc945d16242a")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppBase.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppBase.xml
new file mode 100644
index 0000000..9280689
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppBase.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Base element (super parent)-->
+
+ <object id="BaseMapper" abstract="true">
+ <property name="Mapper"><ref object="Mapper"/></property>
+ </object>
+
+ <!-- Base class parents -->
+
+ <object id="BaseChain" type="Nexus.Core.RequestChain, Nexus.Core"/>
+
+ <object id="BaseCount" type="PhoneBook.Core.Commands.BaseCount, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseDelete" type="PhoneBook.Core.Commands.BaseDelete, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseEntry" type="PhoneBook.Core.Commands.BaseEntry, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFilterList" type="PhoneBook.Core.Commands.BaseFilterList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFieldContext" type="Nexus.Extras.Spring.FieldContext">
+ <property name="MessageSource">
+ <ref object="messageSource" />
+ </property>
+ </object>
+
+ <object id="BaseKeyValueProcessor" type="Nexus.Core.Validators.KeyValueProcessor"/>
+
+ <object id="BaseList" type="PhoneBook.Core.Commands.BaseList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseSave" type="PhoneBook.Core.Commands.BaseSave, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="EntryInitial" type="PhoneBook.Core.Commands.EntryInitial, PhoneBook.Core" parent="BaseMapper"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppConfig.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppConfig.xml
new file mode 100644
index 0000000..f3bbcbd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppConfig.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Message Source -->
+
+ <object id="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
+ <property name="ResourceManagers">
+ <list>
+ <value>PhoneBook.Core.Messages, PhoneBook.Core</value>
+ <value>Nexus.Web.Messages, Nexus.Web</value>
+ </list>
+ </property>
+ </object>
+
+
+ <!-- Request Processors -->
+
+ <object id="convert_input" type="Nexus.Core.Validators.ConvertInput">
+ <property name="ID"><value>convert_input</value></property>
+ </object>
+
+ <object id="format_output" type="Nexus.Core.Validators.FormatOutput">
+ <property name="ID"><value>format_output</value></property>
+ </object>
+
+ <object id="clear_context" type="Nexus.Core.Validators.ClearContext">
+ <property name="ID"><value>clear_context</value></property>
+ </object>
+
+ <!-- pre-op -->
+
+ <object id="pre-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="convert_input"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- post-op -->
+
+ <object id="post-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="format_output"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- Catalog -->
+
+ <object id="Catalog" type="Nexus.Extras.Spring.Catalog">
+ <property name="FieldTable"><ref object="FieldTable"/></property>
+ <property name="PreOp"><ref object="pre-op"/></property>
+ <property name="PostOp"><ref object="post-op"/></property>
+ <property name="ViewHelper"><object type="Nexus.Web.WebHelper, Nexus.Web" singleton="false"/></property>
+ </object>
+
+<!-- iBATIS Mapper -->
+
+ <object id="Mapper" type="IBatisNet.DataMapper.Mapper, IBatisNet.DataMapper"
+ factory-method="Instance"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppFields.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppFields.xml
new file mode 100644
index 0000000..303fc2b
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/AppFields.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- FieldTable -->
+
+ <object id="FieldTable" type="Nexus.Core.Tables.FieldTable">
+ <property name="AddFieldContexts">
+ <list>
+ <ref object="last_name"/>
+ <ref object="first_name"/>
+ <ref object="extension"/>
+ <ref object="user_name"/>
+ <ref object="hired"/>
+ <ref object="hours"/>
+ <ref object="_entry_list"/>
+ <ref object="_entry_list_count"/>
+ <ref object="_extension_list"/>
+ <ref object="_hired_list"/>
+ </list>
+ </property>
+ <property name="AddProcessors">
+ <list>
+ <ref object="DateTimeProcessor"/>
+ <ref object="TelephoneProcessor"/>
+ <ref object="EntryListProcessor"/>
+ <ref object="ExtensionListProcessor"/>
+ <ref object="HiredListProcessor"/>
+ </list>
+ </property>
+ </object>
+
+ <object id="last_name" parent="BaseFieldContext">
+ <property name="ID"><value>last_name</value></property>
+ </object>
+
+ <object id="first_name" parent="BaseFieldContext">
+ <property name="ID"><value>first_name</value></property>
+ </object>
+
+ <object id="user_name" parent="BaseFieldContext">
+ <property name="ID"><value>user_name</value></property>
+ </object>
+
+ <object id="extension" parent="BaseFieldContext">
+ <property name="ID"><value>extension</value></property>
+ <property name="Processor"><ref object="TelephoneProcessor"/></property>
+ </object>
+
+ <object id="hired" parent="BaseFieldContext">
+ <property name="ID"><value>hired</value></property>
+ <property name="Processor"><ref object="DateTimeProcessor"/></property>
+ </object>
+
+ <object id="hours" parent="BaseFieldContext">
+ <property name="ID"><value>hours</value></property>
+ </object>
+
+ <object id="editor" parent="BaseFieldContext">
+ <property name="ID"><value>editor</value></property>
+ </object>
+
+ <!-- property name="ControlTypeName"><value>CheckBox</value></property -->
+
+ <!-- We need to "hash" the name with "_" to avoid conflict with the filter Command -->
+ <object id="_entry_list" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="Processor"><ref object="EntryListProcessor"/></property>
+ </object>
+
+ <object id="_entry_list_count" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="Processor"><ref object="CollectionProcessor"/></property>
+ </object>
+
+ <object id="_extension_list" parent="BaseFieldContext">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="Processor"><ref object="ExtensionListProcessor"/></property>
+ </object>
+
+ <object id="_hired_list" parent="BaseFieldContext">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="Processor"><ref object="HiredListProcessor"/></property>
+ </object>
+
+ <object id="CollectionProcessor" type="Nexus.Core.Validators.CollectionProcessor, Nexus.Core">
+ <property name="ID"><value>EntryCountProcessor</value></property>
+ </object>
+
+ <!-- "d" is .NET for "short date" -->
+ <object id="DateTimeProcessor" type="Nexus.Core.Validators.DateTimeProcessor">
+ <property name="ID"><value>DateTimeProcessor</value></property>
+ <property name="DataFormat"><value>d</value></property>
+ </object>
+
+ <object id="TelephoneProcessor" type="PhoneBook.Core.TelephoneProcessor">
+ <property name="ID"><value>TelephoneProcessor</value></property>
+ </object>
+
+ <object id="EntryListProcessor" type="PhoneBook.Core.AppEntryListProcessor">
+ <property name="ID"><value>EntryListProcessor</value></property>
+ </object>
+
+ <object id="ExtensionListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>ExtensionListProcessor</value></property>
+ <property name="Key"><value>extension</value></property>
+ </object>
+
+ <object id="HiredListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>HiredListProcessor</value></property>
+ <property name="Key"><value>hired</value></property>
+ </object>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/Catalog.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/Catalog.xml
new file mode 100644
index 0000000..bd89c45
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/Catalog.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- entry commands -->
+
+ <object id="entry_list_rows" parent="BaseList">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="QueryID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_list_count" parent="BaseCount">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="QueryID"><value>entry_count</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry" parent="BaseEntry">
+ <property name="ID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_delete" parent="BaseDelete">
+ <property name="ID">
+ <value>entry_delete</value>
+ </property>
+ <property name="RequiredIDs">
+ <list>
+ <value>entry_key</value>
+ </list>
+ </property>
+ </object>
+
+ <!-- filter list commands -->
+
+ <object id="last_name_list" parent="BaseFilterList">
+ <property name="ID"><value>last_name_list</value></property>
+ <property name="RelatedIDs"><list><value>last_name_list</value></list></property>
+ </object>
+
+ <object id="first_name_list" parent="BaseFilterList">
+ <property name="ID"><value>first_name_list</value></property>
+ <property name="RelatedIDs"><list><value>first_name_list</value></list></property>
+ </object>
+
+ <object id="extension_list" parent="BaseFilterList">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="RelatedIDs"><list><value>extension_list</value></list></property>
+ </object>
+
+ <object id="user_name_list" parent="BaseFilterList">
+ <property name="ID"><value>user_name_list</value></property>
+ <property name="RelatedIDs"><list><value>user_name_list</value></list></property>
+ </object>
+
+ <object id="hired_list" parent="BaseFilterList">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="RelatedIDs"><list><value>hired_list</value></list></property>
+ </object>
+
+ <object id="hours_list" parent="BaseFilterList">
+ <property name="ID"><value>hours_list</value></property>
+ <property name="RelatedIDs"><list><value>hours_list</value></list></property>
+ </object>
+
+ <object id="entry_initial" parent="EntryInitial">
+ <property name="ID">
+ <value>entry_initial</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_initial</value>
+ </list>
+ </property>
+ </object>
+
+ <!-- chains -->
+
+ <object id="entry_list" parent="BaseChain">
+ <property name="ID">
+ <value>entry_list</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="entry_list_count" />
+ <ref object="entry_list_rows" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_find" parent="BaseChain">
+ <property name="ID">
+ <value>entry_find</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="last_name_list" />
+ <ref object="first_name_list" />
+ <ref object="extension_list" />
+ <ref object="user_name_list" />
+ <ref object="hired_list" />
+ <ref object="hours_list" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_save" parent="BaseSave">
+ <property name="ID">
+ <value>entry_save</value>
+ </property>
+ <property name="KeyID">
+ <value>entry_key</value>
+ </property>
+ <property name="InsertID">
+ <value>entry_insert</value>
+ </property>
+ <property name="UpdateID">
+ <value>entry_update</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_key</value>
+ </list>
+ </property>
+ <property name="RequiredIDs">
+ <list>
+ <value>first_name</value>
+ <value>last_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hours</value>
+ <value>hired</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/Queries.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/Queries.xml
new file mode 100644
index 0000000..370639f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Resources/Queries.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<sqlMap
+ namespace="phonebook"
+ xmlns="http://ibatis.apache.org/mapping"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
+
+ <parameterMaps>
+
+ <parameterMap id="entry_save_param">
+ <parameter property="last_name"/>
+ <parameter property="first_name"/>
+ <parameter property="extension"/>
+ <parameter property="user_name"/>
+ <parameter property="hired"/>
+ <parameter property="hours"/>
+ <parameter property="editor"/>
+ <parameter property="entry_key"/>
+ </parameterMap>
+
+ </parameterMaps>
+
+ <statements>
+
+ <select id="last_name_list" resultClass="string">
+ SELECT DISTINCT
+ last_name
+ FROM entry
+ ORDER BY last_name
+ </select>
+
+ <select id="first_name_list" resultClass="string">
+ SELECT DISTINCT
+ first_name
+ FROM entry
+ ORDER BY first_name
+ </select>
+
+ <select id="extension_list" resultClass="string">
+ SELECT DISTINCT
+ extension
+ FROM entry
+ ORDER BY extension
+ </select>
+
+ <select id="user_name_list" resultClass="string">
+ SELECT DISTINCT
+ user_name
+ FROM entry
+ ORDER BY user_name
+ </select>
+
+ <select id="hired_list" resultClass="date">
+ SELECT DISTINCT
+ hired
+ FROM entry
+ ORDER BY hired
+ </select>
+
+ <select id="hours_list" resultClass="string">
+ SELECT DISTINCT
+ hours
+ FROM entry
+ ORDER BY hours
+ </select>
+
+ <select id="entry" paramClass="Hashtable" resultClass="Hashtable">
+ SELECT
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry AS entry_key
+ FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ <dynamic>
+ <isNotNull property="item_limit">
+ LIMIT #item_limit# OFFSET #item_offset#
+ </isNotNull>
+ </dynamic>;
+ </select>
+
+ <select id="entry_count" paramClass="Hashtable" resultClass="string">
+ SELECT COUNT(*) FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ </select>
+
+ <select id="entry_initial" paramClass="string" resultClass="string">
+ SELECT COUNT(*)
+ FROM entry
+ WHERE last_name LIKE #value#
+ </select>
+
+ <insert id="entry_insert" parameterMap="entry_save_param">
+ INSERT INTO entry (
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry
+ )
+ VALUES (?,?,?,?, ?,?,?,?)
+ </insert>
+
+ <update id="entry_update" parameterMap="entry_save_param">
+ UPDATE entry SET
+ last_name=?,
+ first_name=?,
+ extension=?,
+ user_name=?,
+ hired=?,
+ hours=?,
+ editor=?
+ WHERE
+ pk_entry=?
+ </update>
+
+ <delete id="entry_delete" paramClass="Hashtable">
+ DELETE FROM entry WHERE pk_entry=#entry_key#;
+ </delete>
+
+ </statements>
+</sqlMap>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.csproj b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.csproj
new file mode 100644
index 0000000..46a57b7
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.csproj
@@ -0,0 +1,112 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{C461D986-BC3C-4A48-8B6F-B4EFA47033E6}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>PhoneBook.Core</RootNamespace>
+ <AssemblyName>PhoneBook.Test</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Agility.Core, Version=1.0.2355.25640, Culture=neutral">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\Agility\Agility.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="MySql.Data, Version=1.0.7.30072, Culture=neutral, PublicKeyToken=c5687fc88969c44d">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\iBatisNet\MySql.Data.dll</HintPath>
+ </Reference>
+ <Reference Include="Nexus.Core, Version=1.0.2539.22197, Culture=neutral">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\Nexus\Nexus.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="Nexus.Test, Version=1.0.2539.22198, Culture=neutral">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\Nexus\Nexus.Test.dll</HintPath>
+ </Reference>
+ <Reference Include="Nexus.Web, Version=1.0.2539.22197, Culture=neutral">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\Nexus\Nexus.Web.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.2.9.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
+ <Reference Include="Spring.Core, Version=1.1.0.2, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\local-cache\SpringNet\Spring.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BaseTest.cs" />
+ <Compile Include="Commands\DirectoryViewTest.cs" />
+ <Compile Include="Commands\EditFixture.cs" />
+ <Compile Include="Commands\FilterLists.cs" />
+ <Compile Include="Commands\FormatEntry.cs" />
+ <Compile Include="Commands\SelectAllTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Core\Core.csproj">
+ <Project>{F65FCC91-C9CB-40CE-87A6-C0CB00F73592}</Project>
+ <Name>Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="bin\Debug\sqlmap.config.xml" />
+ <Content Include="Objects.xml" />
+ <Content Include="Resources\AppBase.xml" />
+ <Content Include="Resources\AppConfig.xml" />
+ <Content Include="Resources\AppFields.xml" />
+ <Content Include="Resources\Catalog.xml" />
+ <Content Include="Resources\Queries.xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="bin\Debug\providers.config" />
+ <None Include="bin\Debug\sqlmap.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.resharper.user b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.resharper.user
new file mode 100644
index 0000000..f9157a1
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.resharper.user
@@ -0,0 +1,27 @@
+<Configuration>
+ <CompletionStatisticsManager />
+ <EditorManager>
+ <RecentFiles>
+ <File id="C461D986-BC3C-4A48-8B6F-B4EFA47033E6/f:Class1.cs" caret="0" visual-x="0" visual-y="0" />
+ </RecentFiles>
+ </EditorManager>
+ <FileStructureView>
+ <AutoScrollToSource>False</AutoScrollToSource>
+ <TrackCaretLocation>False</TrackCaretLocation>
+ </FileStructureView>
+ <NAntValidationSettings>
+ <NAntPath value="" />
+ </NAntValidationSettings>
+ <ReFormatCode>
+ <OptimizeUsings>False</OptimizeUsings>
+ <RemoveRedundantThis>False</RemoveRedundantThis>
+ <ShortenReferences>False</ShortenReferences>
+ <DecorateModifiers>False</DecorateModifiers>
+ </ReFormatCode>
+ <SharedSolutionDisabledTemplatesManager>
+ <DisabledTemplates />
+ </SharedSolutionDisabledTemplatesManager>
+ <UserSolutionDisabledTemplatesManager>
+ <DisabledTemplates />
+ </UserSolutionDisabledTemplatesManager>
+</Configuration>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.sln b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.sln
new file mode 100644
index 0000000..efdfd6a
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/Test.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test.csproj", "{C461D986-BC3C-4A48-8B6F-B4EFA47033E6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C461D986-BC3C-4A48-8B6F-B4EFA47033E6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/providers.config b/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/providers.config
new file mode 100644
index 0000000..d229090
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/providers.config
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8"?>
+<providers
+xmlns="http://ibatis.apache.org/providers"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <clear/>
+ <provider
+ name="sqlServer1.0"
+ description="Microsoft SQL Server, provider V1.0.3300.0 in framework .NET V1.0"
+ enabled="false"
+ assemblyName="System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="sqlServer1.1"
+ description="Microsoft SQL Server, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ default="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="sqlServer2.0"
+ enabled="false"
+ description="Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass=" System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters = "false"
+ useParameterPrefixInSql = "true"
+ useParameterPrefixInParameter = "true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider name="OleDb1.1"
+ description="OleDb, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider name="OleDb2.0"
+ description="OleDb, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc1.1"
+ description="Odbc, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc2.0"
+ description="Odbc, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle9.2"
+ description="Oracle, Oracle provider V9.2.0.401"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=9.2.0.401, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle10.1"
+ description="Oracle, oracle provider V10.1.0.301"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=10.1.0.301, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracleClient1.0"
+ description="Oracle, Microsoft provider V1.0.5000.0"
+ enabled="false"
+ assemblyName="System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.OracleClient.OracleConnection"
+ commandClass="System.Data.OracleClient.OracleCommand"
+ parameterClass="System.Data.OracleClient.OracleParameter"
+ parameterDbTypeClass="System.Data.OracleClient.OracleType"
+ parameterDbTypeProperty="OracleType"
+ dataAdapterClass="System.Data.OracleClient.OracleDataAdapter"
+ commandBuilderClass="System.Data.OracleClient.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ allowMARS="false"
+ />
+ <provider
+ name="ByteFx"
+ description="MySQL, ByteFx provider V0.7.6.15073"
+ enabled="false"
+ assemblyName="ByteFX.MySqlClient, Version=0.7.6.15073, Culture=neutral, PublicKeyToken=f2fef6fed1732fc1" connectionClass="ByteFX.Data.MySqlClient.MySqlConnection"
+ commandClass="ByteFX.Data.MySqlClient.MySqlCommand"
+ parameterClass="ByteFX.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="ByteFX.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="ByteFX.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="ByteFX.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="MySql"
+ description="MySQL, MySQL provider 1.0.7.30072"
+ enabled="true"
+ assemblyName="MySql.Data, Version=1.0.7.30072, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionClass="MySql.Data.MySqlClient.MySqlConnection"
+ commandClass="MySql.Data.MySqlClient.MySqlCommand"
+ parameterClass="MySql.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="MySql.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="MySql.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="MySql.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="?"
+ allowMARS="false"
+ />
+ <provider name="SQLite3"
+ description="SQLite, SQLite.NET provider V0.21.1869.3794"
+ enabled="false"
+ assemblyName="SQLite.NET, Version=0.21.1869.3794, Culture=neutral, PublicKeyToken=c273bd375e695f9c"
+ connectionClass="Finisar.SQLite.SQLiteConnection"
+ commandClass="Finisar.SQLite.SQLiteCommand"
+ parameterClass="Finisar.SQLite.SQLiteParameter"
+ parameterDbTypeClass="System.Data.DbType, System.Data"
+ parameterDbTypeProperty="DbType"
+ dataAdapterClass="Finisar.SQLite.SQLiteDataAdapter"
+ commandBuilderClass="Finisar.SQLite.SQLiteCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ setDbParameterPrecision="false"
+ setDbParameterScale="false"
+ allowMARS="false"
+ />
+ <provider
+ name="Firebird1.7"
+ description="Firebird, Firebird SQL .NET provider V1.7.0.33200"
+ enabled="false"
+ assemblyName="FirebirdSql.Data.Firebird, Version=1.7.0.33200, Culture=neutral, PublicKeyToken=fa843d180294369d" connectionClass="FirebirdSql.Data.Firebird.FbConnection"
+ commandClass="FirebirdSql.Data.Firebird.FbCommand"
+ parameterClass="FirebirdSql.Data.Firebird.FbParameter"
+ parameterDbTypeClass="FirebirdSql.Data.Firebird.FbDbType"
+ parameterDbTypeProperty="FbDbType"
+ dataAdapterClass="FirebirdSql.Data.Firebird.FbDataAdapter"
+ commandBuilderClass="FirebirdSql.Data.Firebird.FbCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="PostgreSql0.99.1.0"
+ description="PostgreSql, Npgsql provider V0.99.1.0"
+ enabled="false"
+ assemblyName="Npgsql, Version=0.99.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"
+ connectionClass="Npgsql.NpgsqlConnection"
+ commandClass="Npgsql.NpgsqlCommand"
+ parameterClass="Npgsql.NpgsqlParameter"
+ parameterDbTypeClass="NpgsqlTypes.NpgsqlDbType"
+ parameterDbTypeProperty="NpgsqlDbType"
+ dataAdapterClass="Npgsql.NpgsqlDataAdapter"
+ commandBuilderClass="Npgsql.NpgsqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ allowMARS="true"
+ />
+ <provider
+ name="iDb2.10"
+ description="IBM DB2 Provider, V 10.0"
+ enabled="false"
+ assemblyName="IBM.Data.DB2.iSeries, Version=10.0.0.0,Culture=neutral, PublicKeyToken=9cdb2ebfb1f93a26, Custom=null" connectionClass="IBM.Data.DB2.iSeries.iDB2Connection"
+ commandClass="IBM.Data.DB2.iSeries.iDB2Command"
+ parameterClass="IBM.Data.DB2.iSeries.iDB2Parameter"
+ parameterDbTypeClass="IBM.Data.DB2.iSeries.iDB2DbType"
+ parameterDbTypeProperty="iDB2DbType"
+ dataAdapterClass="IBM.Data.DB2.iSeries.iDB2DataAdapter"
+ commandBuilderClass="IBM.Data.DB2.iSeries.iDB2CommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Informix"
+ description="Informix NET Provider, 2.81.0.0"
+ enabled="false"
+ assemblyName="IBM.Data.Informix, Version=2.81.0.0, Culture=neutral, PublicKeyToken=7c307b91aa13d208"
+ connectionClass="IBM.Data.Informix.IfxConnection"
+ commandClass="IBM.Data.Informix.IfxCommand"
+ parameterClass="IBM.Data.Informix.IfxParameter"
+ parameterDbTypeClass="IBM.Data.Informix.IfxType"
+ parameterDbTypeProperty="IfxType"
+ dataAdapterClass="IBM.Data.Informix.IfxDataAdapter"
+ commandBuilderClass="IBM.Data.Informix.IfxCommandBuilder"
+ usePositionalParameters = "true"
+ useParameterPrefixInSql = "false"
+ useParameterPrefixInParameter = "false"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+</providers>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/sqlmap.config b/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/sqlmap.config
new file mode 100644
index 0000000..6c73ffd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/sqlmap.config
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" >
+
+ <properties resource="sqlmap.config.xml"/>
+
+ <settings>
+ <setting useStatementNamespaces="false"/>
+ <setting cacheModelsEnabled="true"/>
+ </settings>
+
+ <database>
+ <provider name="${provider}"/>
+ <dataSource name="default" connectionString="${development}"/>
+ </database>
+
+ <sqlMaps>
+ <sqlMap resource="${root}/Resources/Queries.xml"/>
+ </sqlMaps>
+
+</sqlMapConfig>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/sqlmap.config.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/sqlmap.config.xml
new file mode 100644
index 0000000..069ab40
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Test/bin/Debug/sqlmap.config.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<settings>
+ <add key="root" value="../../" />
+ <add key="provider" value="MySql" />
+ <add key="development" value="Host=clifford;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+ <add key="production" value="Host=zippy;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+</settings>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Default.aspx b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Default.aspx
new file mode 100644
index 0000000..3c374ac
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Default.aspx
@@ -0,0 +1,37 @@
+<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head runat="server">
+ <title>PhoneBook and Friends</title>
+</head>
+<body>
+ <form id="form1" runat="server">
+ <div>
+ <ul>
+ <li>
+ <a href="HelloWorld.html">HelloWorld.html</a> - Simple Jayrock example
+ </li>
+ <li>
+ <a href="DemoService.html">DemoService.html</a> - Simple example of integrating Dojo and Jayrock
+ </li>
+ <li>
+ <a href="PhoneBook.html">PhoneBook.html</a> - First blush example of calling Nexus commands from JSON-RPC service
+ </li>
+ </ul>
+ <ul>
+ <li>
+ <a href="HelloWorld.ashx">HelloWorld.ashx</a> - Simple example of a Jayrock JSON-RPC service.
+ </li>
+ <li>
+ <a href="DemoService.ashx">DemoService.ashx</a> - Examples of various output types.
+ </li>
+ <li>
+ <a href="PhoneBook.ashx">PhoneBook.ashx</a> - PhoneBook API - WORK IN PROGRESS.
+ </li>
+ </ul>
+ </div>
+ </form>
+</body>
+</html>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Default.aspx.cs b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Default.aspx.cs
new file mode 100644
index 0000000..e482262
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Default.aspx.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Data;
+using System.Configuration;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.WebParts;
+using System.Web.UI.HtmlControls;
+
+public partial class _Default : System.Web.UI.Page
+{
+ protected void Page_Load(object sender, EventArgs e)
+ {
+
+ }
+}
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/DemoService.ashx b/struts-sandbox/overdrive/PhoneBook2/projects/Web/DemoService.ashx
new file mode 100644
index 0000000..7bfdd10
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/DemoService.ashx
@@ -0,0 +1,310 @@
+<%@ WebHandler Class="JayrockWeb.DemoService" Language="C#" %>
+
+namespace JayrockWeb
+{
+ using System;
+ using System.Configuration;
+ using System.Data;
+ using System.Data.SqlClient;
+ using System.Collections;
+ using System.Collections.Specialized;
+ using System.Web;
+ using System.Web.SessionState;
+ using System.Web.UI;
+ using System.Web.UI.WebControls;
+ using Jayrock.JsonRpc;
+ using Jayrock.JsonRpc.Web;
+
+ [ JsonRpcHelp("This is a JSON-RPC service that demonstrates the basic features of the Jayrock library.") ]
+ public class DemoService : JsonRpcHandler, IRequiresSessionState
+ {
+ [ JsonRpcMethod("echo", Idempotent = true)]
+ [ JsonRpcHelp("Echoes back the text sent as input.") ]
+ public string Echo(string text)
+ {
+ return text;
+ }
+
+ [ JsonRpcMethod("echoObject", Idempotent = true)]
+ [ JsonRpcHelp("Echoes back the object sent as input.") ]
+ public object EchoOject(object o)
+ {
+ return o;
+ }
+
+ [ JsonRpcMethod("echoArgs", Idempotent = true)]
+ [ JsonRpcHelp("Echoes back the arguments sent as input. This method demonstrates variable number of arguments.") ]
+ public object EchoArgs(params object[] args)
+ {
+ return args;
+ }
+
+ [ JsonRpcMethod("echoAsStrings", Idempotent = true)]
+ [ JsonRpcHelp("Echoes back the arguments as an array of strings. This method demonstrates working with variable number of arguments.") ]
+ public object EchoAsStrings(params object[] args)
+ {
+ string[] strings = new string[args.Length];
+
+ for (int i = 0; i < args.Length; i++)
+ {
+ if (args[i] != null)
+ strings[i] = args[i].ToString();
+ }
+
+ return strings;
+ }
+
+ [ JsonRpcMethod("echoGuid", Idempotent = true)]
+ [ JsonRpcHelp("Echoes back the given GUID. This method demonstrates working with an argument typed as System.Guid.") ]
+ public Guid EchoGuid(Guid id)
+ {
+ return id;
+ }
+
+ [ JsonRpcMethod("sum", Idempotent = true)]
+ [ JsonRpcHelp("Return the sum of two integers.") ]
+ [ JsonRpcObsolete("Use the total method instead.") ]
+ public int Sum(int a, int b)
+ {
+ return a + b;
+ }
+
+ [ JsonRpcMethod("getStringArray", Idempotent = true)]
+ [ JsonRpcHelp("Returns an array of city names. Demonstrates returning a strongly-typed array.") ]
+ public string[] GetCities()
+ {
+ return new string[] { "London", "Zurich", "Paris", "New York" };
+ }
+
+ [ JsonRpcMethod("now", Idempotent = true)]
+ [ JsonRpcHelp("Returns the local time on the server. Demonstrates how DateTime is returned simply as a string using the ISO 8601 format.") ]
+ public DateTime Now()
+ {
+ return DateTime.Now;
+ }
+
+ [ JsonRpcMethod("newGuid", Idempotent = true)]
+ [ JsonRpcHelp("Generates and returns a GUID as a string.") ]
+ public Guid NewGuid()
+ {
+ return Guid.NewGuid();
+ }
+
+ [ JsonRpcMethod("cookies", Idempotent = true)]
+ [ JsonRpcHelp("Returns the cookie names seen by the server.") ]
+ public HttpCookieCollection Cookies()
+ {
+ return Request.Cookies;
+ }
+
+ [ JsonRpcMethod("serverVariables", Idempotent = true)]
+ [ JsonRpcHelp("Returns the server variables collection at the server. Demonstrates returning NameValueCollection.") ]
+ public NameValueCollection ServerVariables()
+ {
+ return Request.ServerVariables;
+ }
+
+ [ JsonRpcMethod("getAuthor", Idempotent = true)]
+ [ JsonRpcHelp("Returns information about the author. Demonstrates how a Hashtable from the server is automatically converted into an object on the client-side.") ]
+ public IDictionary GetAuthor()
+ {
+ Hashtable author = new Hashtable();
+ author["FirstName"] = "Atif";
+ author["LastName"] = "Aziz";
+ return author;
+ }
+
+ [ JsonRpcMethod("getCouple", Idempotent = true) ]
+ [ JsonRpcHelp("Returns a server-typed object representing a couple. Demonstrates to returning server-typed objects.")]
+ public Marriage GetCouple()
+ {
+ return new Marriage(
+ new Person("Mickey", "Mouse"),
+ new Person("Minnie", "Mouse"));
+ }
+
+ [ JsonRpcMethod("swapNames", Idempotent = true)]
+ [ JsonRpcHelp("Swaps first and last name of person. Demonstrates receiving and returning a server-typed object.")]
+ public Person SwapPersonNames(Person p)
+ {
+ return p == null ? new Person() : new Person(p.LastName, p.FirstName);
+ }
+
+ [JsonRpcMethod("getDataSet", Idempotent = true)]
+ [ JsonRpcHelp("Returns the Northwind employees as a DataSet.") ]
+ public DataSet GetEmployeeSet()
+ {
+ using (SqlConnection connection = new SqlConnection(ConfigurationSettings.AppSettings["NorthwindConnectionString"]))
+ {
+ SqlDataAdapter a = new SqlDataAdapter();
+ a.SelectCommand = new SqlCommand("SELECT EmployeeID, LastName, FirstName, Title, TitleOfCourtesy, BirthDate, HireDate, Address, City, Region, PostalCode, Country, HomePhone, Extension, Notes, ReportsTo, PhotoPath FROM Employees", connection);
+ DataSet ds = new DataSet();
+ a.Fill(ds, "Employee");
+ return ds;
+ }
+ }
+
+ [ JsonRpcMethod("getDataTable", Idempotent = true)]
+ [ JsonRpcHelp("Returns the Northwind employees as a DataTable.") ]
+ public DataTable GetEmployeeTable()
+ {
+ return GetEmployeeSet().Tables[0];
+ }
+
+ [ JsonRpcMethod("getRowArray", Idempotent = true)]
+ [ JsonRpcHelp("Returns the Northwind employees as an array of DataRow objects.") ]
+ public DataRow[] GetEmployeeRowArray()
+ {
+ return GetEmployeeSet().Tables[0].Select();
+ }
+
+ [ JsonRpcMethod("getRowCollection", Idempotent = true)]
+ [ JsonRpcHelp("Returns the Northwind employees as a DataRowCollection.") ]
+ public DataRowCollection GetEmployeeRows()
+ {
+ return GetEmployeeSet().Tables[0].Rows;
+ }
+
+ [ JsonRpcMethod("getDataView", Idempotent = true)]
+ [ JsonRpcHelp("Returns the Northwind employees as a DataView object.") ]
+ public DataView GetEmployeeView()
+ {
+ return GetEmployeeSet().Tables[0].DefaultView;
+ }
+
+ [ JsonRpcMethod("getFirstDataRow", Idempotent = true)]
+ [ JsonRpcHelp("Returns the first Northwind employee as a DataRow object.") ]
+ public DataRow GetFirstEmployeeRow()
+ {
+ return GetEmployeeSet().Tables[0].Rows[0];
+ }
+
+ [ JsonRpcMethod("getFirstDataRowView", Idempotent = true)]
+ [ JsonRpcHelp("Returns the first Northwind employee as a DataRowView object.") ]
+ public DataRowView GetFirstEmployeeRowView()
+ {
+ return GetEmployeeSet().Tables[0].DefaultView[0];
+ }
+
+ [ JsonRpcMethod("getDropDown", Idempotent = true)]
+ [ JsonRpcHelp("Returns a data-bound DropDownList to the client as HTML.") ]
+ public Control EmployeeDropDown()
+ {
+ DropDownList ddl = new DropDownList();
+ DataSet ds = GetEmployeeSet();
+ ds.Tables[0].Columns.Add("FullName", typeof(string), "FirstName + ' ' + LastName");
+ ddl.DataSource = ds;
+ ddl.DataMember = "Employee";
+ ddl.DataTextField = "FullName";
+ ddl.DataValueField = "EmployeeID";
+ ddl.DataBind();
+ return ddl;
+ }
+
+ [ JsonRpcMethod("getDataGrid", Idempotent = true)]
+ [ JsonRpcHelp("Returns a data-bound DataGrid to the client as HTML.") ]
+ public Control EmployeeDataGrid()
+ {
+ DataGrid grid = new DataGrid();
+ grid.DataSource = GetEmployeeSet();
+ grid.DataBind();
+ return grid;
+ }
+
+ [ JsonRpcMethod("total", Idempotent = true)]
+ [ JsonRpcHelp("Returns the total of all integers sent in an array.") ]
+ public int Total(int[] values)
+ {
+ int total = 0;
+
+ if (values != null)
+ {
+ foreach (int value in values)
+ total += value;
+ }
+
+ return total;
+ }
+
+ [ JsonRpcMethod("sleep", Idempotent = true) ]
+ [ JsonRpcHelp("Blocks the request for the specified number of milliseconds (maximum 7 seconds).") ]
+ public void Sleep(int milliseconds)
+ {
+ System.Threading.Thread.Sleep(Math.Min(7000, milliseconds));
+ }
+
+ [ JsonRpcMethod("throwError", Idempotent = true)]
+ [ JsonRpcHelp("Throws an error if you try to call this method.") ]
+ public void ThrowError()
+ {
+ throw new ApplicationException();
+ }
+
+ [ JsonRpcMethod("format", Idempotent = true)]
+ [ JsonRpcHelp("Formats placeholders in a format specification with supplied replacements. This method demonstrates fixed and variable arguments.") ]
+ public string Format(string format, params object[] args)
+ {
+ return string.Format(format, args);
+ }
+
+ [ JsonRpcMethod("counter", Idempotent = true)]
+ [ JsonRpcHelp("Increments a counter and returns its new value. Demonstrates use of session state.") ]
+ public int SessionCounter()
+ {
+ int counter = 0;
+ object counterObject = Session["Counter"];
+ if (counterObject != null)
+ counter = (int) counterObject;
+ Session["Counter"] = ++counter;
+ return counter;
+ }
+
+ [ JsonRpcMethod("encode", Idempotent = true)]
+ [ JsonRpcHelp("Returns the bytes of a string in a given encoding that are transmitted as a Base64 string.") ]
+ public byte[] EncodeBytes(string s, string encoding)
+ {
+ return System.Text.Encoding.GetEncoding(encoding).GetBytes(s);
+ }
+
+ [JsonRpcMethod("decode", Idempotent = true)]
+ [JsonRpcHelp("Returns the string from encoded bytes (transmitted as a Base64 string).")]
+ public string DecodeString(byte[] bytes, string encoding)
+ {
+ return System.Text.Encoding.GetEncoding(encoding).GetString(bytes);
+ }
+
+ //
+ // NOTE: To send and receive typed objects, use public types only
+ // that have a default constructor. Only public read/write fields
+ // and properties are convert to and from JSON.
+ //
+
+ public class Marriage
+ {
+ public Person Husband;
+ public Person Wife;
+
+ public Marriage() { }
+
+ public Marriage(Person husband, Person wife)
+ {
+ Husband = husband;
+ Wife = wife;
+ }
+ }
+
+ public class Person
+ {
+ public string FirstName;
+ public string LastName;
+
+ public Person() { }
+
+ public Person(string fn, string ln)
+ {
+ FirstName = fn;
+ LastName = ln;
+ }
+ }
+ }
+}
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/DemoService.html b/struts-sandbox/overdrive/PhoneBook2/projects/Web/DemoService.html
new file mode 100644
index 0000000..ebb7353
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/DemoService.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <title>Dojo Element / Jayrocks Service Demonstration</title>
+ <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
+ <meta name=ProgId content=VisualStudio.HTML>
+ <meta name=Originator content="Microsoft Visual Studio .NET 7.1">
+ <script language="javascript" src="DemoService.ashx?proxy&v=2"></script>
+ <script language="javascript" src="js/dojo/dojo.js"></script>
+ <script language="javascript">
+ dojo.require("dojo.io.*");
+ dojo.require("dojo.event.*");
+ dojo.require("dojo.html.*");
+ dojo.require("dojo.json");
+
+ // Invokes service method
+ function dojoChannel(call)
+ {
+ var bindArgs = {
+ url: call.url+'?rpc',
+ error: function(type, data, evt){alert("error");},
+ method: "POST",
+ mimetype: "text/json",
+ handle: call.callback,
+ postContent: dojo.json.serialize(call.request)
+ };
+ var req = dojo.io.bind(bindArgs);
+ dojo.event
+ return req;
+ }
+
+ // Formats output into a control
+ function string_array_element(type, data, evt)
+ {
+ var arr = data.result;
+ var theDiv = dojo.byId('string_array');
+ var select = document.createElement('select');
+ for(var i=0; i < arr.length; i++)
+ {
+ select.options[i] = new Option(arr[i], arr[i]);
+ }
+ theDiv.appendChild(select);
+ }
+
+ // Wraps call to RPC method
+ function getStringArray()
+ {
+ DemoService.rpc.getStringArray(string_array_element).call(dojoChannel);
+ }
+
+ // Obtains output on page load
+ dojo.event.connect(window, "onload", getStringArray);
+ </script>
+ </head>
+ <body>
+
+ <h2>getStringArray as Select control</h2>
+ <div id="string_array"></div>
+ <hr />
+
+ </body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/HelloWorld.ashx b/struts-sandbox/overdrive/PhoneBook2/projects/Web/HelloWorld.ashx
new file mode 100644
index 0000000..f0332ab
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/HelloWorld.ashx
@@ -0,0 +1,16 @@
+<%@ WebHandler Class="JayrockWeb.HelloWorld" Language="C#" %>
+
+namespace JayrockWeb
+{
+ using Jayrock.JsonRpc;
+ using Jayrock.JsonRpc.Web;
+
+ public class HelloWorld : JsonRpcHandler
+ {
+ [ JsonRpcMethod("greetings") ]
+ public string Greetings()
+ {
+ return "Welcome to Jayrock!";
+ }
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/HelloWorld.html b/struts-sandbox/overdrive/PhoneBook2/projects/Web/HelloWorld.html
new file mode 100644
index 0000000..62f6594
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/HelloWorld.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+ <title>Hello Jayrock and Dojo</title>
+
+ <!-- Basic Jayrock -->
+ <script type="text/javascript" src="js/json.js"></script>
+ <script type="text/javascript" src="helloworld.ashx?proxy"></script>
+ <script type="text/javascript">
+ window.onload = function()
+ {
+ var s = new HelloWorld();
+ alert("sync:" + s.greetings());
+ s.greetings(function(response) {
+ alert("async:" + response.result)
+ });
+ }
+ </script>
+ <!-- Basic Dojo -->
+ <script language="javascript" src="js/dojo/dojo.js"></script>
+ <script language="javascript">
+ dojo.require("dojo.event.*");
+ dojo.require("dojo.widget.*");
+ dojo.require("dojo.widget.Button");
+
+ function helloPressed()
+ {
+ alert('You pressed the button');
+ }
+
+ function helloInit()
+ {
+ var helloButton = dojo.widget.byId('helloButton');
+ dojo.event.connect(helloButton, 'onClick', 'helloPressed')
+
+ }
+ dojo.addOnLoad(helloInit);
+ </script>
+</head>
+<body>
+ <p>This page combines the Jayrock and Dojo Hello World examples.</p>
+
+ <p><button id="helloButton" class="dojo-Button">Hello World!</button></p>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Objects.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Objects.xml
new file mode 100644
index 0000000..899f4ed
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Objects.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <import resource="Resources/AppBase.xml"/>
+ <import resource="Resources/AppConfig.xml"/>
+ <import resource="Resources/AppFields.xml"/>
+ <import resource="Resources/Catalog.xml"/>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/PhoneBook.ashx b/struts-sandbox/overdrive/PhoneBook2/projects/Web/PhoneBook.ashx
new file mode 100644
index 0000000..866b9cc
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/PhoneBook.ashx
@@ -0,0 +1,103 @@
+<%@ WebHandler Class="JayrockWeb.PhoneBook" Language="C#" %>
+
+using System;
+using System.Collections;
+using System.Configuration;
+using Agility.Extras.Spring;
+using Jayrock.JsonRpc;
+using Jayrock.JsonRpc.Web;
+using Nexus.Core;
+using Nexus.Core.Helpers;
+using PhoneBook.Core;
+using Spring.Context;
+
+namespace JayrockWeb
+{
+ public class PhoneBook : JsonRpcHandler
+ {
+
+ private IRequestCatalog catalog = null;
+
+ private IRequestCatalog GetCatalog()
+ {
+ if (catalog == null)
+ {
+ IApplicationContext factory = Objects.Factory();
+ catalog = factory.GetObject(App.CATALOG_KEY) as IRequestCatalog;
+ if (catalog == null)
+ throw new ConfigurationErrorsException("PhoneBook: GetCatalog()==null");
+ }
+ return catalog;
+ }
+
+ private RequestContext Execute(string command)
+ {
+ return (RequestContext) GetCatalog().ExecuteRequest(command);
+ }
+
+ [JsonRpcMethod(App.LAST_NAME_LIST, Idempotent = true)]
+ [JsonRpcHelp("Returns Last Name List as an array.")]
+ public string[] last_name_list()
+ {
+ RequestContext context = Execute(App.LAST_NAME_LIST);
+ KeyValueList list = context.Outcome as KeyValueList;
+ if (list == null) return null; // FIXME: Better error handling
+
+ ArrayList names = new ArrayList(list.Count);
+ foreach (KeyValue k in list)
+ {
+ names.Add(k.Value);
+ }
+ return (string[]) names.ToArray(typeof (String));
+ }
+
+ [JsonRpcMethod(App.ENTRY_LIST, Idempotent = true)]
+ [JsonRpcHelp("Returns the complete directory as an array of formatted IDictionary objects.")]
+ public AppEntryList entry_list()
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY_LIST);
+ helper.Execute();
+ // if helper.IsNominal ... // FIXME: Better error handling
+ AppEntryList list = helper.Outcome as AppEntryList;
+ return list;
+ }
+
+ [JsonRpcMethod(App.ENTRY, Idempotent = true)]
+ [JsonRpcHelp("Returns an entry by key.")]
+ public AppEntry entry(string key)
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY);
+ helper.Criteria[App.ENTRY_KEY] = key;
+ helper.Execute();
+ // if helper.IsNominal ... // FIXME: Better error handling
+ AppEntry entry = new AppEntry(helper.Criteria);
+ return entry;
+ }
+
+ [JsonRpcMethod(App.ENTRY_SAVE, Idempotent = true)]
+ [JsonRpcHelp("Saves the entry, insert or updating as appropriate.")]
+ public AppEntry entry_save(IDictionary input)
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY_SAVE);
+ helper.Read(input,true);
+ helper.Execute();
+ // if helper.IsNominal ... // FIXME: Better error handling
+ AppEntry entry = new AppEntry(helper.Criteria);
+ return entry;
+ }
+
+ [JsonRpcMethod(App.ENTRY_DELETE, Idempotent = true)]
+ [JsonRpcHelp("Deletes an entry by key.")]
+ public AppEntry entry_delete(string key)
+ {
+ IViewHelper helper = GetCatalog().GetHelperFor(App.ENTRY_DELETE);
+ helper.Criteria[App.ENTRY_KEY] = key;
+ helper.Execute();
+ // if helper.IsNominal ... // FIXME: Better error handling
+ AppEntry entry = new AppEntry(helper.Criteria);
+ return entry;
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/PhoneBook.html b/struts-sandbox/overdrive/PhoneBook2/projects/Web/PhoneBook.html
new file mode 100644
index 0000000..47938c8
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/PhoneBook.html
@@ -0,0 +1,339 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>PhoneBook</title>
+ <script type="text/javascript" src="PhoneBook.ashx?proxy&v=2"></script>
+ <script type="text/javascript" src="js/dojo/dojo.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.widget.TabContainer");
+ dojo.require("dojo.widget.ContentPane");
+ dojo.require("dojo.widget.LayoutContainer");
+ dojo.require("dojo.io.*");
+ dojo.require("dojo.event.*");
+ dojo.require("dojo.html.*");
+ dojo.require("dojo.json");
+ dojo.require("dojo.widget.FilteringTable");
+ dojo.hostenv.writeIncludes();
+
+ /* call server */
+
+ function server(call)
+ {
+ var bindArgs = {
+ url: call.url+'?rpc',
+ error: function(type, data, evt){alert("Error Communicating with Server: " + data.result);},
+ method: "POST",
+ mimetype: "text/json",
+ handle: call.callback,
+ postContent: dojo.json.serialize(call.request)
+ };
+ var req = dojo.io.bind(bindArgs);
+ dojo.event
+ return req;
+ }
+
+ var container_id = "container";
+
+ function view_select(id) {
+ var w = dojo.widget.byId(container_id);
+ w.selectChild(id);
+ }
+
+ /* lister */
+
+ var lister_id = "lister";
+ var entry_list_id = "entry_list";
+
+ function lister_select() {
+ view_select(lister_id);
+ }
+
+ function entry_list() {
+ return dojo.widget.byId(entry_list_id);
+ }
+
+ function entry_list_result(type, data, evt)
+ {
+ entry_list().store.setData(data.result);
+ }
+ function entry_list_load()
+ {
+ PhoneBook.rpc.entry_list(entry_list_result).call(server);
+ }
+ dojo.addOnLoad(entry_list_load);
+
+ function entry_list_select_edit(evt) {
+ entry_edit(entry_list().getSelectedData().entry_key);
+ }
+ function entry_list_select_delete(evt) {
+ entry_delete(entry_list().getSelectedData().entry_key);
+ }
+
+ function entry_list_select() {
+ dojo.event.connect(entry_list(), "onSelect", entry_list_select_edit);
+ }
+ dojo.addOnLoad(entry_list_select);
+
+ /* lister filters */
+
+ function dateFilter(hired) {
+ return (hired == '5/29/1987' || hired == '11/18/1984');
+ }
+ function applyDate(id){
+ dojo.widget.byId(id).setFilter("hired", dateFilter);
+ }
+
+ function nameFilter(last_name){
+ return (last_name.charAt(0) >= 'M' && last_name.charAt(0) <= 'Z');
+ }
+ function applyName(id){
+ dojo.widget.byId(id).setFilter("last_name", nameFilter);
+ }
+
+ function clearFilters(id){
+ dojo.widget.byId(id).clearFilters();
+ }
+ function reloadData(id){
+ dojo.widget.byId(id).store.clearData();
+ entry_list_load();
+ }
+
+ /* editor */
+
+ var editor_id = "editor";
+
+ function editor_select() {
+ view_select(editor_id);
+ }
+
+ var entry_form_id = "entry_form";
+
+ function entry_form() {
+ return dojo.widget.byId(entry_form_id);
+ }
+
+ var dpHired_id = "dpHired";
+
+ function setHired(hired) {
+ var dpHired = dojo.widget.byId(dpHired_id);
+ dpHired.setDate(hired);
+ }
+
+ function entry_edit_result(type, data, evt)
+ {
+ entry_form().setValues(data.result);
+ var part = new Array();
+ part = data.result.hired.split('/',3); // mm/dd/yyyy
+ var yyyy = part[2];
+ var mm = part[0];
+ var dd = part[1];
+ if (mm.length==1) mm = new String().concat('0',mm);
+ if (dd.length==1) dd = new String().concat('0',dd);
+ var hired = new String().concat( yyyy,'-',mm,'-',dd );
+ setHired(hired);
+
+ editor_select();
+ }
+ function entry_edit(entry_key)
+ {
+ PhoneBook.rpc.entry(entry_key,entry_edit_result).call(server);
+ }
+
+ function entry_save_result() {
+ reloadData(entry_list_id);
+ entry_reset();
+ lister_select();
+
+ }
+ function entry_save_update_result(type, data, evt)
+ {
+ alert ( "Edited: " + data.result.user_name + " (" + data.result.entry_key + ")" );
+ entry_save_result();
+ }
+ function entry_save_insert_result(type, data, evt)
+ {
+ alert ( "Added: " + data.result.user_name + " (" + data.result.entry_key + ")" );
+ entry_save_result();
+ }
+ function entry_save()
+ {
+ var values = entry_form().getValues();
+ if (values.entry_key)
+ PhoneBook.rpc.entry_save(values,entry_save_update_result).call(server);
+ else
+ PhoneBook.rpc.entry_save(values,entry_save_insert_result).call(server);
+ }
+
+ function entry_quit() {
+ entry_reset();
+ lister_select();
+ }
+
+ function entry_reset() {
+ var values = entry_form().getValues();
+ values.first_name = "";
+ values.last_name = "";
+ values.extension = "";
+ values.user_name = "";
+ values.hours = "37.5";
+ values.entry_key = "";
+ entry_form().setValues(values);
+ var today = new Date();
+ setHired(today);
+ }
+
+ function entry_add()
+ {
+ entry_reset();
+ editor_select();
+ }
+
+ function entry_delete_result(type, data, evt)
+ {
+ alert ( "Deleted: (" + data.result.entry_key + ")" );
+ entry_save_result();
+ }
+ function entry_delete(entry_key)
+ {
+ if (entry_key) {
+ var ok = confirm ( "Delete entry?" );
+ if (ok)
+ PhoneBook.rpc.entry_delete(entry_key,entry_delete_result).call(server);
+ }
+ }
+
+ </script>
+
+ <style type="text/css">
+ body {
+ font-family : sans-serif;
+ }
+ .dojoTabPaneWrapper {
+ padding : 10px 10px 10px 10px;
+ }
+
+ </style>
+
+ <style type="text/css">
+ /***
+ The following is just an example of how to use the table.
+ You can override any class names to be used if you wish.
+ ***/
+ table {
+ font-family:Lucida Grande, Verdana;
+ font-size:0.8em;
+ width:100%;
+ border:1px solid #ccc;
+ border-collapse:collapse;
+ cursor:default;
+ }
+ table td,
+ table th{
+ padding:2px;
+ font-weight:normal;
+ }
+ table thead td, table thead th {
+ background-image:url(images/ft-head.gif);
+ background-repeat:no-repeat;
+ background-position:top right;
+ }
+ table thead td.selectedUp, table thead th.selectedUp {
+ background-image:url(images/ft-headup.gif);
+ }
+ table thead td.selectedDown, table thead th.selectedDown {
+ background-image:url(images/ft-headdown.gif);
+ }
+
+ table tbody tr td{
+ border-bottom:1px solid #ddd;
+ }
+ table tbody tr.alt td{
+ background: #e3edfa;
+ }
+ table tbody tr.selected td{
+ background: yellow;
+ }
+ table tbody tr:hover td{
+ background: #a6c2e7;
+ }
+ table tbody tr.selected:hover td{
+ background:#ff9;
+ }
+
+ #inputArea{
+ margin:1em 0;
+ padding:1em;
+ background-color:#eef;
+ }
+ #updateTestInput{
+ border:1px solid #ccc;
+ width:100%;
+ height:80px;
+ font-family:serif;
+ font-size:0.9em;
+ overflow:auto;
+ }
+ </style>
+ </head>
+ <body>
+
+ <div id="container" dojoType="TabContainer" style="width:100%; height:70%;" selectedChild="lister">
+
+ <div id="lister" dojoType="ContentPane" label="PhoneBook Directory" >
+ <table id="filter_menu"><tr><td>
+ <input type="button" onclick="applyDate('entry_list');" value="Show only hires between 1/1/1984 and 1/1/1987" />
+ <input type="button" onclick="applyName('entry_list');" value="Show only names between M and Z" />
+ <input type="button" value="Show All Entries" onclick="clearFilters('entry_list');" />
+ <input type="button" value="Reload Entries" onclick="reloadData('entry_list');" />
+ </td></tr></table>
+
+ <table id="entry_list"
+ dojoType="filteringTable" alternateRows="true" valueField="user_name" >
+ <thead>
+ <tr>
+ <th field="last_name" sort="asc">Last Name</th>
+ <th field="first_name">First Name</th>
+ <th field="extension">Extension</th>
+ <th field="user_name">User</th>
+ <th field="hired" align="center">Hired</th>
+ <th field="hours" align="center">Hours</th>
+ </tr>
+ </thead>
+ </table>
+
+ <table id="edit_menu"><tr><td>
+ <input type="button" value="Add Entry" onclick="entry_add('entry_list');" />
+ </td></tr></table>
+
+ </div>
+
+ <div id="editor" dojoType="ContentPane" label="Entry Editor">
+
+ <form id="entry_form" dojoType="Form">
+ <table><tr>
+ <td>First Name</td><td><input name="first_name" /></td>
+ </tr><tr>
+ <td>Last Name</td><td><input name="last_name" /></td>
+ </tr><tr>
+ <td>Extension</td><td><input name="extension" /></td>
+ </tr><tr>
+ <td>User Name</td><td><input name="user_name" /></td>
+ </tr><tr>
+ <td>Hired</td><td><input name="hired" widgetid="dpHired" dojoType="dropdowndatepicker" displayFormat="MM/dd/yyyy" /></td>
+ </tr><tr>
+ <td>Hours</td><td><input name="hours" /></td>
+ </tr><tr>
+ <td rowspan="2">
+ <input type="button" value="SAVE" onClick="entry_save();" />
+ <input type="button" value="CANCEL" onClick="entry_quit();" />
+ <input type="button" value="DELETE" onclick="entry_list_select_delete('entry_list');" />
+ <input type="hidden" name="editor" value="1" />
+ <input type="hidden" name="entry_key" />
+ </td>
+ </tr></table>
+ </form>
+ </div>
+ </div>
+
+ </body>
+</html>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppBase.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppBase.xml
new file mode 100644
index 0000000..9280689
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppBase.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Base element (super parent)-->
+
+ <object id="BaseMapper" abstract="true">
+ <property name="Mapper"><ref object="Mapper"/></property>
+ </object>
+
+ <!-- Base class parents -->
+
+ <object id="BaseChain" type="Nexus.Core.RequestChain, Nexus.Core"/>
+
+ <object id="BaseCount" type="PhoneBook.Core.Commands.BaseCount, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseDelete" type="PhoneBook.Core.Commands.BaseDelete, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseEntry" type="PhoneBook.Core.Commands.BaseEntry, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFilterList" type="PhoneBook.Core.Commands.BaseFilterList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseFieldContext" type="Nexus.Extras.Spring.FieldContext">
+ <property name="MessageSource">
+ <ref object="messageSource" />
+ </property>
+ </object>
+
+ <object id="BaseKeyValueProcessor" type="Nexus.Core.Validators.KeyValueProcessor"/>
+
+ <object id="BaseList" type="PhoneBook.Core.Commands.BaseList, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="BaseSave" type="PhoneBook.Core.Commands.BaseSave, PhoneBook.Core" parent="BaseMapper"/>
+
+ <object id="EntryInitial" type="PhoneBook.Core.Commands.EntryInitial, PhoneBook.Core" parent="BaseMapper"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppConfig.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppConfig.xml
new file mode 100644
index 0000000..f3bbcbd
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppConfig.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- Message Source -->
+
+ <object id="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core">
+ <property name="ResourceManagers">
+ <list>
+ <value>PhoneBook.Core.Messages, PhoneBook.Core</value>
+ <value>Nexus.Web.Messages, Nexus.Web</value>
+ </list>
+ </property>
+ </object>
+
+
+ <!-- Request Processors -->
+
+ <object id="convert_input" type="Nexus.Core.Validators.ConvertInput">
+ <property name="ID"><value>convert_input</value></property>
+ </object>
+
+ <object id="format_output" type="Nexus.Core.Validators.FormatOutput">
+ <property name="ID"><value>format_output</value></property>
+ </object>
+
+ <object id="clear_context" type="Nexus.Core.Validators.ClearContext">
+ <property name="ID"><value>clear_context</value></property>
+ </object>
+
+ <!-- pre-op -->
+
+ <object id="pre-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="convert_input"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- post-op -->
+
+ <object id="post-op" parent="BaseChain">
+ <property name="AddCommands">
+ <list>
+ <ref object="format_output"/>
+ </list>
+ </property>
+ </object>
+
+ <!-- Catalog -->
+
+ <object id="Catalog" type="Nexus.Extras.Spring.Catalog">
+ <property name="FieldTable"><ref object="FieldTable"/></property>
+ <property name="PreOp"><ref object="pre-op"/></property>
+ <property name="PostOp"><ref object="post-op"/></property>
+ <property name="ViewHelper"><object type="Nexus.Web.WebHelper, Nexus.Web" singleton="false"/></property>
+ </object>
+
+<!-- iBATIS Mapper -->
+
+ <object id="Mapper" type="IBatisNet.DataMapper.Mapper, IBatisNet.DataMapper"
+ factory-method="Instance"/>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppFields.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppFields.xml
new file mode 100644
index 0000000..99c23d9
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/AppFields.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- FieldTable -->
+
+ <object id="FieldTable" type="Nexus.Core.Tables.FieldTable">
+ <property name="AddFieldContexts">
+ <list>
+ <ref object="last_name"/>
+ <ref object="first_name"/>
+ <ref object="extension"/>
+ <ref object="user_name"/>
+ <ref object="hired"/>
+ <ref object="hours"/>
+ <ref object="_entry_list"/>
+ <ref object="_entry_list_count"/>
+ <ref object="_extension_list"/>
+ <ref object="_hired_list"/>
+ </list>
+ </property>
+ <property name="AddProcessors">
+ <list>
+ <ref object="DateTimeProcessor"/>
+ <ref object="TelephoneProcessor"/>
+ <ref object="EntryListProcessor"/>
+ <ref object="ExtensionListProcessor"/>
+ <ref object="HiredListProcessor"/>
+ </list>
+ </property>
+ </object>
+
+ <object id="last_name" parent="BaseFieldContext">
+ <property name="ID"><value>last_name</value></property>
+ </object>
+
+ <object id="first_name" parent="BaseFieldContext">
+ <property name="ID"><value>first_name</value></property>
+ </object>
+
+ <object id="user_name" parent="BaseFieldContext">
+ <property name="ID"><value>user_name</value></property>
+ </object>
+
+ <object id="extension" parent="BaseFieldContext">
+ <property name="ID"><value>extension</value></property>
+ <property name="Processor"><ref object="TelephoneProcessor"/></property>
+ </object>
+
+ <object id="hired" parent="BaseFieldContext">
+ <property name="ID"><value>hired</value></property>
+ <property name="Processor"><ref object="DateTimeProcessor"/></property>
+ </object>
+
+ <object id="hours" parent="BaseFieldContext">
+ <property name="ID"><value>hours</value></property>
+ </object>
+
+ <object id="editor" parent="BaseFieldContext">
+ <property name="ID"><value>editor</value></property>
+ </object>
+
+ <!-- property name="ControlTypeName"><value>CheckBox</value></property -->
+
+ <!-- We need to "hash" the name with "_" to avoid conflict with the filter Command -->
+ <object id="_entry_list" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="Processor"><ref object="EntryListProcessor"/></property>
+ </object>
+
+ <object id="_entry_list_count" parent="BaseFieldContext">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="Processor"><ref object="CollectionProcessor"/></property>
+ </object>
+
+ <object id="_extension_list" parent="BaseFieldContext">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="Processor"><ref object="ExtensionListProcessor"/></property>
+ </object>
+
+ <object id="_hired_list" parent="BaseFieldContext">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="Processor"><ref object="HiredListProcessor"/></property>
+ </object>
+
+ <object id="CollectionProcessor" type="Nexus.Core.Validators.CollectionProcessor, Nexus.Core">
+ <property name="ID"><value>EntryCountProcessor</value></property>
+ </object>
+
+ <!-- "d" is .NET for "shor date" -->
+ <object id="DateTimeProcessor" type="Nexus.Core.Validators.DateTimeProcessor">
+ <property name="ID"><value>DateTimeProcessor</value></property>
+ <property name="DataFormat"><value>d</value></property>
+ </object>
+
+ <object id="TelephoneProcessor" type="PhoneBook.Core.TelephoneProcessor">
+ <property name="ID"><value>TelephoneProcessor</value></property>
+ </object>
+
+ <object id="EntryListProcessor" type="PhoneBook.Core.AppEntryListProcessor">
+ <property name="ID"><value>EntryListProcessor</value></property>
+ </object>
+
+ <object id="ExtensionListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>ExtensionListProcessor</value></property>
+ <property name="Key"><value>extension</value></property>
+ </object>
+
+ <object id="HiredListProcessor" parent="BaseKeyValueProcessor">
+ <property name="ID"><value>HiredListProcessor</value></property>
+ <property name="Key"><value>hired</value></property>
+ </object>
+
+</objects>
\ No newline at end of file
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/Catalog.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/Catalog.xml
new file mode 100644
index 0000000..bd89c45
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/Catalog.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">
+
+ <!-- entry commands -->
+
+ <object id="entry_list_rows" parent="BaseList">
+ <property name="ID"><value>entry_list</value></property>
+ <property name="QueryID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_list_count" parent="BaseCount">
+ <property name="ID"><value>entry_list_count</value></property>
+ <property name="QueryID"><value>entry_count</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_list</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ <value>initial</value>
+ <value>item_count</value>
+ <value>item_offset</value>
+ <value>item_limit</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry" parent="BaseEntry">
+ <property name="ID"><value>entry</value></property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry</value>
+ <value>entry_key</value>
+ <value>last_name</value>
+ <value>first_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hired</value>
+ <value>hours</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_delete" parent="BaseDelete">
+ <property name="ID">
+ <value>entry_delete</value>
+ </property>
+ <property name="RequiredIDs">
+ <list>
+ <value>entry_key</value>
+ </list>
+ </property>
+ </object>
+
+ <!-- filter list commands -->
+
+ <object id="last_name_list" parent="BaseFilterList">
+ <property name="ID"><value>last_name_list</value></property>
+ <property name="RelatedIDs"><list><value>last_name_list</value></list></property>
+ </object>
+
+ <object id="first_name_list" parent="BaseFilterList">
+ <property name="ID"><value>first_name_list</value></property>
+ <property name="RelatedIDs"><list><value>first_name_list</value></list></property>
+ </object>
+
+ <object id="extension_list" parent="BaseFilterList">
+ <property name="ID"><value>extension_list</value></property>
+ <property name="RelatedIDs"><list><value>extension_list</value></list></property>
+ </object>
+
+ <object id="user_name_list" parent="BaseFilterList">
+ <property name="ID"><value>user_name_list</value></property>
+ <property name="RelatedIDs"><list><value>user_name_list</value></list></property>
+ </object>
+
+ <object id="hired_list" parent="BaseFilterList">
+ <property name="ID"><value>hired_list</value></property>
+ <property name="RelatedIDs"><list><value>hired_list</value></list></property>
+ </object>
+
+ <object id="hours_list" parent="BaseFilterList">
+ <property name="ID"><value>hours_list</value></property>
+ <property name="RelatedIDs"><list><value>hours_list</value></list></property>
+ </object>
+
+ <object id="entry_initial" parent="EntryInitial">
+ <property name="ID">
+ <value>entry_initial</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_initial</value>
+ </list>
+ </property>
+ </object>
+
+ <!-- chains -->
+
+ <object id="entry_list" parent="BaseChain">
+ <property name="ID">
+ <value>entry_list</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="entry_list_count" />
+ <ref object="entry_list_rows" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_find" parent="BaseChain">
+ <property name="ID">
+ <value>entry_find</value>
+ </property>
+ <property name="AddCommands">
+ <list>
+ <ref object="last_name_list" />
+ <ref object="first_name_list" />
+ <ref object="extension_list" />
+ <ref object="user_name_list" />
+ <ref object="hired_list" />
+ <ref object="hours_list" />
+ </list>
+ </property>
+ </object>
+
+ <object id="entry_save" parent="BaseSave">
+ <property name="ID">
+ <value>entry_save</value>
+ </property>
+ <property name="KeyID">
+ <value>entry_key</value>
+ </property>
+ <property name="InsertID">
+ <value>entry_insert</value>
+ </property>
+ <property name="UpdateID">
+ <value>entry_update</value>
+ </property>
+ <property name="RelatedIDs">
+ <list>
+ <value>entry_key</value>
+ </list>
+ </property>
+ <property name="RequiredIDs">
+ <list>
+ <value>first_name</value>
+ <value>last_name</value>
+ <value>extension</value>
+ <value>user_name</value>
+ <value>hours</value>
+ <value>hired</value>
+ <value>editor</value>
+ </list>
+ </property>
+ </object>
+
+</objects>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/Queries.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/Queries.xml
new file mode 100644
index 0000000..370639f
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Resources/Queries.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<sqlMap
+ namespace="phonebook"
+ xmlns="http://ibatis.apache.org/mapping"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
+
+ <parameterMaps>
+
+ <parameterMap id="entry_save_param">
+ <parameter property="last_name"/>
+ <parameter property="first_name"/>
+ <parameter property="extension"/>
+ <parameter property="user_name"/>
+ <parameter property="hired"/>
+ <parameter property="hours"/>
+ <parameter property="editor"/>
+ <parameter property="entry_key"/>
+ </parameterMap>
+
+ </parameterMaps>
+
+ <statements>
+
+ <select id="last_name_list" resultClass="string">
+ SELECT DISTINCT
+ last_name
+ FROM entry
+ ORDER BY last_name
+ </select>
+
+ <select id="first_name_list" resultClass="string">
+ SELECT DISTINCT
+ first_name
+ FROM entry
+ ORDER BY first_name
+ </select>
+
+ <select id="extension_list" resultClass="string">
+ SELECT DISTINCT
+ extension
+ FROM entry
+ ORDER BY extension
+ </select>
+
+ <select id="user_name_list" resultClass="string">
+ SELECT DISTINCT
+ user_name
+ FROM entry
+ ORDER BY user_name
+ </select>
+
+ <select id="hired_list" resultClass="date">
+ SELECT DISTINCT
+ hired
+ FROM entry
+ ORDER BY hired
+ </select>
+
+ <select id="hours_list" resultClass="string">
+ SELECT DISTINCT
+ hours
+ FROM entry
+ ORDER BY hours
+ </select>
+
+ <select id="entry" paramClass="Hashtable" resultClass="Hashtable">
+ SELECT
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry AS entry_key
+ FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ <dynamic>
+ <isNotNull property="item_limit">
+ LIMIT #item_limit# OFFSET #item_offset#
+ </isNotNull>
+ </dynamic>;
+ </select>
+
+ <select id="entry_count" paramClass="Hashtable" resultClass="string">
+ SELECT COUNT(*) FROM entry
+ <dynamic prepend="WHERE">
+ <isNotNull property="initial" prepend="AND">
+ last_name LIKE #initial#
+ </isNotNull>
+ <isNotNull property="last_name" prepend="AND">
+ last_name=#last_name#
+ </isNotNull>
+ <isNotNull property="first_name" prepend="AND">
+ first_name=#first_name#
+ </isNotNull>
+ <isNotNull property="extension" prepend="AND">
+ extension=#extension#
+ </isNotNull>
+ <isNotNull property="user_name" prepend="AND">
+ user_name=#user_name#
+ </isNotNull>
+ <isNotNull property="hired" prepend="AND">
+ hired=#hired#
+ </isNotNull>
+ <isNotNull property="hours" prepend="AND">
+ hours=#hours#
+ </isNotNull>
+ <isNotNull property="editor" prepend="AND">
+ hours=#editor#
+ </isNotNull>
+ <isNotNull property="entry_key" prepend="AND">
+ pk_entry=#entry_key#
+ </isNotNull>
+ </dynamic>
+ </select>
+
+ <select id="entry_initial" paramClass="string" resultClass="string">
+ SELECT COUNT(*)
+ FROM entry
+ WHERE last_name LIKE #value#
+ </select>
+
+ <insert id="entry_insert" parameterMap="entry_save_param">
+ INSERT INTO entry (
+ last_name,
+ first_name,
+ extension,
+ user_name,
+ hired,
+ hours,
+ editor,
+ pk_entry
+ )
+ VALUES (?,?,?,?, ?,?,?,?)
+ </insert>
+
+ <update id="entry_update" parameterMap="entry_save_param">
+ UPDATE entry SET
+ last_name=?,
+ first_name=?,
+ extension=?,
+ user_name=?,
+ hired=?,
+ hours=?,
+ editor=?
+ WHERE
+ pk_entry=?
+ </update>
+
+ <delete id="entry_delete" paramClass="Hashtable">
+ DELETE FROM entry WHERE pk_entry=#entry_key#;
+ </delete>
+
+ </statements>
+</sqlMap>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/Web.Config b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Web.Config
new file mode 100644
index 0000000..0abb491
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/Web.Config
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+ Note: As an alternative to hand editing this file you can use the
+ web admin tool to configure settings for your application. Use
+ the Website->Asp.Net Configuration option in Visual Studio.
+ A full list of settings and comments can be found in
+ machine.config.comments usually located in
+ \Windows\Microsoft.Net\Framework\v2.x\Config
+-->
+<configuration>
+ <appSettings/>
+ <connectionStrings/>
+ <system.web>
+ <!--
+ Set compilation debug="true" to insert debugging
+ symbols into the compiled page. Because this
+ affects performance, set this value to true only
+ during development.
+ -->
+ <compilation debug="true"/>
+ <!--
+ The <authentication> section enables configuration
+ of the security authentication mode used by
+ ASP.NET to identify an incoming user.
+ -->
+ <authentication mode="Windows"/>
+ <!--
+ The <customErrors> section enables configuration
+ of what to do if/when an unhandled error occurs
+ during the execution of a request. Specifically,
+ it enables developers to configure html error pages
+ to be displayed in place of a error stack trace.
+
+ <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
+ <error statusCode="403" redirect="NoAccess.htm" />
+ <error statusCode="404" redirect="FileNotFound.htm" />
+ </customErrors>
+ -->
+ </system.web>
+</configuration>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/providers.config b/struts-sandbox/overdrive/PhoneBook2/projects/Web/providers.config
new file mode 100644
index 0000000..e0a5241
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/providers.config
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8"?>
+<providers
+xmlns="http://ibatis.apache.org/providers"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+<clear/>
+<provider
+ name="sqlServer1.0"
+ description="Microsoft SQL Server, provider V1.0.3300.0 in framework .NET V1.0"
+ enabled="false"
+ assemblyName="System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider
+ name="sqlServer1.1"
+ description="Microsoft SQL Server, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ default="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass="System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider
+ name="sqlServer2.0"
+ enabled="false"
+ description="Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.SqlClient.SqlConnection"
+ commandClass="System.Data.SqlClient.SqlCommand"
+ parameterClass="System.Data.SqlClient.SqlParameter"
+ parameterDbTypeClass="System.Data.SqlDbType"
+ parameterDbTypeProperty="SqlDbType"
+ dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
+ commandBuilderClass=" System.Data.SqlClient.SqlCommandBuilder"
+ usePositionalParameters = "false"
+ useParameterPrefixInSql = "true"
+ useParameterPrefixInParameter = "true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+<provider name="OleDb1.1"
+ description="OleDb, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider name="OleDb2.0"
+ description="OleDb, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.OleDb.OleDbConnection"
+ commandClass="System.Data.OleDb.OleDbCommand"
+ parameterClass="System.Data.OleDb.OleDbParameter"
+ parameterDbTypeClass="System.Data.OleDb.OleDbType"
+ parameterDbTypeProperty="OleDbType"
+ dataAdapterClass="System.Data.OleDb.OleDbDataAdapter"
+ commandBuilderClass="System.Data.OleDb.OleDbCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc1.1"
+ description="Odbc, provider V1.0.5000.0 in framework .NET V1.1"
+ enabled="true"
+ assemblyName="System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="Odbc2.0"
+ description="Odbc, provider V2.0.0.0 in framework .NET V2"
+ enabled="false"
+ assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
+ connectionClass="System.Data.Odbc.OdbcConnection"
+ commandClass="System.Data.Odbc.OdbcCommand"
+ parameterClass="System.Data.Odbc.OdbcParameter"
+ parameterDbTypeClass="System.Data.Odbc.OdbcType"
+ parameterDbTypeProperty="OdbcType"
+ dataAdapterClass="System.Data.Odbc.OdbcDataAdapter"
+ commandBuilderClass="System.Data.Odbc.OdbcCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle9.2"
+ description="Oracle, Oracle provider V9.2.0.401"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=9.2.0.401, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracle10.1"
+ description="Oracle, oracle provider V10.1.0.301"
+ enabled="false"
+ assemblyName="Oracle.DataAccess, Version=10.1.0.301, Culture=neutral, PublicKeyToken=89b483f429c47342" connectionClass="Oracle.DataAccess.Client.OracleConnection"
+ commandClass="Oracle.DataAccess.Client.OracleCommand"
+ parameterClass="Oracle.DataAccess.Client.OracleParameter"
+ parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"
+ parameterDbTypeProperty="OracleDbType"
+ dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"
+ commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+ <provider
+ name="oracleClient1.0"
+ description="Oracle, Microsoft provider V1.0.5000.0"
+ enabled="false"
+ assemblyName="System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.OracleClient.OracleConnection"
+ commandClass="System.Data.OracleClient.OracleCommand"
+ parameterClass="System.Data.OracleClient.OracleParameter"
+ parameterDbTypeClass="System.Data.OracleClient.OracleType"
+ parameterDbTypeProperty="OracleType"
+ dataAdapterClass="System.Data.OracleClient.OracleDataAdapter"
+ commandBuilderClass="System.Data.OracleClient.OracleCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=":"
+ allowMARS="false"
+ />
+ <provider
+ name="ByteFx"
+ description="MySQL, ByteFx provider V0.7.6.15073"
+ enabled="false"
+ assemblyName="ByteFX.MySqlClient, Version=0.7.6.15073, Culture=neutral, PublicKeyToken=f2fef6fed1732fc1" connectionClass="ByteFX.Data.MySqlClient.MySqlConnection"
+ commandClass="ByteFX.Data.MySqlClient.MySqlCommand"
+ parameterClass="ByteFX.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="ByteFX.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="ByteFX.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="ByteFX.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="MySql"
+ description="MySQL, MySQL provider 1.0.7.30072"
+ enabled="true"
+ assemblyName="MySql.Data, Version=1.0.7.30072, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionClass="MySql.Data.MySqlClient.MySqlConnection"
+ commandClass="MySql.Data.MySqlClient.MySqlCommand"
+ parameterClass="MySql.Data.MySqlClient.MySqlParameter"
+ parameterDbTypeClass="MySql.Data.MySqlClient.MySqlDbType"
+ parameterDbTypeProperty="MySqlDbType"
+ dataAdapterClass="MySql.Data.MySqlClient.MySqlDataAdapter"
+ commandBuilderClass="MySql.Data.MySqlClient.MySqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="?"
+ allowMARS="false"
+ />
+ <provider name="SQLite3"
+ description="SQLite, SQLite.NET provider V0.21.1869.3794"
+ enabled="false"
+ assemblyName="SQLite.NET, Version=0.21.1869.3794, Culture=neutral, PublicKeyToken=c273bd375e695f9c"
+ connectionClass="Finisar.SQLite.SQLiteConnection"
+ commandClass="Finisar.SQLite.SQLiteCommand"
+ parameterClass="Finisar.SQLite.SQLiteParameter"
+ parameterDbTypeClass="System.Data.DbType, System.Data"
+ parameterDbTypeProperty="DbType"
+ dataAdapterClass="Finisar.SQLite.SQLiteDataAdapter"
+ commandBuilderClass="Finisar.SQLite.SQLiteCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ setDbParameterPrecision="false"
+ setDbParameterScale="false"
+ allowMARS="false"
+ />
+ <provider
+ name="Firebird1.7"
+ description="Firebird, Firebird SQL .NET provider V1.7.0.33200"
+ enabled="false"
+ assemblyName="FirebirdSql.Data.Firebird, Version=1.7.0.33200, Culture=neutral, PublicKeyToken=fa843d180294369d" connectionClass="FirebirdSql.Data.Firebird.FbConnection"
+ commandClass="FirebirdSql.Data.Firebird.FbCommand"
+ parameterClass="FirebirdSql.Data.Firebird.FbParameter"
+ parameterDbTypeClass="FirebirdSql.Data.Firebird.FbDbType"
+ parameterDbTypeProperty="FbDbType"
+ dataAdapterClass="FirebirdSql.Data.Firebird.FbDataAdapter"
+ commandBuilderClass="FirebirdSql.Data.Firebird.FbCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix="@"
+ allowMARS="false"
+ />
+ <provider
+ name="PostgreSql0.99.1.0"
+ description="PostgreSql, Npgsql provider V0.99.1.0"
+ enabled="false"
+ assemblyName="Npgsql, Version=0.99.1.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"
+ connectionClass="Npgsql.NpgsqlConnection"
+ commandClass="Npgsql.NpgsqlCommand"
+ parameterClass="Npgsql.NpgsqlParameter"
+ parameterDbTypeClass="NpgsqlTypes.NpgsqlDbType"
+ parameterDbTypeProperty="NpgsqlDbType"
+ dataAdapterClass="Npgsql.NpgsqlDataAdapter"
+ commandBuilderClass="Npgsql.NpgsqlCommandBuilder"
+ usePositionalParameters="false"
+ useParameterPrefixInSql="true"
+ useParameterPrefixInParameter="true"
+ parameterPrefix=":"
+ allowMARS="true"
+ />
+ <provider
+ name="iDb2.10"
+ description="IBM DB2 Provider, V 10.0"
+ enabled="false"
+ assemblyName="IBM.Data.DB2.iSeries, Version=10.0.0.0,Culture=neutral, PublicKeyToken=9cdb2ebfb1f93a26, Custom=null" connectionClass="IBM.Data.DB2.iSeries.iDB2Connection"
+ commandClass="IBM.Data.DB2.iSeries.iDB2Command"
+ parameterClass="IBM.Data.DB2.iSeries.iDB2Parameter"
+ parameterDbTypeClass="IBM.Data.DB2.iSeries.iDB2DbType"
+ parameterDbTypeProperty="iDB2DbType"
+ dataAdapterClass="IBM.Data.DB2.iSeries.iDB2DataAdapter"
+ commandBuilderClass="IBM.Data.DB2.iSeries.iDB2CommandBuilder"
+ usePositionalParameters="true"
+ useParameterPrefixInSql="false"
+ useParameterPrefixInParameter="false"
+ parameterPrefix=""
+ allowMARS="false"
+ />
+ <provider
+ name="Informix"
+ description="Informix NET Provider, 2.81.0.0"
+ enabled="false"
+ assemblyName="IBM.Data.Informix, Version=2.81.0.0, Culture=neutral, PublicKeyToken=7c307b91aa13d208"
+ connectionClass="IBM.Data.Informix.IfxConnection"
+ commandClass="IBM.Data.Informix.IfxCommand"
+ parameterClass="IBM.Data.Informix.IfxParameter"
+ parameterDbTypeClass="IBM.Data.Informix.IfxType"
+ parameterDbTypeProperty="IfxType"
+ dataAdapterClass="IBM.Data.Informix.IfxDataAdapter"
+ commandBuilderClass="IBM.Data.Informix.IfxCommandBuilder"
+ usePositionalParameters = "true"
+ useParameterPrefixInSql = "false"
+ useParameterPrefixInParameter = "false"
+ useDeriveParameters="false"
+ allowMARS="false"
+ />
+</providers>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/sqlmap.config b/struts-sandbox/overdrive/PhoneBook2/projects/Web/sqlmap.config
new file mode 100644
index 0000000..fa86239
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/sqlmap.config
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" >
+
+ <properties resource="sqlmap.config.xml"/>
+
+ <settings>
+ <setting useStatementNamespaces="false"/>
+ <setting cacheModelsEnabled="true"/>
+ </settings>
+
+ <database>
+ <provider name="${provider}"/>
+ <dataSource name="default" connectionString="${development}"/>
+ </database>
+
+ <sqlMaps>
+ <sqlMap resource="${root}Resources/Queries.xml"/>
+ </sqlMaps>
+
+</sqlMapConfig>
diff --git a/struts-sandbox/overdrive/PhoneBook2/projects/Web/sqlmap.config.xml b/struts-sandbox/overdrive/PhoneBook2/projects/Web/sqlmap.config.xml
new file mode 100644
index 0000000..06d49e4
--- /dev/null
+++ b/struts-sandbox/overdrive/PhoneBook2/projects/Web/sqlmap.config.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<settings>
+ <add key="root" value="./" />
+ <add key="provider" value="MySql" />
+ <add key="development" value="Host=clifford;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+ <add key="production" value="Host=zippy;Database=phonebook;Username=phonebookApp;Password=p1nH34d" />
+</settings>
diff --git a/struts-sandbox/overdrive/README.txt b/struts-sandbox/overdrive/README.txt
new file mode 100644
index 0000000..cb1d7e5
--- /dev/null
+++ b/struts-sandbox/overdrive/README.txt
@@ -0,0 +1,174 @@
+About OverDrive
+
+OverDrive is a working whiteboard proposal for a new Struts subproject.
+The subproject will feature a set of best-practice applications written
+using a MVC framework that merges Struts with the Commons Chain of
+Responsiblity package.
+
+----
+
+Applications rule, frameworks drool.
+
+Most application frameworks ship with one or more example applications.
+Struts has MailReader. iBATIS has Petstore. JSF has CarDemo. ASP.NET
+distributes several "starter kits". Some frameworks, like Spring, even
+consider the examples to be "first-class citizens".
+
+From the OverDrive perspective, the applications are not just first-class
+citizens, they are the only first-class citizens. The MVC framework shared
+by the applications is simply a means to an end.
+
+OverDrive is about writing business applications, regardless of platform,
+and extracting components the applications can share. The initial OverDrive
+applications are being written for ASP.NET/Mono, but versions for Java5 and
+PHP5 are expected.
+
+The first two applications on the billet are
+
+ * PhoneBook – A single-table employee directory.
+ * MailReader – A multi-table account listing.
+
+Once these ship, others will follow, including
+
+ * Examples – A coding reference to document common strategies.
+ * Wicker - A shopping cart application.
+ * Gavel - An online b2c auction application.
+
+The MVC Framework behind the OverDrive applications bundles two major components:
+
+ * Agility, a C# port of Commons Chain of Responsibility.
+ * Nexus, an application controller built over Agility.
+
+----
+
+Installing a development copy of OverDrive
+
+
+SUBVERSION
+
+* Use Subversion to checkout OverDrive from the
+ [Apache repository|http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/overdrive/].
+
+* If you are using [TortoiseSVN|http://tortoisesvn.tigris.org/] (recommended)
+** Create a likely subdirectory (e.g. /projects/Struts/OverDrive)
+** Right-click on the sudirectory and select Checkout
+** Enter the URL: [https://svn.apache.org/repos/asf/struts/sandbox/trunk/overdrive]
+*** Be sure the destination path is set to the folder you created!
+
+* After the checkout:
+** [Download the external dependencies|
+ http://opensource2.atlassian.com/confluence/oss/download/attachments/442/overdrive-local-cache.zip]
+ (local-cache) to the same directory.
+** Unzip this archive to the same directory, to create the folder local-cache
+ with several subfolders.
+*** local-cache
+**** Agility
+**** iBatisNet
+**** NUnitAsp
+**** Nexus
+**** SpringNet
+** This archive may contain development versions of some products,
+ so be sure to use these rather than the released assemblies.
+ Our goal is to stay current with the development versions for now.
+** If you have not already done so, also install NUnit 2.2 or later.
+ There is a MSI available from [http://NUnit.org], along with a Mono-friendly ZIP.
+
+----
+
+See also
+* [VStudio Readme]
+* [Database Readme]
+
+
+VISUAL STUDIO
+
+h2. NUnit
+
+* To run the NUnit Tests (v2.2)
+** Configure the Test project to run NUnit
+*** Right Click on "Tests", select "Properties"
+*** Open "Configuration Properties"
+*** Open "Debugging"
+*** Change "Debug Mode" to "Program"
+*** Press Apply
+*** For "Start Application", browse to your instance of "nunit-gui.exe".
+
+* We recommend using the TestDriven.Net plugin rather than the NUnit GUI.
+** [http://www.testdriven.net/]
+
+h2. Agility
+
+* Build Agility first
+
+h2. Nexus
+
+* The Nexus solution has a web project. To allow running the project in-place:
+** Right-click on the "Nexus/Web" folder
+** Open "Sharing" and "Security/Web Sharing"
+** Set the sharename to "Nexus"
+* Build Agility before building Nexus
+
+h2. PhoneBook
+
+* The PhoneBook solution has a web project. To allow running the project in-place:
+** Right-click on the "PhoneBook/Web" folder
+** Open "Sharing" and "Security/Web" Sharing
+** Set the sharename to "Phonebook"
+* Build Nexus (and Agility) before building PhoneBook
+
+h2. Subversion
+
+* We recommend using the Ankh plugin for Subversion.
+** [http://ankhsvn.tigris.org/]
+
+----
+
+See also
+
+* [Subversion Readme]
+* [Database Readme]
+
+
+DATABASE
+
+* Right now, the PhoneBook application is using a MySQL 4.0 database by default.
+** We mean to change the default that to [SharpHSQL|
+ http://www.c-sharpcorner.com/database/SharpHSQL.asp] Real Soon Now,
+ and make it easy to switch between various database systems.
+** But for now, you will need [MySQL 4.0|
+ ftp://mirror.mcs.anl.gov/pub/mysql/Downloads/MySQL-4.0/] installed.
+ Then, all you need to do is execute the {{Phonebook-Start.sql}} script
+
+{code:sql}
+CREATE DATABASE `phonebook`;
+USE `phonebook`;
+CREATE TABLE `entry` (
+ `pk_entry` char(36) NOT NULL default '',
+ `last_name` char(18) NOT NULL default '',
+ `first_name` char(18) NOT NULL default '',
+ `extension` char(18) NOT NULL default '',
+ `user_name` char(9) NOT NULL default '',
+ `editor` tinyint(3) unsigned NOT NULL default '0',
+ `hired` datetime NOT NULL default '0000-00-00 00:00:00',
+ `hours` double NOT NULL default '37.5'
+) TYPE=MyISAM ROW_FORMAT=FIXED;
+INSERT INTO `entry` (`pk_entry`,`last_name`,`first_name`,`extension`,`user_name`,`editor`,`hired`,`hours`) VALUES
+ ('c5b6bbb1-66d6-49cb-9db6-743af6627828','Clinton','William','5557437828','bubba',0,'1992-08-19 00:00:00',37.5),
+ ('7c424227-8e19-4fb5-b089-423cfca723e1','Roosevelt','Theodore','5557438942','bull',0,'2001-09-14 00:00:00',37.5),
+ ('9320ea40-0c01-43e8-9cec-8fb9b3928c2c','Kennedy','John F.','5557433928','fitz',0,'1987-05-29 00:00:00',37.5),
+ ('3b27c933-c1dc-4d85-9744-c7d9debae196','Pierce','Franklin','5557437919','hawkeye',0,'1984-11-18 00:00:00',35),
+ ('554ff9e7-a6f5-478a-b76b-a666f5c54e40','Jefferson','Thomas','5557435440','monty',0,'1976-07-04 00:00:00',37.5);
+{code}
+
+----
+
+See also
+
+* [Subversion Readme]
+* [VStudio Readme]
+
+----
+
+For more help, visit http://opensource.atlassian.com/confluence/oss/display/OVR/Home
+
+----
diff --git a/struts-sandbox/pom.xml b/struts-sandbox/pom.xml
new file mode 100755
index 0000000..7bb0e33
--- /dev/null
+++ b/struts-sandbox/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id$
+ */
+-->
+
+<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">
+
+ <parent>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts-master</artifactId>
+ <version>3</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts-sandbox</artifactId>
+ <version>2-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Apache Struts Sandbox</name>
+ <description>Apache Struts Sandbox</description>
+
+ <inceptionYear>2000</inceptionYear>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/struts/sandbox/trunk</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/sandbox/trunk</developerConnection>
+ <url>http://svn.apache.org/viewvc/struts/sandbox/trunk</url>
+ </scm>
+
+ <distributionManagement>
+ <site>
+ <id>apache-site</id>
+ <url>scp://people.apache.org/www/struts.apache.org/struts-sandbox</url>
+ </site>
+ </distributionManagement>
+
+</project>
+
diff --git a/struts-sandbox/scaffold/LICENSE.txt b/struts-sandbox/scaffold/LICENSE.txt
new file mode 100644
index 0000000..dd5b3a5
--- /dev/null
+++ b/struts-sandbox/scaffold/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/struts-sandbox/scaffold/NOTICE.txt b/struts-sandbox/scaffold/NOTICE.txt
new file mode 100644
index 0000000..25a796b
--- /dev/null
+++ b/struts-sandbox/scaffold/NOTICE.txt
@@ -0,0 +1,30 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+--------------------------------------------------------------------------------
+
+Regarding: BaseAction, BaseForm, BaseHelperAction, BaseMapForm, BizAction,
+ProcessAction, ProdcessDispatchAction and ProcessFormAction
+
+Copyright (c) 2002 Synthis Corporation.
+430 10th Street NW, Suite S-108, Atlanta GA 30318, U.S.A.
+All rights reserved.
+
+This software is licensed to you free of charge under
+the Apache Software License, so long as this copyright
+statement, list of conditions, and comments, remains
+in the source code.
+
+This software was written to support code generation
+for the Apache Struts J2EE architecture by Synthis'
+visual application modeling tool Adalon.
+
+For more information on Adalon and Struts code
+generation please visit http://www.synthis.com
+
+--------------------------------------------------------------------------------
+
+"SnoopAction.java" contains code derived from the Jetty SnoopServlet
+http://www.thecortex.net/clover/eg/jetty/report/default-pkg/SnoopServlet.html>
+and distributed under its open source license
+http://jetty.mortbay.org/jetty/LICENSE.html>.
diff --git a/struts-sandbox/scaffold/README.txt b/struts-sandbox/scaffold/README.txt
new file mode 100644
index 0000000..1b93ed1
--- /dev/null
+++ b/struts-sandbox/scaffold/README.txt
@@ -0,0 +1,18 @@
+Scaffold - Web Application Toolkit
+=======================================================================
+
+Scaffold is a toolkit for building web applications. Web application
+frameworks, like Struts, provide the essential infrastructure most
+developers need to create applications. But there are still many
+reusable pieces that most applications need but frameworks don't
+typically provide. Scaffold is a home for classes that can be reused
+between applications but are not sexy enough (or sometimes too sexy)
+for a framework distribution.
+
+The bulk of Scaffold is being provided through the Commons. This
+is a Struts specific package is provided in the Struts source code
+distribution which builds on the classes provided there.
+
+See build.html for requisite JARs.
+
+###
diff --git a/struts-sandbox/scaffold/build.html b/struts-sandbox/scaffold/build.html
new file mode 100644
index 0000000..b41bce0
--- /dev/null
+++ b/struts-sandbox/scaffold/build.html
@@ -0,0 +1,22 @@
+<html>
+<body>
+
+<p>Requisite JARs</p>
+
+<ul>
+<li>commons-digester.jar - <a href="http://jakarta.apache.org/builds/jakarta-commons/release/commons-digester/v1.1.1/">Jakarta Commons Digester</a></li>
+<li>commons-scaffold.jar - <a href="http://www.husted.com/builds/scaffold">Jakarta Commons Scaffold</a></li>
+<li>scaffold-struts.jar - <a href="http://www.husted.com/builds/scaffold">Jakarta Struts Scaffold</a></li>
+<li>struts.jar - <a href="http://jakarta.apache.org/builds/jakarta-struts/release/">Jakarta Struts 1.0.2</a></li>
+<li>struts-validator.jar - <a href="http://www.husted.com/builds/validator">Struts Validator 1.0</a></li>
+</ul>
+
+<p>Also these tld's from the Struts distribution (above) placed in the /WEB-INF/lib folder with the JARs</p>
+<ul>
+<li>struts-bean.tld</li>
+<li>struts-html.tld</li>
+<li>struts-logic.tld</li>
+</ul>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/build.xml b/struts-sandbox/scaffold/build.xml
new file mode 100644
index 0000000..fba5d92
--- /dev/null
+++ b/struts-sandbox/scaffold/build.xml
@@ -0,0 +1,137 @@
+<!--
+@version $Rev$ $Date$
+-->
+
+<project name="scaffold" default="compile.lib">
+
+ <!-- Change this to compile against a different version -->
+ <property name="compile.classpath" value="compile.classpath_1_2"/>
+
+ <!-- Local system paths -->
+ <property name="path.dist" value="./target"/>
+ <property name="path.javasoft" value="/opt/JavaSoft/lib"/>
+ <property name="path.jakarta" value="/opt/jakarta"/>
+ <property name="path.sf" value="/opt/sourceforge"/>
+ <property name="path.struts" value="/opt/struts/jakarta-struts-1.2.4-lib"/>
+
+ <!-- Project settings -->
+ <property name="project.title" value="scaffold"/>
+ <property name="project.version" value="0.6"/>
+ <property name="project.distname" value="struts-scaffold_1_2"/>
+
+ <!-- Standard Javasoft jars -->
+ <property name="servlet.jar" value="${path.javasoft}/servletapi_2_3.jar"/>
+ <property name="jdbc20ext.jar" value="${path.javasoft}/jdbc2_0-stdext.jar"/>
+
+ <!-- Path settings -->
+ <property name="doc.path" value="./doc/api"/>
+ <property name="doc.src" value="./src/java"/>
+
+ <!-- Build working classpath -->
+ <path id="compile.classpath_1_2">
+ <pathelement path ="${path.jakarta}/lucene-1.4.3.jar"/>
+ <pathelement path ="${path.sf}/poolman-2-0-4/lib/poolman.jar"/>
+ <pathelement path ="${path.struts}/commons-beanutils.jar"/>
+ <pathelement path ="${path.struts}/commons-digester.jar"/>
+ <pathelement path ="${path.jakarta}/commons-scaffold.jar"/>
+ <pathelement path ="${path.jakarta}/commons-resources.jar"/>
+ <pathelement path ="${path.struts}/struts.jar"/>
+ <pathelement path ="classes"/>
+ <pathelement path ="${classpath}"/>
+ </path>
+
+ <!-- Check timestamp on files -->
+ <target name="prepare">
+ <tstamp>
+ <format property="year" pattern="yyyy"/>
+ </tstamp>
+ </target>
+
+ <!-- Copy any resource or configuration files -->
+ <target name="resources">
+ <copy todir="classes" includeEmptyDirs="no">
+ <fileset dir="src/java">
+ <patternset>
+ <include name="**/*.conf"/>
+ <include name="**/*.properties"/>
+ <include name="**/*.xml"/>
+ </patternset>
+ </fileset>
+ </copy>
+ </target>
+
+ <!-- Normal build of application -->
+ <target name="compile" depends="prepare,resources">
+ <copy
+ file="./LICENSE.txt"
+ todir="classes"/>
+ <!-- Remove "jikes" value if you must use javac instead -->
+ <!-- property name="build.compiler" value="jikes"/ -->
+ <javac srcdir="src" destdir="classes">
+ <classpath path="${servlet.jar}:${jdbc20ext.jar}" />
+ <classpath refid="${compile.classpath}"/>
+ </javac>
+ </target>
+
+ <!-- Remove classes directory for clean build -->
+ <target name="clean"
+ description="Prepare for clean build">
+ <delete dir="classes"/>
+ <mkdir dir="classes"/>
+ </target>
+
+ <!-- Build Javadoc documentation -->
+ <target name="javadoc"
+ description="Generate JavaDoc API docs">
+ <delete dir="./doc/api"/>
+ <mkdir dir="./doc/api"/>
+ <javadoc sourcepath="./src/java"
+ destdir="./doc/api"
+ classpath="${servlet.jar}:${jdbc20ext.jar}"
+ packagenames="org.*"
+ author="false"
+ private="true"
+ version="true"
+ windowtitle="${project.title} API Documentation"
+ doctitle="<h1>${project.title} API Documentation (Version ${project.version})</h1>"
+ bottom="Copyright © 2001-${year} - Apache Software Foundation">
+ <classpath refid="${compile.classpath}"/>
+ </javadoc>
+ </target>
+
+ <!-- Build binary distribution -->
+ <target name="compile.lib"
+ depends="compile"
+ description="Create binary distribution">
+
+ <mkdir
+ dir="${path.dist}"/>
+
+ <jar
+ jarfile="${path.dist}/${project.distname}.jar"
+ basedir="./classes"/>
+
+ </target>
+
+ <!-- Build distribution -->
+ <target name="dist"
+ description="Create distribution">
+
+ <mkdir
+ dir="${path.dist}"/>
+
+ <zip zipfile="${path.dist}/${project.distname}.zip">
+ <zipfileset dir="." prefix="struts-scaffold"/>
+ </zip>
+
+ <jar
+ jarfile="${path.dist}/${project.distname}.jar"
+ basedir="./classes"/>
+
+ </target>
+
+
+ <!-- Build entire project -->
+ <target name="project" depends="clean,prepare,compile,javadoc,dist"/>
+
+</project>
diff --git a/struts-sandbox/scaffold/conf/framework/manifest b/struts-sandbox/scaffold/conf/framework/manifest
new file mode 100644
index 0000000..30a48dd
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/framework/manifest
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Created-By: Ant
+
+Name: @project.name.file@/
+Specification-Title: @project.name.text@
+Specification-Vendor: The Apache Software Foundation
+Implementation-Vendor: The Apache Software Foundation
+Specification-Version: @version@
+Implementation-Version: @version@
+Implementation-Title: @project.name.file@
diff --git a/struts-sandbox/scaffold/conf/sample/ApplicationResources.properties b/struts-sandbox/scaffold/conf/sample/ApplicationResources.properties
new file mode 100644
index 0000000..1189a5e
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/sample/ApplicationResources.properties
@@ -0,0 +1,5 @@
+index.title=Scaffold Sample Application
+index.heading=Hello World!
+index.message=This is a sample application that does not do much but it shows
+how to package a Scaffold application and also serves as an integration test
+bed for Scaffold.
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/conf/sample/manifest b/struts-sandbox/scaffold/conf/sample/manifest
new file mode 100644
index 0000000..1c27b81
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/sample/manifest
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Created-By: Ant
+
+Name: @project.name.file@/sample
+Specification-Title: @project.name.text@ Sample
+Specification-Vendor: The Apache Software Foundation
+Implementation-Vendor: The Apache Software Foundation
+Specification-Version: @version@
+Implementation-Version: @version@
+Implementation-Title: @project.name.file@-sample
diff --git a/struts-sandbox/scaffold/conf/sample/struts-config.xml b/struts-sandbox/scaffold/conf/sample/struts-config.xml
new file mode 100644
index 0000000..813aef9
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/sample/struts-config.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
+ "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
+
+<!--
+ This is a blank Struts configuration file based on the example application,
+ with commented examples of some items.
+
+ NOTE: If you have a generator tool to create the corresponding Java classes
+ for you, you could include the details in the "form-bean" declarations.
+ Otherwise, you would only define the "form-bean" element itself, with the
+ corresponding "name" and "type" attributes, as shown here.
+-->
+
+
+<struts-config>
+
+
+ <!-- ========== Data Source Configuration =============================== -->
+<!--
+ <data-sources>
+ <data-source
+ autoCommit="false"
+ description="Example Data Source Configuration"
+ driverClass="org.postgresql.Driver"
+ maxCount="4"
+ minCount="2"
+ password="mypassword"
+ url="jdbc:postgresql://localhost/mydatabase"
+ user="myusername"
+ />
+ </data-sources>
+-->
+
+ <!-- ========== Form Bean Definitions =================================== -->
+ <form-beans>
+
+ <!-- Example logon form bean
+ <form-bean name="logonForm"
+ type="org.apache.struts.example.LogonForm"/>
+ -->
+
+ </form-beans>
+
+
+ <!-- ========== Global Forward Definitions ============================== -->
+ <global-forwards>
+
+ <!-- Example logon forward
+ <forward name="logon" path="/logon.jsp"/>
+ -->
+
+ </global-forwards>
+
+
+ <!-- ========== Action Mapping Definitions ============================== -->
+ <action-mappings>
+
+ <!-- Example logon action
+ <action path="/logon"
+ type="org.apache.struts.example.LogonAction"
+ name="logonForm"
+ scope="request"
+ input="/logon.jsp">
+ </action>
+ -->
+
+ <!-- Example logoff action
+ <action path="/logoff"
+ type="org.apache.struts.example.LogoffAction">
+ <forward name="success" path="/index.jsp"/>
+ </action>
+ -->
+
+
+ <!-- The standard administrative actions available with Struts -->
+ <!-- These would be either omitted or protected by security -->
+ <!-- in a real application deployment -->
+ <action path="/admin/addFormBean"
+ type="org.apache.struts.actions.AddFormBeanAction"/>
+ <action path="/admin/addForward"
+ type="org.apache.struts.actions.AddForwardAction"/>
+ <action path="/admin/addMapping"
+ type="org.apache.struts.actions.AddMappingAction"/>
+ <action path="/admin/reload"
+ type="org.apache.struts.actions.ReloadAction"/>
+ <action path="/admin/removeFormBean"
+ type="org.apache.struts.actions.RemoveFormBeanAction"/>
+ <action path="/admin/removeForward"
+ type="org.apache.struts.actions.RemoveForwardAction"/>
+ <action path="/admin/removeMapping"
+ type="org.apache.struts.actions.RemoveMappingAction"/>
+
+
+ </action-mappings>
+
+</struts-config>
diff --git a/struts-sandbox/scaffold/conf/sample/test/cactus.properties b/struts-sandbox/scaffold/conf/sample/test/cactus.properties
new file mode 100644
index 0000000..f5c4cbd
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/sample/test/cactus.properties
@@ -0,0 +1,12 @@
+# Configuration file for Cactus.
+
+# Each project using Cactus need to have such a file put in the client side
+# CLASSPATH (Meaning the directory containgin this file should be in the client
+# side CLASSPATH, not the file itself of course ... :) )
+
+# Defines the URLs that will be used by Cactus to call it's redirectors.
+# You need to specify in these URLs the webapp context that you use for your
+# application. In the example below, the context is "test".
+
+# Servlet Redirector. Used by ServletTestCase test cases.
+cactus.servletRedirectorURL = http://localhost:@test.port@/@project.name.file@-sample/ServletRedirector
diff --git a/struts-sandbox/scaffold/conf/sample/test/tomcat40/server.xml b/struts-sandbox/scaffold/conf/sample/test/tomcat40/server.xml
new file mode 100644
index 0000000..e4a643d
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/sample/test/tomcat40/server.xml
@@ -0,0 +1,21 @@
+<Server port="8005" shutdown="SHUTDOWN" debug="0">
+
+ <Service name="Tomcat-Standalone">
+
+ <Connector className="org.apache.catalina.connector.http.HttpConnector"
+ port="@test.port@" minProcessors="5" maxProcessors="75"
+ acceptCount="10" debug="0"/>
+
+ <Engine name="Standalone" defaultHost="localhost" debug="0">
+
+ <Realm className="org.apache.catalina.realm.MemoryRealm" />
+
+ <Host name="localhost" debug="0"
+ appBase="@target.tomcat40.full.dir@/webapps">
+ </Host>
+
+ </Engine>
+
+ </Service>
+
+</Server>
diff --git a/struts-sandbox/scaffold/conf/sample/test/tomcat40/web.xml b/struts-sandbox/scaffold/conf/sample/test/tomcat40/web.xml
new file mode 100644
index 0000000..117e1d7
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/sample/test/tomcat40/web.xml
@@ -0,0 +1,706 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
+
+<web-app>
+
+ <!-- Mappings in this file are the defaults for all Contexts -->
+
+ <!-- The default servlet that serves static resources -->
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>listings</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <!-- The invoker servlet that executes non-registered servlets -->
+ <servlet>
+ <servlet-name>invoker</servlet-name>
+ <servlet-class>org.apache.catalina.servlets.InvokerServlet</servlet-class>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <!-- The JSP page compiler and execution servlet -->
+ <servlet>
+ <servlet-name>jsp</servlet-name>
+ <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+ <!-- Uncomment the following to use Jikes for JSP compilation -->
+<!--
+ <init-param>
+ <param-name>jspCompilerPlugin</param-name>
+ <param-value>org.apache.jasper.compiler.JikesJavaCompiler</param-value>
+ </init-param>
+-->
+ <init-param>
+ <!-- An alternate java encoding -->
+ <param-name>javaEncoding</param-name>
+ <param-value>UTF-8</param-value>
+ </init-param>
+ <init-param>
+ <!-- Levels: FATAL ERROR WARNING INFORMATION DEBUG -->
+ <param-name>logVerbosityLevel</param-name>
+ <param-value>WARNING</param-value>
+ </init-param>
+ <load-on-startup>4</load-on-startup>
+ </servlet>
+
+ <!-- SSIInvoker Servlet -->
+ <servlet>
+ <servlet-name>ssi</servlet-name>
+ <servlet-class>org.apache.catalina.servlets.SsiInvokerServlet</servlet-class>
+ <init-param>
+ <!-- debug > 0 == debug enabled -->
+ <param-name>debug</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <!-- time in seconds before the SSI page expires -->
+ <param-name>expires</param-name>
+ <param-value>666</param-value>
+ </init-param>
+ <init-param>
+ <!-- 0 == false; 1 == true -->
+ <param-name>buffered</param-name>
+ <param-value>1</param-value>
+ </init-param>
+ <init-param>
+ <!-- 0 == false; 1 == true -->
+ <param-name>isVirtualWebappRelative</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <load-on-startup>5</load-on-startup>
+ </servlet>
+
+ <!-- CGIServlet -->
+ <servlet>
+ <servlet-name>cgi</servlet-name>
+ <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
+ <init-param>
+ <!-- debug > 0 == debug enabled -->
+ <param-name>debug</param-name>
+ <param-value>6</param-value>
+ </init-param>
+ <init-param>
+ <!-- clientInputTimeout is the time in milliseconds to wait for-->
+ <!-- input from the client browser before assuming there is none -->
+ <param-name>clientInputTimeout</param-name>
+ <param-value>100</param-value>
+ </init-param>
+ <init-param>
+ <!-- The CGI search path will start at -->
+ <!-- webAppRootDir + File.separator + cgiPathPrefix -->
+ <param-name>cgiPathPrefix</param-name>
+ <param-value>WEB-INF/cgi</param-value>
+ </init-param>
+ <load-on-startup>6</load-on-startup>
+ </servlet>
+
+ <!-- The mapping for the default servlet -->
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/</url-pattern>
+ </servlet-mapping>
+
+ <!-- The mapping for the invoker servlet -->
+ <!-- Comment this out if you do not want "invoker" service -->
+ <servlet-mapping>
+ <servlet-name>invoker</servlet-name>
+ <url-pattern>/servlet/*</url-pattern>
+ </servlet-mapping>
+
+ <!-- The mapping for the JSP servlet -->
+ <!-- Comment this out if you do not want "jsp" service -->
+ <servlet-mapping>
+ <servlet-name>jsp</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ </servlet-mapping>
+
+ <!-- The mapping for SSI-->
+ <servlet-mapping>
+ <servlet-name>ssi</servlet-name>
+ <url-pattern>*.shtml</url-pattern>
+ </servlet-mapping>
+
+ <!-- The mapping for the CGI Gateway servlet -->
+ <!-- Comment this out if you do not want "CGI Gateway" service -->
+ <servlet-mapping>
+ <servlet-name>cgi</servlet-name>
+ <url-pattern>/cgi-bin/*</url-pattern>
+ </servlet-mapping>
+
+ <!-- Set the default session timeout (in seconds) -->
+ <session-config>
+ <session-timeout>30</session-timeout>
+ </session-config>
+
+ <!-- Establish the default MIME type mappings -->
+ <mime-mapping>
+ <extension>txt</extension>
+ <mime-type>text/plain</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>html</extension>
+ <mime-type>text/html</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>htm</extension>
+ <mime-type>text/html</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>gif</extension>
+ <mime-type>image/gif</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jpg</extension>
+ <mime-type>image/jpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jpe</extension>
+ <mime-type>image/jpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jpeg</extension>
+ <mime-type>image/jpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>java</extension>
+ <mime-type>text/plain</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>body</extension>
+ <mime-type>text/html</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rtx</extension>
+ <mime-type>text/richtext</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tsv</extension>
+ <mime-type>text/tab-separated-values</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>etx</extension>
+ <mime-type>text/x-setext</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ps</extension>
+ <mime-type>application/x-postscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>class</extension>
+ <mime-type>application/java</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>csh</extension>
+ <mime-type>application/x-csh</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>sh</extension>
+ <mime-type>application/x-sh</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tcl</extension>
+ <mime-type>application/x-tcl</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tex</extension>
+ <mime-type>application/x-tex</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>texinfo</extension>
+ <mime-type>application/x-texinfo</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>texi</extension>
+ <mime-type>application/x-texinfo</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>t</extension>
+ <mime-type>application/x-troff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tr</extension>
+ <mime-type>application/x-troff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>roff</extension>
+ <mime-type>application/x-troff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>man</extension>
+ <mime-type>application/x-troff-man</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>me</extension>
+ <mime-type>application/x-troff-me</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ms</extension>
+ <mime-type>application/x-wais-source</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>src</extension>
+ <mime-type>application/x-wais-source</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>zip</extension>
+ <mime-type>application/zip</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>bcpio</extension>
+ <mime-type>application/x-bcpio</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>cpio</extension>
+ <mime-type>application/x-cpio</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>gtar</extension>
+ <mime-type>application/x-gtar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>shar</extension>
+ <mime-type>application/x-shar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>sv4cpio</extension>
+ <mime-type>application/x-sv4cpio</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>sv4crc</extension>
+ <mime-type>application/x-sv4crc</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tar</extension>
+ <mime-type>application/x-tar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ustar</extension>
+ <mime-type>application/x-ustar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dvi</extension>
+ <mime-type>application/x-dvi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>hdf</extension>
+ <mime-type>application/x-hdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>latex</extension>
+ <mime-type>application/x-latex</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>bin</extension>
+ <mime-type>application/octet-stream</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>oda</extension>
+ <mime-type>application/oda</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pdf</extension>
+ <mime-type>application/pdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ps</extension>
+ <mime-type>application/postscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>eps</extension>
+ <mime-type>application/postscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ai</extension>
+ <mime-type>application/postscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rtf</extension>
+ <mime-type>application/rtf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>nc</extension>
+ <mime-type>application/x-netcdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>cdf</extension>
+ <mime-type>application/x-netcdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>cer</extension>
+ <mime-type>application/x-x509-ca-cert</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>exe</extension>
+ <mime-type>application/octet-stream</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>gz</extension>
+ <mime-type>application/x-gzip</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>Z</extension>
+ <mime-type>application/x-compress</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>z</extension>
+ <mime-type>application/x-compress</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>hqx</extension>
+ <mime-type>application/mac-binhex40</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mif</extension>
+ <mime-type>application/x-mif</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ief</extension>
+ <mime-type>image/ief</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tiff</extension>
+ <mime-type>image/tiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tif</extension>
+ <mime-type>image/tiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ras</extension>
+ <mime-type>image/x-cmu-raster</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pnm</extension>
+ <mime-type>image/x-portable-anymap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pbm</extension>
+ <mime-type>image/x-portable-bitmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pgm</extension>
+ <mime-type>image/x-portable-graymap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ppm</extension>
+ <mime-type>image/x-portable-pixmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rgb</extension>
+ <mime-type>image/x-rgb</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xbm</extension>
+ <mime-type>image/x-xbitmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xpm</extension>
+ <mime-type>image/x-xpixmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xwd</extension>
+ <mime-type>image/x-xwindowdump</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>au</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>snd</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aif</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aiff</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aifc</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>wav</extension>
+ <mime-type>audio/x-wav</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpeg</extension>
+ <mime-type>video/mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpg</extension>
+ <mime-type>video/mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpe</extension>
+ <mime-type>video/mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>qt</extension>
+ <mime-type>video/quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mov</extension>
+ <mime-type>video/quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>qt</extension>
+ <mime-type>video/quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>avi</extension>
+ <mime-type>video/x-msvideo</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>movie</extension>
+ <mime-type>video/x-sgi-movie</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>avx</extension>
+ <mime-type>video/x-rad-screenplay</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>wrl</extension>
+ <mime-type>x-world/x-vrml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpv2</extension>
+ <mime-type>video/mpeg2</mime-type>
+ </mime-mapping>
+ <mime-mapping> <!-- WML Source -->
+ <extension>wml</extension>
+ <mime-type>text/vnd.wap.wml</mime-type>
+ </mime-mapping>
+ <mime-mapping> <!-- Compiled WML -->
+ <extension>wmlc</extension>
+ <mime-type>application/vnd.wap.wmlc</mime-type>
+ </mime-mapping>
+ <mime-mapping> <!-- WML Script Source -->
+ <extension>wmls</extension>
+ <mime-type>text/vnd.wap.wmls</mime-type>
+ </mime-mapping>
+ <mime-mapping> <!-- Compiled WML Script -->
+ <extension>wmlscriptc</extension>
+ <mime-type>application/vnd.wap.wmlscriptc</mime-type>
+ </mime-mapping>
+ <mime-mapping> <!-- Wireless Bitmap -->
+ <extension>wbmp</extension>
+ <mime-type>image/vnd.wap.wbmp</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mp2</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mp3</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mp1</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpa</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>abs</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpega</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>midi</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mid</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>smf</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>kar</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aiff</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aif</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aifc</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aim</extension>
+ <mime-type>application/x-aim</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>art</extension>
+ <mime-type>image/x-jg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>au</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>snd</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ulw</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>bmp</extension>
+ <mime-type>image/bmp</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dib</extension>
+ <mime-type>image/bmp</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>cdf</extension>
+ <mime-type>application/x-cdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dv</extension>
+ <mime-type>video/x-dv</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>m3u</extension>
+ <mime-type>audio/x-mpegurl</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jar</extension>
+ <mime-type>application/java-archive</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>hqx</extension>
+ <mime-type>application/mac-binhex40</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pnt</extension>
+ <mime-type>image/x-macpaint</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mac</extension>
+ <mime-type>image/x-macpaint</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>asf</extension>
+ <mime-type>video/x-ms-asf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>asx</extension>
+ <mime-type>video/x-ms-asf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>doc</extension>
+ <mime-type>application/msword</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rm</extension>
+ <mime-type>application/vnd.rn-realmedia</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>psd</extension>
+ <mime-type>image/x-photoshop</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pic</extension>
+ <mime-type>image/pict</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pict</extension>
+ <mime-type>image/pict</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pct</extension>
+ <mime-type>image/pict</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pls</extension>
+ <mime-type>audio/x-scpls</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>png</extension>
+ <mime-type>image/png</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>qti</extension>
+ <mime-type>image/x-quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>qtif</extension>
+ <mime-type>image/x-quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>swf</extension>
+ <mime-type>application/x-shockwave-flash</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dtd</extension>
+ <mime-type>text/plain</mime-type>
+ </mime-mapping>
+
+ <!-- Establish the default list of welcome files -->
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ <welcome-file>index.htm</welcome-file>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <!-- ================ Security Constraints for Testing =============== -->
+
+<!--
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>The Entire Web Application</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>tomcat</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>Tomcat Supported Realm</realm-name>
+ </login-config>
+
+ <security-role>
+ <description>
+ An example role defined in "conf/tomcat-users.xml"
+ </description>
+ <role-name>tomcat</role-name>
+ </security-role>
+-->
+
+</web-app>
+
diff --git a/struts-sandbox/scaffold/conf/sample/web.xml b/struts-sandbox/scaffold/conf/sample/web.xml
new file mode 100644
index 0000000..63985f3
--- /dev/null
+++ b/struts-sandbox/scaffold/conf/sample/web.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
+ "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
+
+<web-app>
+
+
+ <!-- Standard Action Servlet Configuration (with debugging) -->
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
+ <init-param>
+ <param-name>application</param-name>
+ <param-value>ApplicationResources</param-value>
+ </init-param>
+ <init-param>
+ <param-name>config</param-name>
+ <param-value>/WEB-INF/struts-config.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>2</param-value>
+ </init-param>
+ <init-param>
+ <param-name>detail</param-name>
+ <param-value>2</param-value>
+ </init-param>
+ <init-param>
+ <param-name>validate</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <!-- This is only needed for Cactus integration unit tests -->
+ <servlet>
+ <servlet-name>ServletRedirector</servlet-name>
+ <servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class>
+ </servlet>
+
+ <!-- Standard Action Servlet Mapping -->
+ <servlet-mapping>
+ <servlet-name>action</servlet-name>
+ <url-pattern>/do/*</url-pattern>
+ </servlet-mapping>
+
+ <!-- This is only needed for Cactus integration unit tests -->
+ <servlet-mapping>
+ <servlet-name>ServletRedirector</servlet-name>
+ <url-pattern>/ServletRedirector</url-pattern>
+ </servlet-mapping>
+
+ <!-- The Usual Welcome File List -->
+ <welcome-file-list>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <!-- Struts Tag Library Descriptors -->
+ <taglib>
+ <taglib-uri>/WEB-INF/struts-bean</taglib-uri>
+ <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
+ </taglib>
+
+ <taglib>
+ <taglib-uri>/WEB-INF/struts-html</taglib-uri>
+ <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
+ </taglib>
+
+ <taglib>
+ <taglib-uri>/WEB-INF/struts-logic</taglib-uri>
+ <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
+ </taglib>
+
+</web-app>
diff --git a/struts-sandbox/scaffold/rss/ParseRss.java b/struts-sandbox/scaffold/rss/ParseRss.java
new file mode 100644
index 0000000..1dc2a3e
--- /dev/null
+++ b/struts-sandbox/scaffold/rss/ParseRss.java
@@ -0,0 +1,93 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold.rss;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.digester.rss.RSSDigester;
+import org.apache.commons.digester.rss.Channel;
+import org.apache.commons.scaffold.lang.Tokens;
+
+import org.apache.struts.action.ActionError;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionServlet;
+
+import org.apache.struts.scaffold.BaseAction;
+
+
+/**
+ * Read and parse RSS file found at a given
+ * path, save the Channel bean in request scope,
+ * and forward to "success".
+ *
+ * @author Ted Husted
+ * @version $Rev$ $Date$
+ */
+public final class ParseRss extends BaseAction {
+
+ // --------------------------------------------------------- Instances Variables
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Request attribute key for saving Channel bean ["CHANNEL"].
+ */
+ public static final String CHANNEL_KEY = "CHANNEL";
+
+
+ /**
+ * Read and parse RSS file found at a given
+ * path, save the Channel bean in request scope,
+ * and forward to "success".
+ *
+ * @expects path={uri} on command line or as parameter property to ActionMapping.
+ * @expects an input page or error forwarding if exception digesting RSS
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ * @param errors Our ActionErrors collection
+ */
+ public void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ Channel channel = null;
+
+ String path = request.getParameter(Tokens.PATH);
+ if (path==null) path = mapping.getParameter();
+
+ RSSDigester digester = new RSSDigester();
+ channel = (Channel) digester.parse(path);
+
+ request.setAttribute(CHANNEL_KEY,channel);
+
+ } // end executeLogic()
+
+} // end ParseRss
diff --git a/struts-sandbox/scaffold/rss/RenderRss.java b/struts-sandbox/scaffold/rss/RenderRss.java
new file mode 100644
index 0000000..e4951a6
--- /dev/null
+++ b/struts-sandbox/scaffold/rss/RenderRss.java
@@ -0,0 +1,141 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold.rss;
+
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.sql.SQLException;
+import java.util.Iterator;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.digester.rss.Channel;
+import org.apache.commons.digester.rss.Item;
+
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.util.ResultList;
+
+import org.apache.struts.action.ActionError;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionServlet;
+
+import org.apache.struts.scaffold.BaseAction;
+
+
+/**
+ * Convert result bean to channel and render as response.
+ *
+ * @author Ted Husted
+ * @version $Rev$ $Date$
+ */
+public final class RenderRss extends BaseAction {
+
+// ------------------------------------------------- Instance Variables
+// ----------------------------------------------------- Public Methods
+
+
+ /**
+ (* // :FIXME: Hasn't been tested.
+ * Retrieves a Digester Channel bean from request context and
+ * renders it.
+ * <p>
+ * Channel bean must be stored under the attribute
+ * ParseRss.CHANNEL_KEY or under an attribute given as the
+ * parameter property.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ * @fixme Use ActionForwards for links instead of properties
+ */
+ public void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ ActionErrors errors = new ActionErrors();
+ Channel channel = null;
+
+ try {
+ channel = (Channel)
+ request.getAttribute(ParseRss.CHANNEL_KEY);
+ }
+ catch (Throwable t) {
+ channel = null;
+ }
+
+ if (null==channel) {
+ try {
+ channel = (Channel)
+ request.getAttribute(mapping.getParameter());
+ }
+ catch (Throwable t) {
+ channel = null;
+ }
+ }
+
+ if (null==channel) {
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.PROCESS_MISSING_PARAMETER));
+ }
+
+ if (errors.empty()) {
+ response.setContentType(Tokens.TEXT_PLAIN);
+ channel.render(response.getWriter());
+ }
+
+ else {
+ // This will trigger findFailure() in the BaseAction
+ saveErrors(request,errors);
+ }
+
+ } // end executeLogic()
+
+
+ /**
+ * Return null to the controller, indicating that the
+ * response has been rendered.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ * @param errors Our ActionErrors collection
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ return null;
+
+ } // end findSucess()
+
+} // end RenderRss
diff --git a/struts-sandbox/scaffold/src/STATUS.txt b/struts-sandbox/scaffold/src/STATUS.txt
new file mode 100644
index 0000000..17e2d1a
--- /dev/null
+++ b/struts-sandbox/scaffold/src/STATUS.txt
@@ -0,0 +1,105 @@
+
+[SCAFFOLD]
+=======================================================================
+[Ordering is LIFO. Last thing done for a day is the first item listed.]
+
+
+*** WARNING - PACKAGE IS UNDERGOING AN UPDATE AND *IS NOT STABLE*. ***
+
+
+
+// -------------------------------------------------------------- FIXME
+
+BaseAction - !MUST! provide equivalent of
+ActionFormBean formBean = servlet.findFormBean(helperName);
+BizFormImple - Ditto.
+
+RemoveAttributeAction - Needs to be tested.
+
+// ---------------------------------------------------------------- TODO
+
+- BizAction - Resolve message handling with latest Commons Resources
+- BizForm++ - Update for latest releases
+
+- ProcessDispatchAction: Refactor with ProcessAction so there is not
+so much duplicate code here
+- BaseForm: Change from BeanUtil.populate to copyProperties
+- ExistsAttributeAction: Add support for multiple attributes
+- ProcessFormAction: Change from BeanUtil.populate to copyProperties
+- RemoveAttributeAction: Add support for multiple attributes
+
+// ------------------------------------------------------------ CHANGES
+
+[2004-12-28]
++ BaseAction: Extend from DynaValidatorForm
++ *: Remove obsolete logging statements
++ *: Move to Global.* constants
++ Began updating code for latest releases.
++ Updated build for latest releases.
+
+[2002-11-11]
++ BaseAction: Extend from ValidatorForm again.
++ ParameterAction: Amend JavaDocs.
+
+[2002-10-29]
++ ProcessDispatchAction: Resolve problem in Scroller/ScrollBeanBase;
+helper methods needed to be named UNlike properties to keep from
+confusing BeanUtils.
++ ProcessDispatchAction: Change to bypass ProcessFormAction. Now works.
++ ProcessDispatchAction: Now causing a reflection error when used.
+
+
+24-OCT-2002
+-----------
++ ParameterAction: Fix to observer redirect on template froward.
+
+09-OCT-2002
+-----------
++ Add BaseActionMapping
+
+07-OCT-2002
+-----------
++ Add RecreateSessionAction.
++ Add ImageBeanButton
+
+19-SEP-2002
+-----------
++ RemoveAttributeAction: Correct operation.
+
+
+11-SEP-2002
+-----------
++ Replace calls to BeanUtils.populate with copyProperties
++ Migrate to latest commons.beanutil.BeanUtils
+
+
+06-SEP-2002
+-----------
++ ActionForm: Add remoteAddr property (automatic). Add validate
+method that will not return null.
+
+
+21-AUG-2002
+-----------
++ resources.properties: Add process complete message.
++ ProcessDispatchAction: Change to extend ProcessFormAction
+
+
+20-AUG-2002
+-----------
++ ProcessAction: Update to use LIST_KEY
++ ProcessFormAction: Expanded JavaDocs
+
+
+19-AUG-2002
+-----------
++ Resources.properties: Conform with latest Token class.
++ ProcessDispatchAction: Improve exception handling.
++ BaseAction: Update to better handle exceptions with null message.
+
+
+14-AUG-2002
+-----------
++ Initial upload of new version to Struts Contrib.
+
+
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseAction.java
new file mode 100644
index 0000000..617fe34
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseAction.java
@@ -0,0 +1,919 @@
+/*
+// MUST! :FIXME: Need to provide equivalent of
+// ActionFormBean formBean = servlet.findFormBean(helperName);
+*/
+
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.struts.action.*;
+
+import org.apache.struts.Globals;
+
+import org.apache.commons.scaffold.lang.BaseException;
+import org.apache.commons.scaffold.lang.Log;
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.text.ConvertUtils;
+
+
+/**
+ * Enhanced base Action.
+ * See the documentation for the <code>execute</code> method for
+ * operational details.
+ * A <code>perform</code> method is also provided for backwards
+ * compatibility with 1_0.
+ * :TODO: Remove deprecations after formal 1.0 Scaffod release.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BaseAction extends Action {
+
+
+// ---------------------------------------------------------- UTIITIES
+
+
+ /**
+ * Return whether Struts 1.0 compatibility should be used.
+ *
+ * @return True if built for Struts 1.0.x, false otherwise.
+ * @deprecated Will be removed after Struts 1.1 final ships.
+ */
+ private final boolean isStruts_1_0() {
+ return false; // Struts 1.1+
+ }
+
+// ---------------------------------------------------------------- Log
+
+ /**
+ * Is logging set this level or higher?
+ *
+ * @param level The debug level to test
+ */
+ protected boolean isLogLevel(int level) {
+ // FIXME: return servlet.getDebug()>=level);
+ return false;
+ }
+
+
+ /**
+ * Is logging set to debugging?
+ */
+ protected boolean isDebug() {
+ // FIXME: return (servlet.getDebug()>=Log.DEBUG);
+ return false;
+ }
+
+
+ /**
+ * Is logging set to verbose?
+ */
+ protected boolean isVerbose() {
+ // FIXME: return (servlet.getDebug()>=Log.VERBOSE);
+ return false;
+ }
+
+
+// ---------------------------------------------------------- Exception
+
+
+ /**
+ * Set exception to request under public key [Action.EXCEPTION].
+ *
+ * @param request The HTTP request we are processing
+ * @param e The new Exception
+ */
+ protected void setException(
+ HttpServletRequest request,
+ Exception e) {
+ request.setAttribute(Globals.EXCEPTION_KEY,e);
+ }
+
+
+ /**
+ * Return exception stored in request under public key [Action.EXCEPTION].
+ *
+ * @param request The HTTP request we are processing
+ */
+ protected Exception getException(HttpServletRequest request) {
+ return (Exception) request.getAttribute(Globals.EXCEPTION_KEY);
+ }
+
+
+// ------------------------------------------------------------- Locale
+
+ /**
+ * Return the framework locale object for the user session
+ * for given request.
+ * If no session is set, or if the session has no locale
+ * set, the default locale is returned.
+ *
+ * @param request The HTTP request we are processing
+ * author François Rey (FREY - francois.rey@capco.com)
+ * author Eric Bariaux (EBRX - eric.bariaux@capco.com)
+ */
+ protected Locale getLocale(HttpServletRequest request) {
+
+ Locale result = null;
+ HttpSession session = request.getSession();
+ if (session!=null) {
+ result = (Locale) session.getAttribute(Globals.LOCALE_KEY);
+ if (result == null) result = Locale.getDefault();
+ } else {
+ result = Locale.getDefault();
+ }
+
+ return result;
+
+ } // end getLocale()
+
+
+ /**
+ * Set the framework locale object in the session for this request.
+ * If a session context does not exist, one is created.
+ *
+ * @param request The HTTP request we are processing
+ * @param locale The locale to use for this session
+ */
+ protected void setLocale(
+ HttpServletRequest request,
+ Locale locale) {
+
+ HttpSession session = request.getSession(true);
+ session.setAttribute(Globals.LOCALE_KEY,locale);
+
+ } // end setLocale()
+
+
+
+// ------------------------------------------------------ Remote Node
+
+
+ /**
+ * Returns the RemoteHost IP as an Integer.
+ */
+ protected Integer getRemoteNode(HttpServletRequest request) {
+ return new Integer(0); // :FIXME: Non functional
+ }
+
+
+// ------------------------------------------------------ Remote Server
+
+ /**
+ * Default name for a remote server that may be found
+ * in application scope ["REMOTE_SERVER"].
+ */
+ public static String REMOTE_SERVER_KEY = "REMOTE_SERVER";
+
+
+ /**
+ * Returns name of result server to be used by this Action,
+ * e.g, RESULT_SERVER_KEY.
+ */
+ protected String getRemoteServerName() {
+ return REMOTE_SERVER_KEY;
+ }
+
+
+ /**
+ * Checks application scope for the remote server object
+ * specified by <code>getRemoteServerName</code>
+ */
+ protected Object getRemoteServer() {
+return servlet.getServletContext().getAttribute(getRemoteServerName());
+ }
+
+// ----------------------------------------------------------- Messages
+
+ /**
+ * Return the application properties for this web application,
+ * if any.
+ */
+ protected Properties getProperties() {
+ return (Properties) servlet.getServletContext().getAttribute(
+ org.apache.commons.scaffold.lang.Tokens.PROPERTIES_KEY);
+ }
+
+
+ /**
+ * Number of replacement parameters permitted in Struts 1.0.
+ * See also saveConfirm.
+ */
+ private static int CONFIRM_MAX = 5; // (Message Key, plus 1..4)
+
+
+ /**
+ * Retrieves a base messages and up to four replaceable
+ * parameters from a List, and adds them to an ActionErrors
+ * collection.
+ *
+ * // :FIXME: This should be updated to use the
+ * new ActionMessages superclass.
+ *
+ * @param request The request we are servicing
+ * @param alerts Our ActionErrors collection
+ * @param list our list of replaceable parameters
+ */
+ protected void mergeAlerts(
+ HttpServletRequest request,
+ ActionErrors alerts,
+ List list) {
+
+ if ((null!=list) && (0!=list.size())) {
+
+ int size = list.size();
+ // Struts 1.0 allows up to 4 parameters, 1..4
+ if (size > CONFIRM_MAX) size = CONFIRM_MAX;
+ Object[] confirm = new Object[size];
+
+ for (int i=0; i<size; i++) {
+ confirm[i] = list.get(i);
+ }
+
+ switch (size) {
+ case 5:
+ alerts.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError((String) confirm[0],
+ confirm[1],confirm[2],confirm[3],
+ confirm[4]));
+ break;
+ case 4:
+ alerts.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError((String) confirm[0],
+ confirm[1],confirm[2],confirm[3]));
+ break;
+ case 3:
+ alerts.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError((String) confirm[0],
+ confirm[1],confirm[2]));
+ break;
+ case 2:
+ alerts.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError((String) confirm[0],
+ confirm[1]));
+ break;
+ case 1:
+ alerts.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError((String) confirm[0]));
+ }
+
+ }
+
+ } // end mergeAlerts()
+
+
+ /**
+ * Check for pending message collection.
+ * If it doesn't exist, and create is true, a new collection is
+ * returned.
+ *
+ * :FIXME: This should be the ActionMessage superclass
+ * @param request The HTTP request we are processing
+ * @param create Whether to create a new collection if one does
+ * not exist
+ * @return The pending ActionError queue
+ */
+ protected ActionErrors getMessages(
+ HttpServletRequest request,
+ boolean create) {
+
+ final String
+ MESSAGE_KEY = Globals.MESSAGE_KEY;
+
+ ActionErrors alerts = (ActionErrors)
+ request.getAttribute(MESSAGE_KEY);
+
+ if ((null==alerts) && (create)) {
+ alerts = new ActionErrors();
+ // Bypass Action.SaveMessage() since it
+ // won't accept a blank collection
+ request.setAttribute(MESSAGE_KEY,alerts);
+ }
+
+ return alerts;
+
+ } // end getMessages()
+
+
+ /**
+ * Merge incoming messages and save to messages
+ * collection. The collection is automatically saved to the request,
+ * so <code>Action.saveErrors(request,errors)</code> does not need
+ * to be called. If this method called more than once, the new
+ * messages are appended.
+ * <p>
+ * This method is upwardly compatabile with Struts 1.1 and uses the
+ * messages queue introduced with that release.
+ *
+ * @param request The HTTP request we are processing
+ * @param list The ResourceBundle token followed by 0 or more
+ * parameters
+ */
+ protected void saveMessages(
+ HttpServletRequest request,
+ List list) {
+
+ ActionErrors alerts = getMessages(request,true);
+ mergeAlerts(request,alerts,list);
+
+ } // end saveMessages()
+
+
+ /**
+ * Return whether there is an informational alert collection pending.
+ *
+ * @param request The HTTP request we are processing
+ * @return True if an informational alert collection exists
+ */
+ protected boolean isMessages(HttpServletRequest request) {
+ return (null!=getMessages(request,false));
+ }
+
+
+ /**
+ * Merge incoming messages and save to errors
+ * collection. The collection is automatically saved to the request,
+ * so <code>Action.saveErrors(request,errors)</code> does not need
+ * to be called. If this method called more than once, the new
+ * messages are appended.
+ *
+ * @param request The HTTP request we are processing
+ * @param list The ResourceBundle token followed by 0 or more
+ * parameters
+ */
+ protected void saveErrors(
+ HttpServletRequest request,
+ List list) {
+
+ ActionErrors alerts = getErrors(request,true);
+ mergeAlerts(request,alerts,list);
+
+ } // end saveErrors
+
+
+ /**
+ * Return whether there is an errors alert collection pending.
+ *
+ * @param request The HTTP request we are processing
+ * @return True if an errors alert collection exists
+ */
+ protected ActionErrors getErrors(
+ HttpServletRequest request,
+ boolean create) {
+
+ ActionErrors alerts = (ActionErrors)
+ request.getAttribute(Globals.ERROR_KEY);
+
+ if ((null==alerts) && (create)) {
+
+ alerts = new ActionErrors();
+ // Bypass Action.SaveError() since it
+ // won't accept a blank collection
+ request.setAttribute(Globals.ERROR_KEY,alerts);
+
+ }
+
+ return alerts;
+
+ } // end getErrors()
+
+
+ /**
+ * Return whether there is an errors alert collection pending.
+ *
+ * @param request The HTTP request we are processing
+ * @return True if an errors alert collection exists
+ */
+ protected boolean isErrors(HttpServletRequest request) {
+ return (null!=getErrors(request,false));
+ }
+
+
+// ------------------------------------------------------------ Helpers
+
+ /**
+ * Default separator character for list of tokens [";"] (semi-colon).
+ */
+ public static final String TOKEN_SEP = ";";
+
+
+ /**
+ * Return separator character for list of tokens
+ */
+ public String getTokenSep() {
+ return TOKEN_SEP;
+ }
+
+
+ /**
+ * Return array of tokens,
+ * using the result of <code>getTokeSep()</code> as the
+ * separator.
+ * Blanks are trimmed from tokens.
+ *
+ * @param parameter The string to tokenize into an array
+ */
+ public String[] tokenize(String parameter) {
+
+ return ConvertUtils.tokensToArray(parameter,getTokenSep());
+
+/*
+ StringTokenizer tokenizer =
+ new StringTokenizer(parameter,getTokenSep());
+ int i = 0;
+ String[] tokens = new String[tokenizer.countTokens()];
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken().trim();
+ if ((token==null) || (token.length()==0)) continue;
+ tokens[i++] = token;
+ }
+ return tokens;
+*/
+ } // end tokenize()
+
+
+ /**
+ * Create an object of the specified class,
+ * throwing a runtime exception if any error occurs.
+ * If method succeeds, then helpers are guaranteed
+ * to exist.
+ *
+ * @param request The HTTP request we are processing
+ * @param helperClass The name of the class
+ * @throws IllegalArgumentException if helper cannot be
+ * instantiated
+ */
+ public Object createHelperObject(
+ HttpServletRequest request,
+ String helperClass) {
+
+ StringBuffer sb = new StringBuffer();
+
+ if (isDebug()) {
+ sb.append(Log.HELPER_CREATING);
+ sb.append(helperClass);
+ servlet.log(sb.toString());
+ }
+
+ // Try the create
+ Object helper = null;
+ try {
+ helper = Class.forName(helperClass).newInstance();
+ }
+ catch (Throwable t) {
+ helper = null;
+ // assemble message: {class}: {exception}
+ sb.setLength(0);
+ sb.append(Log.CREATE_OBJECT_ERROR);
+ sb.append(Log.CLASS);
+ sb.append(helperClass);
+ sb.append(Log.SPACE);
+ sb.append(Log.ACTION_EXCEPTION);
+ sb.append(t.toString());
+ // throw runtime exception
+ throw new IllegalArgumentException(sb.toString());
+ }
+
+ if (isDebug()) {
+ sb.setLength(0);
+ sb.append(Log.HELPER_CREATED);
+ sb.append(Log.CLASS);
+ sb.append(helperClass);
+ servlet.log(sb.toString());
+ }
+
+ return helper;
+
+ } // createHelperObject()
+
+
+ /**
+ * Return an instance of the form-bean associated with the
+ * specified name, if any; otherwise return <code>null</code>.
+ * May be used to create an bean registered under a known name or
+ * a form-bean name passed with the mapping.
+ * <p>
+ * It is not required that the form-bean specified here be an
+ * ActionForm subclass. This allows other helper classes to be
+ * registered as form-beans and then instantiated by the Action.
+ *
+ * @param request The HTTP request we are processing
+ * @param helperName name of the form-bean helper
+ */
+ protected Object createHelperBean(
+ HttpServletRequest request,
+ String helperName) {
+
+ StringBuffer sb = new StringBuffer();
+
+ if (isDebug()) {
+ sb.append(Log.HELPER_CREATING);
+ sb.append(Log.NAME);
+ sb.append(helperName);
+ servlet.log(sb.toString());
+ }
+
+ Object bean = null;
+ // MUST! :FIXME: Need to provide equivalent of
+ // ActionFormBean formBean = servlet.findFormBean(helperName);
+ ActionFormBean formBean = null;
+ if (formBean != null) {
+ String className = null;
+ className = formBean.getType();
+ try {
+ Class clazz = Class.forName(className);
+ bean = clazz.newInstance();
+ } catch (Throwable t) {
+ bean = null;
+ // assemble message: {class}: {exception}
+ sb.setLength(0);
+ sb.append(Log.CREATE_OBJECT_ERROR);
+ sb.append(Log.NAME);
+ sb.append(helperName);
+ sb.append(Log.SPACE);
+ sb.append(Log.ACTION_EXCEPTION);
+ sb.append(t.toString());
+ String message = sb.toString();
+ servlet.log(message);
+ // echo log message as error
+ ActionErrors errors = getErrors(request,true);
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.HELPER_ACCESS_ERROR,
+ message));
+ }
+ if (isDebug()) {
+ sb.setLength(0);
+ sb.append(Log.HELPER_CREATED);
+ sb.append(Log.NAME);
+ sb.append(helperName);
+ servlet.log(sb.toString());
+ }
+ }
+ else {
+ // Not found
+ sb.setLength(0);
+ sb.append(Log.CREATE_OBJECT_ERROR);
+ sb.append(Log.NAME);
+ sb.append(helperName);
+ sb.append(Log.SPACE);
+ sb.append(Log.NOT_FOUND);
+ String message = sb.toString();
+ servlet.log(message);
+ // echo log message as error
+ ActionErrors errors = getErrors(request,true);
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.HELPER_ACCESS_ERROR,
+ message));
+ }
+
+ return bean;
+
+ } // createHelperBean()
+
+
+
+// --------------------------------------------------- EXTENSION POINTS
+
+
+ /**
+ * Optional extension point for pre-processing.
+ * Default method does nothing.
+ * To branch to another URI, return an non-null ActionForward.
+ * If errors are logged (getErrors() et al),
+ * default behaviour will branch to findFailure().
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ */
+ protected void preProcess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // override to provide functionality
+
+ } // end preProcess()
+
+
+ /**
+ * Return the appropriate ActionForward for an
+ * error condition.
+ * The default method returns a forward to input,
+ * when there is one, or "error" when not.
+ * The application must provide an "error" forward.
+ * An advanced implementation could check the errors
+ * and provide different forwardings for different circumstances.
+ * One possible error may be whether the form is null.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ * @return The ActionForward representing FAILURE
+ * or null if a FAILURE forward has not been specified.
+ */
+ protected ActionForward findFailure(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // If input page, use that
+ if (mapping.getInput()!=null)
+ return (new ActionForward(mapping.getInput()));
+
+ // If no input page, use error forwarding
+ return mapping.findForward(Tokens.FAILURE);
+
+ } // end findFailure()
+
+
+ /**
+ * Execute the business logic for this Action.
+ * <p>
+ * The default method logs the executeLogic() "event"
+ * when the logging level is set to DEBUG.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ */
+ public void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // override to provide functionality, like
+ // myBusinessObject.execute(form);
+
+ } // end executeLogic()
+
+
+ /**
+ * Token to print before short description
+ * of an exception.
+ */
+ private static final String ERROR = " ERROR: ";
+
+ /**
+ * Token to print between short and long description
+ * of an exception.
+ */
+ private static final String DETAILS = " DETAILS: ";
+
+
+ /**
+ * Process the exception handling for this Action.
+ *
+ * If Exception is subclass of BaseException, will
+ * report on everything in chain.
+ *
+ * Default behaviour should suffice for most circumstances.
+ * If overridden, if an alert is logged to the errors
+ * queue (getErrors()), then default behaviour will branch
+ * to findFailure().
+ * :TODO: Use a StringBufferOUTPUTStream to capture trace for error queue
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ */
+ protected void catchException(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+
+ // Retrieve, log and print to error console
+ Exception exception = getException(request);
+ servlet.log(Log.ACTION_EXCEPTION, exception);
+ exception.printStackTrace();
+
+ // General error message
+ ActionErrors errors = getErrors(request,true);
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.ERROR_GENERAL));
+
+ // Wrap exception messages in ActionError
+ // If chained, descend down chain
+ // appending messages to StringBuffer
+ StringBuffer sb = new StringBuffer();
+ if (exception instanceof BaseException) {
+ BaseException e = (BaseException) exception;
+ e.getMessage(sb);
+ }
+ else {
+ sb.append(ConvertUtils.LINE_FEED);
+ sb.append(ERROR);
+ sb.append(exception.toString());
+ String message = exception.getMessage();
+ if (null!=message) {
+ sb.append(ConvertUtils.LINE_FEED);
+ sb.append(DETAILS);
+ sb.append(message);
+ sb.append(ConvertUtils.LINE_FEED);
+ }
+ // :TODO: Use a StringBufferOUTPUTStream to capture trace
+ }
+
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.ERROR_DETAIL,sb.toString()));
+
+ } // end catchException()
+
+
+ /**
+ * Optional extension point for post-processing.
+ * Default method does nothing.
+ * This is called from a finally{} clause,
+ * and so is guaranteed to be called after executeLogic() or
+ * catchException().
+ * Use getException() to check if error occured.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ */
+ protected void postProcess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // override to provide functionality
+
+ } // end postProcess()
+
+
+ /**
+ * Return the appropriate ActionForward for the nominal,
+ * non-error state.
+ * The default returns mapping.findForward("continue");
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ * @return The ActionForward representing SUCCESS
+ * or null if a SUCCESS forward has not been specified.
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ return mapping.findForward(Tokens.SUCCESS);
+
+ } // end findSuccess()
+
+
+// --------------------------------------------------- ANCESTOR METHODS
+
+
+ /**
+ * Wrapper around original <code>perform()</code> method
+ * to call now-preferred <code>execute()</code> method,
+ * This provides forward compatibility for Struts 1.0.x a
+ * applications.
+ * A 1.0.x application will call this method, which will return the
+ * outcome of the <code>execute()</code> method.
+ * A 1.1+ application will ignore this wrapper method, and call
+ * <code>execute()</code> directly.
+ * Good practice says that the <code>execute()</code> method
+ * should cope with any exceptions and forward to the appropriate
+ * error page.
+ * But if any were to slip through, they are wrapped as
+ * <code>ServetExceptions</code> and rethrown.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @exception IOException if an input/output error occurs
+ * @exception ServletException if a servlet exception occurs
+ */
+ public ActionForward perform(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws IOException, ServletException {
+
+ try {
+
+ return execute(
+ mapping,
+ form,
+ request,
+ response
+ );
+ }
+
+ catch (Exception e) {
+ throw new ServletException(e);
+ }
+ }
+
+
+ /**
+ * Skeleton method that calls the other extension points
+ * (or "hotspots") provided by this class. These are:
+ * <ul>
+ * <li><code>preProcess(),</code></li>
+ * <li><code>executeLogic(),</code></li>
+ * <li><code>catchException(),</code></li>
+ * <li><code>postProcess(),</code></li>
+ * <li><code>findFailure(),</code></li>
+ * <li><code>findSuccess()</code></li>
+ * </ul>
+ * Typically, you can just override the other extension points
+ * as needed, and leave this one as is.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @exception IOException if an input/output error occurs
+ * @exception ServletException if a servlet exception occurs
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) throws Exception {
+
+
+ // Check for precondition errors; fail if found
+ preProcess(mapping,form,request,response);
+
+ if (isErrors(request)) {
+ return findFailure(mapping,form,request,response);
+ }
+
+ // Try the logic; Call catchException() if needed
+ try {
+
+ executeLogic(mapping,form,request,response);
+ }
+
+ catch (Exception e) {
+ // Store Exception; call extension point
+ setException(request,e);
+ catchException(mapping,form,request,response);
+ }
+
+ finally {
+ postProcess(mapping,form,request,response);
+ }
+
+ // If errors queued, fail
+ if (isErrors(request)) {
+ return findFailure(mapping,form,request,response);
+ }
+
+ // Otherwise, check for messages and succeed (only 1_0)
+ if ((isStruts_1_0()) && (isMessages(request))) {
+ saveErrors(request,getMessages(request,false));
+ }
+
+ return findSuccess(mapping,form,request,response);
+
+ } // end execute()
+
+} // end BaseAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseActionMapping.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseActionMapping.java
new file mode 100644
index 0000000..61d5924
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseActionMapping.java
@@ -0,0 +1,82 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import org.apache.struts.action.RequestActionMapping;
+
+/**
+ * Enhanced base ActionMapping.
+ * @version $Rev$ $Date$
+ */
+public class BaseActionMapping extends RequestActionMapping {
+
+ /**
+ * Forward compatabilty with Struts 1.1.
+ * Comment or remove this field for Stuts 1.1
+ */
+ private static boolean configured = false;
+
+ /**
+ * Message if they try to set a frozen configuration property.
+ */
+ private static String FROZEN_MESSAGE = "Configuration is frozen";
+
+ /**
+ * Adds submitPath to RequestActionMapping.
+ *
+ * This is useful when using one mapping to acquire a
+ * blank or prepopulated form, and then submitting that
+ * form to another mapping to complete the insert or update.
+ *
+ * It is also useful when reusing the same base form
+ * or result list in different workflows.
+ * Each mapping can indicate where to return,
+ * for its own workflow.
+ *
+ * The current mapping is stored in the request under
+ * the Globals.MAPPING_KEY (or the equivalent Struts 1.0
+ * Action.MAPPING_KEY).
+ *
+ * You can access this property, or any mapping property,
+ * using <bean:define>, or the equivalent, and then using
+ * a Runtime Expression to use the property with the
+ * <code>action</code> property of the html:form tag.
+ *
+ * To modify runtime behavior depending on whether returnPath
+ * has been set, use the <logic:present> tag to either
+ * use the returnPath or some alternate property.
+ *
+ * To use more than one-time property in a response,
+ * pass a helper bean from the action instead.
+ */
+ protected String submitPath = null;
+ public String getSubmitPath() {
+ return this.submitPath;
+ }
+ public void setSubmitPath(String submitPath) {
+ if (configured) {
+ throw new IllegalStateException(FROZEN_MESSAGE);
+ }
+ this.submitPath = submitPath;
+ }
+
+
+} // end BaseActionMapping
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseForm.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseForm.java
new file mode 100644
index 0000000..fcc456d
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseForm.java
@@ -0,0 +1,525 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionError;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.validator.DynaValidatorForm;
+import org.apache.struts.Globals;
+
+import org.apache.commons.scaffold.lang.ChainedException;
+import org.apache.commons.scaffold.lang.Log;
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.text.ConvertUtils;
+
+
+/**
+ * Enhanced base ActionForm.
+ * @version $Rev$ $Date$
+ */
+public class BaseForm extends DynaValidatorForm {
+
+
+// ---------------------------------------------------------- Remote Host
+
+ /**
+ * The network address making this request.
+ * <p>
+ * This is the value returned by reqest.getremoteHost.
+ * It is provided so that this can be logged by components on
+ * the business tier if needed.
+ * This property is maintained automatically through the
+ * <code>reset</code> method.
+ */
+ private String remoteHost = null;
+
+ /**
+ * Return our remoteHost property.
+ */
+ public String getRemoteHost() {
+ return (this.remoteHost);
+ }
+
+ /**
+ * Set our remoteHost property.
+ */
+ public void setRemoteHost(String remoteHost) {
+ this.remoteHost = remoteHost;
+ }
+
+
+ /**
+ * Sets RemoteHost attribute to request.getRemoteHost().
+ */
+ protected void resetRemoteHost(HttpServletRequest request) {
+ setRemoteHost(request.getRemoteHost());
+ }
+
+
+// ------------------------------------------------------- Session Locale
+
+ /**
+ * The session attribute key for our session locale [Action.LOCALE_KEY].
+ * (Suggestion only, may be overridden by presentation framework
+ */
+ public static String STRUTS_LOCALE_KEY = Globals.LOCALE_KEY;
+
+
+ /**
+ * Our locale property.
+ * <p>
+ * If the formBean instance is mutable, this is set to the Struts
+ * session locale whenever <code>reset()</code> is called. to update
+ * the session locale, use <code>putSessionLocale()</code>.
+ * <p>
+ * The properties refer to this as the "SessionLocale" so as to avoid
+ * naming/signature conflicts with business beans which may also
+ * maintain a Locale property.
+ */
+ private Locale locale = null;
+
+
+ /**
+ * Set our locale property.
+ *
+ */
+ public void setSessionLocale(Locale locale) {
+ this.locale = locale;
+ }
+
+
+ /**
+ * Retrieve our locale property.
+ */
+ public Locale getSessionLocale() {
+ return this.locale;
+ }
+
+
+ /**
+ * Return the session key attribute for our locale object.
+ */
+ public String getSessionLocaleName() {
+ return STRUTS_LOCALE_KEY;
+ }
+
+
+ /**
+ * Reset our locale property to the locale object found in
+ * the session associated with this request.
+ */
+ protected void resetSessionLocale(HttpServletRequest request) {
+
+ HttpSession session = request.getSession();
+ if (session!=null) {
+
+ setSessionLocale((Locale)
+ session.getAttribute(getSessionLocaleName()));
+
+ }
+ else {
+
+ setSessionLocale(Locale.getDefault());
+ }
+
+ } // end resetSessionLocale
+
+
+ /**
+ * Change the locale property in the session to our locale object,
+ * or the default Locale if ours is null.
+ */
+ protected void putSessionLocale(HttpServletRequest request) {
+
+ Locale locale = getSessionLocale();
+ if (null==locale) locale = Locale.getDefault();
+
+ request.getSession(true).setAttribute(Globals.LOCALE_KEY,locale);
+
+ } // end putSessionLocale
+
+
+ /**
+ * Display the user's locale setting or the default locale.
+ */
+ public String getLocaleDisplay() {
+
+ Locale locale = getSessionLocale();
+ if (null==locale) locale = Locale.getDefault();
+ return locale.getDisplayName();
+
+ } // end getLocaleDisplay
+
+
+ /**
+ * Set our locale to given ISO Language Code.
+ * An empty String is used for the country.
+ * <p>
+ * Mainly provided for completeness.
+ */
+ public void setLocaleDisplay(String language) {
+ setSessionLocale(new Locale(language,EMPTY));
+ }
+
+
+// -------------------------------------------------------------- Mutable
+
+ /**
+ * The mutable state.
+ * <p>
+ * To avoid autopopulation when forwarding beans between actions,
+ * set mutable to be true and be sure all setters observe the
+ * mutable state.
+ * <p>
+ * (<code>if (isMutable()) this.field = field;</code>).
+ * subject to autopopulation.
+ */
+ private boolean mutable = true;
+
+
+ /**
+ * Set the mutable state.
+ */
+ public void setMutable(boolean mutable) {
+ this.mutable = mutable;
+ }
+
+
+ /**
+ * Retrieve the mutable state.
+ */
+ public boolean isMutable() {
+ return this.mutable;
+ }
+
+
+// ------------------------------------------------------------- Dispatch
+
+ /**
+ * The dispatch property.
+ * <p>
+ * This can be set by a JavaScript buttonto indicate which task should
+ * be performed (or dispatched) by an action.
+ * Observes the bean's mutable state.
+ */
+ public String dispatch = null;
+
+
+ /**
+ * Set dispatch.
+ */
+ public void setDispatch(String dispatch) {
+ if (isMutable()) this.dispatch = dispatch;
+ }
+
+
+ /**
+ * Get the dispatch.
+ */
+ public String getDispatch() {
+ return this.dispatch;
+ }
+
+
+// --------------------------------------------------------- Public Methods
+
+ /**
+ * A static, empty String used by isBlank.
+ */
+ private static String EMPTY = "";
+
+
+ /**
+ * Convenience method to check for a null or empty String.
+ *
+ * @param s The sting to check
+ */
+ protected boolean blank(String s) {
+ return ConvertUtils.blank(s);
+ }
+
+
+ /**
+ * Convenience method to check for a null, empty, or "0" String.
+ *
+ * @param s The sting to check
+ */
+ protected boolean blankValue(String s) {
+ return ConvertUtils.blankValue(s);
+ }
+
+
+ /**
+ * @deprecated Use blank instead.
+ */
+ protected boolean isBlank(String s) {
+ return blank(s);
+ }
+
+
+ /**
+ * Convenience method to test for a required field
+ * and setup the error message.
+ */
+ protected void required(
+ ActionErrors errors,
+ String field,
+ String name,
+ String arg) {
+ if ((null==field) || (0==field.length())) {
+ errors.add(name,
+ new ActionError(Tokens.ERRORS_REQUIRED,arg));
+ }
+ }
+
+
+ /**
+ * Convenience method to test for a required array
+ * and setup the error message.
+ */
+ protected void required(
+ ActionErrors errors,
+ String[] field,
+ String name,
+ String arg) {
+ if ((null==field) || (0==field.length)) {
+ errors.add(name,
+ new ActionError(Tokens.ERRORS_REQUIRED,arg));
+ }
+ }
+
+
+ /**
+ * Create an object of the specified class,
+ * throwing a runtime exception if any error occurs.
+ * If an exception is not thrown, then helper is guaranteed to exist.
+ *
+ * @param objectClass The name of the class
+ * @throws IllegalArgumentException if object cannot be
+ * instantiated
+ */
+ public Object createObject(
+ String objectClass) {
+
+ // Try the create
+ Object object = null;
+ try {
+ object = Class.forName(objectClass).newInstance();
+ }
+ catch (Throwable t) {
+ object = null;
+ // assemble message: {class}: {exception}
+ StringBuffer sb = new StringBuffer();
+ sb.append(Log.CREATE_OBJECT_ERROR);
+ sb.append(Log.CLASS);
+ sb.append(objectClass);
+ sb.append(Log.SPACE);
+ sb.append(Log.ACTION_EXCEPTION);
+ sb.append(t.toString());
+ // throw runtime exception
+ throw new IllegalArgumentException(sb.toString());
+ }
+ return object;
+
+ } // createHelperObject()
+
+
+ /**
+ * Return map of properties for this bean.
+ * Base method uses <code>PropertyUtils.describe</code>.
+ * Override if some properties should not be transfered
+ * this way, or a property name should be altered.
+ * This will return the actual public properties.
+ *
+ * @exception Exception on any error.
+ */
+ public Map describe() throws Exception {
+
+ try {
+ return PropertyUtils.describe(this);
+ } catch (Throwable t) {
+ throw new ChainedException(t);
+ }
+
+ } // end describe
+
+
+ /**
+ * Set properties from given object.
+ * Base method uses <code>BeanUtils.copyProperties</code> and
+ * <code>PropertyUtils.describe</code>.
+ *
+ * @param o The object to use to populate this object.
+ * @exception Exception on any error.
+ */
+ public void set(Object o) throws Exception {
+
+ try {
+ BeanUtils.copyProperties(this,o);
+ } catch (Throwable t) {
+ throw new ChainedException(t);
+ }
+
+ } // end set
+
+
+ /**
+ * Populate matching properties on given object.
+ * Base method uses <code>BeanUtils.copyProperties</code> and
+ * <code>describe()</code>.
+ *
+ * @param o The object to populate from this object.
+ * @exception Exception on any error.
+ */
+ public void populate(Object o) throws Exception {
+
+ try {
+ BeanUtils.copyProperties(o,describe());
+ } catch (Throwable t) {
+ throw new ChainedException(t);
+ }
+
+ } // end populate
+
+
+ /**
+ * // :FIXME: Needs testing. Works OK without a profile bean =:o)
+ * Merge a profile bean with this bean to provide a unified map
+ * of the combined parameters. Will on add properties to the map
+ * from the profile bean if matching property on this bean is
+ * blank or null (which includes absent).
+ * The result is a union of the properties, with the this
+ * bean's non-blank properties having precedence over the
+ * profile's properties. The profile is a base that this bean
+ * can override on the fly -- If this bean does not supply a
+ * property, then the profile property is used. But any
+ * property named on the userProfile is included (even if
+ * it has no match on this bean).
+ * <p>
+ * If profile is null, a map of this bean's properties is returned.
+ * <p>
+ * The profile can be any JavaBean.
+ * <p>
+ * This method is forwardly-compatible with BaseMapForm.
+ * For an instance of BaseMapForm, getMap() is used; otherwise
+ * describe() or PropertyUtils.describe() is used.
+ *
+ * :FIXME: Needs testing. Works OK without a profile bean =:o)
+ * @param profile The profile bean, if any
+ * @throws Exception if error transfering data to map
+ */
+ protected Map merge(Object profile) throws Exception {
+
+ Map formMap = null;
+ if (this instanceof BaseMapForm) {
+ BaseMapForm form = (BaseMapForm) this;
+ formMap = form.getMap();
+ }
+ else {
+ formMap = describe();
+ }
+
+ if (profile!=null) {
+
+ Map userMap = null;
+ if (profile instanceof BaseMapForm) {
+ BaseMapForm form = (BaseMapForm) profile;
+ userMap = form.getMap();
+ }
+ else if (profile instanceof BaseForm) {
+ BaseForm form = (BaseForm) profile;
+ userMap = form.describe();
+ }
+ else {
+ userMap = PropertyUtils.describe(this);
+ }
+
+ // Add user element to formMap if form element is null or blank
+ // Starting with the formMap, for every element in the userMap,
+ // see if the formMap element is non-existant, null, or an empty String.
+ // If it is (our formMap doesn't override), add the userMap value
+ // to the formMap.
+ Iterator i = userMap.keySet().iterator();
+ while (i.hasNext()) {
+ String key = (String) i.next();
+ String formValue = (String) formMap.get(key);
+ if (isBlank(formValue)) {
+ formMap.put(key,userMap.get(key));
+ }
+ }
+ }
+
+ return formMap;
+
+ } // end merge
+
+
+
+ /**
+ * If bean is set to mutable, calls <code>resetSessionLocale</code>
+ * and <code>resetRemoteHost</code>.
+ *
+ * Subclasses resetting their own fields should observe the mutable
+ * state (<code>if (isMutable()) ...</code>).
+ *
+ * @param mapping The mapping used to select this instance
+ * @param request The servlet request we are processing
+ */
+ public void reset(
+ ActionMapping mapping,
+ HttpServletRequest request) {
+
+ if (isMutable()) {
+
+ super.reset(mapping,request);
+
+ // :TODO: Might be useful to have a collection of reset listeners
+ resetRemoteHost(request);
+ resetSessionLocale(request);
+ }
+
+ } // end reset
+
+
+ /**
+ * Return an empty ActionErrors or the result of calling
+ * the superclass validate. Will not return null.
+ */
+ public ActionErrors validate(ActionMapping mapping,
+ HttpServletRequest request) {
+
+ ActionErrors errors = super.validate(mapping,request);
+ if (null==errors) errors = new ActionErrors();
+ return errors;
+ }
+
+
+} // end BaseForm
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseHelperAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseHelperAction.java
new file mode 100644
index 0000000..a219265
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseHelperAction.java
@@ -0,0 +1,110 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+
+/**
+ * Base class to instantiate helper objects from parameter property.
+ * Subclasses should override the alternate executeLogic to provide
+ * functionality.
+ * The standard executeLogic will instantiate the object(s),
+ * and call the alternate executeLogic method, passing the helpers
+ * in an array.
+ * <p>
+ * Multiple helper classes may be specified in a semi-colon delimited list,
+ * which will be instantiated in the helpers array in the order given.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BaseHelperAction extends BaseAction {
+
+
+// --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Simple test to render String version of instantiated
+ * helpers. Should be overridden to provide functionality
+ * (without calling super!).
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The ActionForm
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @param helpers The object instantiated from type given as parameter.
+ * @exception java.io.IOException if an input/output error occurs
+ * @exception javax.servlet.ServletException if a servlet exception occurs
+ */
+ protected void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ Object[] helpers)
+ throws Exception {
+ // override to provide new functionality
+ response.setContentType(Tokens.TEXT_PLAIN);
+ for (int i = 0; i < helpers.length; i++)
+ response.getWriter().print(helpers[i].toString());
+ }
+
+
+ /**
+ * Instantiate helper objects from the type given as the
+ * ActionMapping parameter (delimited with semicolons), and call
+ * the alternate executeLogic.
+ * Will not call "helper" perform if helper creation fails.
+ * The error is logged, and null returned.
+ * <p>
+ * Also checks for cancel and token conditions, if an
+ * appropriate forward is present.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The ActionForm
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * <p>
+ * @exception Exception if error occurs
+ */
+ public void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ String[] tokens = tokenize(mapping.getParameter());
+ int helperCount = tokens.length;
+ Object[] helpers = new Object[helperCount];
+
+ for (int i=0; i<helperCount; i++) {
+ helpers[i] = createHelperObject(request,tokens[i]);
+ }
+
+ executeLogic(mapping,form,request,response,helpers);
+ }
+
+} // end BaseHelperAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseMapForm.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseMapForm.java
new file mode 100644
index 0000000..aa8bdac
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BaseMapForm.java
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+/**
+ * Enhanced base ActionForm for Struts 1.1 and later.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BaseMapForm extends BaseForm {
+
+// ----------------------------------------------------------- Properties
+
+ /**
+ * Associates the specified value with the specified key in
+ * the property map for this object
+ * -- the equivalent of <code>getMap().put(key,value).
+ * Observes the mutable property and only set new value when
+ * <code>isMutable()</code> is true.
+ * <p>
+ * In a Struts 1.1 application, this will set an element to the
+ * map. See also <code>getValue()</code>.
+ * <p>
+ * @exception Exception Passes through any Exception thrown by underlying
+ * hashmap.
+ * @param key - key with which the specified value is to be associated.
+ * @param value - value to be associated with the specified key.*/
+ public void setValue(String key, Object value) throws Exception {
+ if (isMutable()) getMap().put(key,value);
+ }
+
+
+ /**
+ * Returns the value to which this map maps the specified key
+ * -- the equivalent of <code>Object getMap().get(key)</code>.
+ * <p>
+ * In a Struts 1.1 application, this can be used to retrieve a
+ * property from the Map, e.g., property="value(username)"
+ * <p>
+ * @param key - key whose associated value is to be returned.
+ * @exception Exception Passes through any Exception thrown by underlying
+ * hashmap.
+ */
+ public Object getValue(String key) throws Exception {
+ return getMap().get(key);
+ }
+
+// end BaseMapForm
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizAction.java
new file mode 100644
index 0000000..385f100
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizAction.java
@@ -0,0 +1,589 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.beanutils.BeanUtils;
+
+import org.apache.struts.action.ActionError;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Log;
+import org.apache.commons.scaffold.lang.ParameterException;
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.util.BizRequest;
+import org.apache.commons.scaffold.util.BizResponse;
+import org.apache.commons.scaffold.util.BizService;
+import org.apache.commons.resources.Message;
+
+/**
+ * Advanced framework class to invoke a business service
+ * and process the response.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BizAction extends BaseHelperAction {
+
+
+ /**
+ * Exposes result in a servlet context.
+ * If there is an existing bean with same attribute name in the target
+ * context,
+ * then the matching properties on that bean are populated with the
+ * result.
+ *
+ * @param request the request being serviced
+ * @param name The name to use in scope
+ * @param scope The scope to set the attribute in
+ * @param bean The attribute to be set
+ */
+ protected void exposeInScope(
+ HttpServletRequest request,
+ String name,
+ String scope,
+ Object bean) {
+
+ if ((null==scope) || (null==bean)) {
+ return;
+ }
+
+ if (Tokens.REQUEST.equals(scope)) {
+ Object form = request.getAttribute(name);
+ if (null==form) {
+ request.setAttribute(name,bean);
+ }
+ else {
+ try {
+ BeanUtils.copyProperties(form,bean);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+ else if (Tokens.SESSION.equals(scope)) {
+ Object form = request.getSession().getAttribute(name);
+ if (null==form) {
+ request.getSession().setAttribute(name,bean);
+ }
+ else {
+ try {
+ BeanUtils.copyProperties(form,bean);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+ else if (Tokens.APPLICATION.equals(scope)) {
+ Object form = servlet.getServletContext().getAttribute(name);
+ if (null==form) {
+ servlet.getServletContext().setAttribute(name,bean);
+ }
+ else {
+ try {
+ BeanUtils.copyProperties(form,bean);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+ else {
+ StringBuffer sb = new StringBuffer("exposeInScope: ");
+ sb.append(scope);
+ sb.append(Tokens.INVALID_SCOPE);
+ throw new IllegalArgumentException(sb.toString());
+ }
+
+ } // end exposeInScope()
+
+
+ /**
+ * Save the result object within the business response to servlet context.
+ * <p>
+ * <code>bizResponse.getData()</code> must return non-null.
+ * <p>
+ * If <code>bizResponse.getName()</code> is null, the mapping's attribute
+ * (<code>mapping.getAttribute()</code>) is used instead.
+ * By default, this is the <code>form-bean</code>'s name.
+ * <p>
+ * If data is a Collection, only the first element is stored.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param bizResponse The BizResponse we are handling
+ */
+ protected void checkDataSingle(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ BizResponse bizResponse) {
+
+ String name = bizResponse.getName();
+ if (null==name) {
+ // use form-bean or mapping name
+ name = mapping.getAttribute();
+ bizResponse.setName(name);
+ }
+ String scope = bizResponse.getScope();
+ Object bean = bizResponse.getData();
+
+ // if data is collection, use first element
+ if (bean instanceof Collection) {
+ Collection collection = (Collection) bean;
+ if (collection.isEmpty()) {
+ // for lack of a better idea, get a fresh form-bean
+ // this will return null if there is not a form-bean
+ // associated with this mapping
+ bean = createHelperBean(request,mapping.getName());
+ }
+ else {
+ bean = collection.iterator().next();
+ }
+ }
+ if (bizResponse.isExposed()) {
+ exposeInScope(request,name,scope,bean);
+
+ }
+
+ } // end checkDataSingle
+
+
+ /**
+ * Save any result objects within the business response to servlet context.
+ * <p>
+ * <code>bizResponse.getData()</code> must return non-null.
+ * <p>
+ * If <code>bizResponse.getName()</code> is null, the mapping's attribute
+ * (<code>mapping.getAttribute()</code>) is used instead.
+ * By default, this is the <code>form-bean</code>'s name.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param bizResponse The BizResponse we are handling
+ */
+ protected void checkData(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ BizResponse bizResponse) {
+
+ if (bizResponse.isSingleForm()) {
+ checkDataSingle(mapping,request,bizResponse);
+ }
+ else {
+
+ String name = bizResponse.getName();
+ if (null==name) {
+ name = Tokens.LIST_KEY;
+ bizResponse.setName(name);
+ }
+ String scope = bizResponse.getScope();
+ Object bean = bizResponse.getData();
+
+ if (bizResponse.isExposed()) {
+ exposeInScope(request,name,scope,bean);
+ }
+ }
+
+ } // end checkData
+
+
+ /**
+ * Process new dispatch advice passed by the business tier.
+ * <p>
+ * This is used to route control to another location besides
+ * the default "success" forward registered with the controller.
+ * <p>
+ * The business tier can pass back either a path or the name of
+ * an ActionForward.
+ * <code>checkDispatch</code> will then create an ActionForward to return
+ * and save it in the request under the SUCCESS token.
+ * The <code>findSuccess()</code> will check for this attribute
+ * before returning the controller's default.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param bizResponse The BizResponse we are handling
+ */
+ protected void checkDispatch(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ BizResponse bizResponse) {
+
+ String dispatch = bizResponse.getDispatch();
+ ActionForward forward = null;
+
+ if (bizResponse.isDispatchPath()) {
+ forward = new ActionForward(dispatch);
+ }
+ else {
+ forward = mapping.findForward(dispatch);
+ }
+
+ // Our findSuccess looks for this
+ request.setAttribute(Tokens.SUCCESS,forward);
+
+ } // end checkDispatch
+
+
+ /**
+ * Check outcome, if any; recurse if container for other outcomes.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param bizResponse The BizResponse we are handling
+ */
+ protected void checkOutcome(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ BizResponse bizResponse) throws Exception {
+
+ if (bizResponse!=null) {
+
+ if (bizResponse.isAggregate()) {
+ // recurse for each BizResponse in collection
+ Collection collection = (Collection)
+ bizResponse.getData();
+ Iterator iterator = collection.iterator();
+ while (iterator.hasNext()) {
+ BizResponse nextBizResponse =
+ (BizResponse) iterator.next();
+ checkOutcome(mapping,request,nextBizResponse);
+ }
+ }
+
+ else {
+ // call extension points for whatever is returned
+ if (bizResponse.isData())
+ checkData(mapping,request,bizResponse);
+
+ if (bizResponse.isMessages())
+ checkMessages(mapping,request,bizResponse);
+
+ if (bizResponse.isDispatch())
+ checkDispatch(mapping,request,bizResponse);
+ }
+ }
+
+ else {
+ throw new Exception(Log.PROCESS_RESULT_NULL);
+ }
+
+ } // end checkOutcome
+
+
+// --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Stores informational messages for display by the presention device.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param bizResponse The BizResponse we are handling
+ */
+ protected void checkMessages(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ BizResponse bizResponse) {
+
+ // saveMessages(request,bizResponse.getMessages());
+
+ } // end checkMessages
+
+
+ /**
+ * Return the appropriate ActionForward for error or failure
+ * conditions.
+ * First checks for a FAILURE ActionForward stored in the request.
+ * If an override is not found, returns the result of the
+ * superclass method.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ * @return The ActionForward representing FAILURE
+ * or null if a FAILURE forward has not been specified.
+ */
+ protected ActionForward findFailure(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // Did someone leave us a forward?
+ ActionForward forward = (ActionForward)
+ request.getAttribute(Tokens.FAILURE);
+
+ if (null==forward) {
+ // No override, use default
+ forward = super.findFailure(mapping,form,request,response);
+ }
+ else {
+ // Clear advice from the request
+ request.setAttribute(Tokens.FAILURE,null);
+ }
+
+ return forward;
+
+ } // end findFailure
+
+
+ /**
+ * Optional extension point for pre-processing.
+ * Default method does nothing.
+ * To branch to another URI, return an non-null ActionForward.
+ * If errors are logged (getErrors() et al),
+ * default behaviour will branch to findFailure().
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ */
+ protected void preProcess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // Check for cancelled
+ ActionForward forward = mapping.findForward(Tokens.CANCEL);
+ if ((null!=forward) && (isCancelled(request))) {
+ // Our findFailure looks for this
+ request.setAttribute(Tokens.FAILURE,forward);
+ // Post cancel error message
+ ActionErrors errors = getErrors(request,true);
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.ERROR_CANCEL));
+ return;
+ }
+
+ // Check for missing token
+ forward = mapping.findForward(Tokens.GET_TOKEN);
+ if ((null!=forward) && (!isTokenValid(request))) {
+ // Our findFailure looks for this
+ request.setAttribute(Tokens.FAILURE,forward);
+ // Post token error message
+ ActionErrors errors = getErrors(request,true);
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.ERROR_TOKEN));
+ return;
+ }
+ if (null!=forward) {
+ // reset to guard against duplicate request
+ resetToken(request);
+ }
+
+ // Check for save token directive (do this last)
+ forward = mapping.findForward(Tokens.SET_TOKEN);
+ if (null!=forward) saveToken(request);
+
+
+ } // end preProcess
+
+
+ /**
+ * Return the appropriate ActionForward for the nominal,
+ * non-error state.
+ * First checks for a SUCCESS ActionForward stored in the request.
+ * If an override is not found, returns the result of the
+ * superclass method.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ * @return The ActionForward representing SUCCESS
+ * or null if a SUCCESS forward has not been specified.
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // Did someone leave us a forward?
+ ActionForward forward = (ActionForward)
+ request.getAttribute(Tokens.SUCCESS);
+
+ if (null==forward) {
+ // No override, use default
+ forward = super.findSuccess(mapping,form,request,response);
+ }
+ else {
+ // Clear advice from the request
+ request.setAttribute(Tokens.SUCCESS,null);
+ }
+
+ return forward;
+
+ } // end findSuccess
+
+
+ /**
+ * The set of argument type classes for the reflected method call.
+ * These are the same for all calls, so calculate them only once.
+ */
+ private static final Class types[] = { Object.class };
+
+
+ /**
+ * Error handler.
+ * Posts a message template and two parameters in a BizResponse.
+ */
+ private BizResponse processError(
+ ActionMapping mapping,
+ String template) {
+
+ // Any other way to do this?
+ BizResponse bizResponse =
+ new org.apache.commons.scaffold.util.BizResponseImpl();
+ Message message = new org.apache.commons.scaffold.util.MessageImpl(
+ template,
+ mapping.getPath(),
+ mapping.getParameter()
+ );
+
+ bizResponse.addMessage(message);
+
+ return bizResponse;
+ }
+
+
+ /**
+ * Invoke an alternate method on BizService.
+ */
+ protected BizResponse processDispatch(
+ ActionMapping mapping,
+ BizService bizService,
+ BizRequest bizRequest,
+ String methodName) throws Exception {
+
+ Method method = bizService.getClass().getMethod(methodName,types);
+ Object args[] = { bizRequest };
+
+ BizResponse bizResponse = null;
+ try {
+
+ bizResponse = (BizResponse) method.invoke(bizService,args);
+
+ }
+
+ catch (ClassCastException e) {
+
+ bizResponse = processError(mapping,Tokens.ERROR_DISPATCH_RETURN);
+ }
+
+ catch (IllegalAccessException e) {
+
+ bizResponse = processError(mapping,Tokens.ERROR_DISPATCH_RETURN);
+ }
+
+ catch (InvocationTargetException e) {
+
+ // Rethrow the target exception if possible so that the
+ // exception handling machinery can deal with it
+ Throwable t = e.getTargetException();
+ if (t instanceof Exception) {
+ throw ((Exception) t);
+ } else {
+ bizResponse = processError(mapping,Tokens.ERROR_DISPATCH);
+ }
+ }
+
+ return bizResponse;
+ }
+
+
+
+ /**
+ * Obtain the business request, invoke the business service,
+ * and process the outcome.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The ActionForm
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @param helpers The object instantiated from type given as parameter.
+ * @exception Exception if a error occurs
+ */
+ protected void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ Object[] helpers) throws Exception {
+
+ BizResponse bizResponse = null;
+ try {
+
+ // Cast our form bean; snag our request bean
+ BizForm bizForm = (BizForm) form;
+ BizRequest bizRequest = bizForm.getBizRequest();
+
+ // Munge the parameter property
+ String[] tokens = tokenize(mapping.getParameter());
+
+ // Create our business service helper
+ Object helper = createHelperObject(request,tokens[0]);
+ BizService bizService = (BizService) helper;
+
+ // Process business logic
+ if (tokens.length>1) {
+
+ // Pass along the helper's parameter, if any
+ if (tokens.length>2) {
+ bizRequest.setParameter(tokens[2]);
+ }
+
+ bizResponse = processDispatch(
+ mapping,
+ bizService,
+ bizRequest,
+ tokens[1]);
+ }
+
+ else {
+ bizResponse = (BizResponse) bizService.process(bizRequest);
+ }
+ }
+
+ // Gracefully trap any kinky class-cast or NPE type exceptions
+ catch (Throwable t) {
+ throw new ParameterException(t);
+ }
+
+ // Analyze result of business logic
+ checkOutcome(mapping,request,bizResponse);
+
+ } // end executeLogic
+
+} // end BizAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizForm.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizForm.java
new file mode 100644
index 0000000..0378502
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizForm.java
@@ -0,0 +1,119 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.struts.action.ActionErrors;
+
+import org.apache.commons.scaffold.util.BizRequest;
+import org.apache.commons.scaffold.util.Messages;
+
+
+/**
+ * A BizForm creates and validates a business request
+ * [<code>org.apache.commons.scaffold.BizRequest</code>]
+ * as part of its own validation routine.
+ * A BizForm is typically procesed by a business action
+ * [<code>org.apache.commons.scaffold.BizAction</code>]
+ * which passes the business request to a business service
+ * [<code>org.apache.commons.scaffold.BizService</code>].
+ *
+ * @version $Rev$ $Date$
+ */
+public interface BizForm {
+
+ /**
+ * The session attribute key for our user profile bean ["USER_PROFILE"].
+ * (Suggestion only, may be overridden by presentation framework
+ */
+ public static String USER_PROFILE_KEY = "USER_PROFILE";
+
+ /**
+ * Return our bizRequest property.
+ */
+ public BizRequest getBizRequest();
+
+ /**
+ * Set our bizRequest property.
+ */
+ public void setBizRequest(BizRequest bizRequest);
+
+ /**
+ * Factory method to create business request object.
+ */
+ public BizRequest createBizRequest(String bizType);
+
+
+ // ------------------------------------------------------ User Profile
+
+ /**
+ * Return our userProfile property.
+ */
+ public Object getUserProfile();
+
+ /**
+ * Set our userProfile property.
+ */
+ public void setUserProfile(Object userProfile);
+
+ /**
+ * Returns name of result server to be used by this Action,
+ * [BizRequest.USER_PROFILE_KEY]
+ */
+ public String getUserProfileName();
+
+ /**
+ * Retrieve from session under known key
+ * (<code>ProcessBean.USER_PROFILE_KEY</code>).
+ * Override this approach to implement another method (e.g cookies).
+ * Also revise UpdateProfile action-mapping to store changes.
+ *
+ * @param request The HTTP request we are processing
+ */
+ public void resetUserProfile(HttpServletRequest request);
+
+ /**
+ * Return our remoteServer property.
+ */
+ public Object getRemoteServer();
+
+ /**
+ * Set our remoteServer property.
+ */
+ public void setRemoteServer(Object remoteServer);
+
+ /**
+ * Checks application scope for the remote server object
+ * specified by <code>getRemoteServerName</code>
+ */
+ public void resetRemoteServer(HttpServletRequest request);
+
+ /**
+ * Copy messages from business tier message class to presentation
+ * tier error class.
+ * :TODO: Refactor once everything is based on a root Commons
+ * Messages class.
+ */
+ public void addMessages(ActionErrors errors, Messages messages);
+
+
+} // end BizForm
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizFormBean.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizFormBean.java
new file mode 100644
index 0000000..a7f4ab3
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizFormBean.java
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import org.apache.struts.action.ActionFormBean;
+
+/**
+ * An <code>ActionFormBean</code> for specifying a <code>BizForm</code>.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BizFormBean extends ActionFormBean {
+
+ /**
+ * The business request type to create, populate, and validate.
+ */
+ private String bizType = null;
+
+ // see interface for Javadoc
+ public String getBizType() {
+ return (this.bizType);
+ }
+
+ // see interface for Javadoc
+ public void setBizType(String bizType) {
+ this.bizType = bizType;
+ }
+
+} // end BizFormBean
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizFormImpl.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizFormImpl.java
new file mode 100644
index 0000000..a535fdd
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/BizFormImpl.java
@@ -0,0 +1,225 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import java.util.Map;
+import org.apache.commons.beanutils.BeanUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.util.BizRequest;
+import org.apache.commons.scaffold.util.MessageImpl;
+import org.apache.commons.scaffold.util.Messages;
+import org.apache.commons.scaffold.util.MessagesImpl;
+
+
+/**
+ * Concrete implementation of a BizForm.
+ * To use this object, you must specify the BizFormBean or a superclass
+ * as the default ActionFormBean type for the ActionServlet controller.
+ *
+ * :FIXME: This implementation can only be used with the default module.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BizFormImpl extends BaseForm implements BizForm {
+
+
+ // ------------------------------------------------------ Business Request
+
+ /**
+ * The business request object.
+ */
+ private BizRequest bizRequest = null;
+
+ // see interface for Javadoc
+ public BizRequest getBizRequest() {
+ return (this.bizRequest);
+ }
+
+ // see interface for Javadoc
+ public void setBizRequest(BizRequest bizRequest) {
+ this.bizRequest = bizRequest;
+ }
+
+ // see interface for Javadoc
+ public BizRequest createBizRequest(String bizType) {
+
+ BizRequest bizRequest = (BizRequest) createObject(bizType) ;
+
+ return bizRequest;
+ }
+
+ // ------------------------------------------------------ User Profile
+
+ /**
+ * The business request type to create, populate, and validate.
+ */
+ private Object userProfile = null;
+
+ // see interface for Javadoc
+ public Object getUserProfile() {
+ return (this.userProfile);
+ }
+
+ // see interface for Javadoc
+ public void setUserProfile(Object userProfile) {
+ this.userProfile = userProfile;
+ }
+
+ // see interface for Javadoc
+ public String getUserProfileName() {
+ return USER_PROFILE_KEY;
+ }
+
+ // see interface for Javadoc
+ public void resetUserProfile(HttpServletRequest request) {
+
+ setUserProfile(
+ request.getSession().getAttribute(getUserProfileName())
+ );
+
+ }
+
+ // ------------------------------------------------------ Remote Server
+
+ /**
+ * The business request type to create, populate, and validate.
+ */
+ private Object remoteServer = null;
+
+ // see interface for Javadoc
+ public Object getRemoteServer() {
+ return (this.remoteServer);
+ }
+
+ // see interface for Javadoc
+ public void setRemoteServer(Object remoteServer) {
+ this.remoteServer = remoteServer;
+ }
+
+ // see interface for Javadoc
+ public String getRemoteServerName() {
+ return BizRequest.REMOTE_SERVER_KEY;
+ }
+
+ // see interface for Javadoc
+ public void resetRemoteServer(HttpServletRequest request) {
+
+ setRemoteServer(servlet.getServletContext().getAttribute(
+ getRemoteServerName()));
+
+ }
+
+ // --------------------------------------------------------------------
+
+ // see interface for Javadoc
+ public void addMessages(ActionErrors errors, Messages messages) {
+
+ //:TODO: add functionality
+
+ }
+
+ /**
+ * Call superclass reset and other reset* methods in this class.
+ */
+ public void reset(ActionMapping mapping,
+ HttpServletRequest request) {
+
+ super.reset(mapping,request);
+
+ if (isMutable()) {
+
+ resetUserProfile(request);
+ resetRemoteServer(request);
+ }
+ }
+
+ /**
+ * Call superclass validate.
+ * If returns null, return an empty ActionErrors for the
+ * benefit of our subclasses.
+ */
+ public ActionErrors validate(ActionMapping mapping,
+ HttpServletRequest request) {
+
+ // First validate ourself
+ ActionErrors errors = super.validate(mapping,request);
+ if (null==errors) errors = new ActionErrors();
+
+ // Then validate our business request
+ if ((isMutable()) && (errors.empty())) {
+
+ // Find our business request type
+ BizFormBean bizFormBean = (BizFormBean)
+ mapping.getMappings().getServlet().findFormBean(mapping.getName());
+ String bizType = bizFormBean.getBizType();
+
+ if ((errors.empty()) && (null!=bizType)) {
+
+ // Generate and populate our business request
+ Messages messages = new MessagesImpl();
+ try {
+
+ BizRequest bizRequest = createBizRequest(bizType);
+ // Populate the business request with ourselves
+ // merged with any user profile properties
+ Map properties = merge(getUserProfile());
+ BeanUtils.copyProperties(bizRequest,properties);
+
+ }
+ catch (Throwable t) {
+
+ messages.add(new MessageImpl(
+ Tokens.ERROR_GENERAL,
+ t.toString()
+ ));
+
+ }
+
+ // Validate our business request
+ if (messages.isEmpty()) {
+ messages.add(
+ bizRequest.validate(mapping.getAttribute()));
+ }
+ if (messages.isEmpty()) {
+
+ setBizRequest(bizRequest);
+ }
+ else {
+
+ setBizRequest(null);
+
+ addMessages(errors,messages);
+ }
+
+ } // end errors empty
+
+ } // end isMutable
+
+ return errors;
+
+ }
+
+} // end BizFormImpl
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ContinueAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ContinueAction.java
new file mode 100644
index 0000000..1c10c0e
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ContinueAction.java
@@ -0,0 +1,66 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+
+/**
+ * Standard Action to forward control to continue.
+ * Useful for prototyping flow during development,
+ * and for creating blank forms for new input.
+ * <p>
+ * Equivalent to org.apache.struts.action.ForwardAction
+ * but uses ActionForward semantics.
+ * <p>
+ * This class extends BaseAction to provide
+ * cross-compatibility with Struts 1.1 and 1.0
+ *
+ * @version $Rev$ $Date$
+ */
+public final class ContinueAction extends BaseAction {
+
+ /**
+ * Forward to the "continue" ActionForward.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ return mapping.findForward(Tokens.CONTINUE);
+
+ }
+
+} // end ContinueAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ExistsAttributeAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ExistsAttributeAction.java
new file mode 100644
index 0000000..4841405
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ExistsAttributeAction.java
@@ -0,0 +1,123 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionError;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+/**
+ * Remove an object from the user's session.
+ * The name of the attribute is passed via the parameter property.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class ExistsAttributeAction extends BaseAction {
+
+ /**
+ * Find "success" if attribute exists, or "failure" if not.
+ *
+ * The servlet context and attributes are specified as the
+ * parameters property, seperated by semi-colons
+ * [parameter="application;HOURS].
+ * non-error state.
+ *
+ * To indicatethat all scopes are to be checked,
+ * specify an asterisk instead of the scope name
+ * [parameter="*;HOURS].
+ *
+ * If both parameters are not given, an error is set.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ * @todo Add support for multiple attributes
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ String[] parameters = tokenize(mapping.getParameter());
+
+ // If not 2+ parameters, bail
+ if (2>parameters.length) {
+ ActionErrors errors = new ActionErrors();
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.PROCESS_MISSING_PARAMETER));
+ saveErrors(request,errors);
+ return mapping.findForward(Tokens.FAILURE);
+ }
+
+ String scope = parameters[0];
+ Object bean = null;
+ String name = parameters[1];
+
+ // :TODO: Add support for multiple attributes
+
+ boolean any = ("*".equals(name));
+
+ if (any) {
+
+ bean = request.getAttribute(name);
+
+ if (null==bean)
+ bean = request.getSession().getAttribute(name);
+
+ if (null==bean)
+ bean = servlet.getServletContext().getAttribute(name);
+
+ } // end any
+
+ else {
+
+ if (Tokens.REQUEST.equals(scope))
+ bean = request.getAttribute(name);
+
+ if (Tokens.SESSION.equals(scope))
+ bean = request.getSession().getAttribute(name);
+
+ if (Tokens.APPLICATION.equals(scope))
+ bean = servlet.getServletContext().getAttribute(name);
+
+ } // end !any
+
+
+ if (null==bean) {
+
+ return mapping.findForward(Tokens.FAILURE);
+
+ }
+
+ return mapping.findForward(Tokens.SUCCESS);
+ }
+
+
+} // end ExistsAttribute
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/FindForwardAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/FindForwardAction.java
new file mode 100644
index 0000000..978a6f4
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/FindForwardAction.java
@@ -0,0 +1,78 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+
+/**
+ * Scan request parameters for the name of a local or global
+ * forward. If one is found, use it. If not, return null.
+ * <p>
+ * This class extends BaseAction to provide
+ * cross-compatibility with Struts 1.1 and 1.0
+ *
+ * @version $Rev$ $Date$
+ */
+public final class FindForwardAction extends BaseAction {
+
+ /**
+ * Scan request parameters for the name of a local or global
+ * forward. If one is found, use it. If not, return null.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ String forwards[] = mapping.findForwards();
+
+ /* -- non-deprecated version for 1.1
+ ApplicationConfig config = (ApplicationConfig)
+ request.getAttribute(Action.APPLICATION_KEY);
+ ForwardConfig forwards[] = config.findForwardConfigs();
+ */
+
+ for (int i=0; i<forwards.length; i++) {
+ if (request.getParameter(forwards[i])!=null) {
+ // Return the required ActionForward instance
+ return mapping.findForward(forwards[i]);
+ }
+ }
+
+ return null;
+
+ }
+
+} // end FindForwardAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ImageButtonBean.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ImageButtonBean.java
new file mode 100644
index 0000000..9d2e932
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ImageButtonBean.java
@@ -0,0 +1,51 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+/**
+ * Generic bean to use with image buttons.
+ */
+public final class ImageButtonBean extends Object {
+
+ private String x = null;
+ private String y = null;
+
+ public String getX() {
+ return (this.x);
+ }
+
+ public void setX(String x) {
+ this.x = x;
+ }
+
+ public String getY() {
+ return (this.y);
+ }
+
+ public void setY(String y) {
+ this.y = y;
+ }
+
+ public boolean isSelected() {
+ return ((x!=null) || (y!=null));
+ }
+
+} // end ImageButtonBean
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/MenuForm.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/MenuForm.java
new file mode 100644
index 0000000..52be304
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/MenuForm.java
@@ -0,0 +1,231 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+import org.apache.struts.action.ActionForm;
+
+
+/**
+ * Generic properties for use with menu items.
+ */
+public class MenuForm extends ActionForm {
+
+
+// ------------------------------------------------------- Properties
+
+
+ /**
+ * A generic name field,
+ * use to store a selected option or the name of a property.
+ * <p>
+ * For example, to indicate a search by product, you might set
+ * keyName=product and keyValue=Scaffold.
+ * <p>
+ * When both name and value are used, value should be the "scalar".
+ * <p>
+ * In forms, the abbreviations N and V may be used.
+ * (See Public Methods section.)
+ */
+ private String keyName = null;
+
+
+ /**
+ * Return the keyName.
+ */
+ public String getKeyName() {
+ return this.keyName;
+ }
+
+
+ /**
+ * Set the keyName.
+ *
+ * @param keyName The new keyName
+ */
+ public void setKeyName(String keyName) {
+ this.keyName = keyName;
+ }
+
+
+ /**
+ * A generic value field,
+ * use to store a value associated with an option or the
+ * value of a property.
+ * <p>
+ * For example, to indicate a search by product you might set
+ * keyName=product and keyValue=Scaffold.
+ * <p>
+ * When both key and value are used, value should be the "scalar".
+ */
+ private String keyValue = null;
+
+
+ /**
+ * Return the value.
+ */
+ public String getKeyValue() {
+ return this.keyValue;
+ }
+
+
+ /**
+ * Set the value.
+ *
+ * @param keyValue The new value
+ */
+ public void setKeyValue(String keyValue) {
+ this.keyValue = keyValue;
+ }
+
+
+ /**
+ * The page, for use in workflows.
+ */
+ private int page = 0;
+
+
+ /**
+ * Return the page.
+ */
+ public int getPage() {
+ return this.page;
+ }
+
+
+ /**
+ * Set the page key
+ *
+ * @param page The new page key
+ */
+ public void setPage(int page) {
+ this.page = page;
+ }
+
+
+ /**
+ * The name of a logical forward
+ * for use in mapping a forward to a menu option.
+ */
+ private String dispatch = null;
+
+
+ /**
+ * Return the dispatch.
+ */
+ public String getDispatch() {
+ return this.dispatch;
+ }
+
+
+ /**
+ * Set the dispatch
+ *
+ * @param dispatch The new dispatch
+ */
+ public void setDispatch(String dispatch) {
+ this.dispatch = dispatch;
+ }
+
+
+
+// ----------------------------------------------------- Public Methods
+
+
+ /**
+ * Return the keyName abbreviated as N.
+ */
+ public String getN() {
+ return getKeyName();
+ }
+
+
+ /**
+ * Set the keyName abbreviated as N.
+ *
+ * @param keyName The new keyName
+ */
+ public void setN(String keyName) {
+ setKeyName(keyName);
+ }
+
+
+ /**
+ * Return the Option (alias for name).
+ * <p>
+ * Mnemoric: O-N / Name
+ */
+ public String getO() {
+ return getKeyName();
+ }
+
+
+ /**
+ * Set the Option (alias for name)
+ * <p>
+ * Mnemoric: O-N / Name
+ *
+ * @param keyName The new keyName
+ */
+ public void setO(String keyName) {
+ setKeyName(keyName);
+ }
+
+
+ /**
+ * Return the value abbreviated as V.
+ */
+ public String getV() {
+ return getKeyValue();
+ }
+
+
+ /**
+ * Set the value abbreviated as V.
+ *
+ * @param keyValue The new keyValue
+ */
+ public void setV(String keyValue) {
+ setKeyValue(keyValue);
+ }
+
+
+ /**
+ * Return the Text (alias for value).
+ * <p>
+ * Mnemoric: T-V / value
+ */
+ public String getT() {
+ return getKeyValue();
+ }
+
+
+ /**
+ * Set the Text (alias for value)
+ * <p>
+ * Mnemoric: T-V / value
+ *
+ * @param keyValue The new KeyValue
+ */
+ public void setT(String keyValue) {
+ setKeyValue(keyValue);
+ }
+
+
+} // end MenuForm
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/MenuRelayAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/MenuRelayAction.java
new file mode 100644
index 0000000..df354c0
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/MenuRelayAction.java
@@ -0,0 +1,79 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.text.ConvertUtils;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.scaffold.BaseAction;
+import org.apache.struts.scaffold.BaseForm;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ * Standard Action to forward control to another mapping
+ * given as a runtime parameter (?dispatch=),
+ * after running any model classes.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class MenuRelayAction extends BaseAction {
+
+
+ /**
+ * Looks for a runtime parameter named "dispatch",
+ * and uses its value to search for an ActionForward.
+ * If a "dispatch" parameter is not available,
+ * and the form is a BaseForm istance, then the
+ * dispatch property is checked.
+ * If dispatch is blank, the mapping parameter is
+ * checked.
+ * Finally, if all of these are blank,
+ * MenuRelayAction looks for a "menu" forward.
+ * <p>
+ * This is useful for returning to a submenu when
+ * a MenuForm is kept in the session for each user.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ String forward = request.getParameter(Tokens.DISPATCH);
+ if ((ConvertUtils.blank(forward)) && (form instanceof BaseForm)) {
+ BaseForm baseForm = (BaseForm) form;
+ forward = baseForm.getDispatch();
+ }
+ if (ConvertUtils.blank(forward)) forward = mapping.getParameter();
+ if (ConvertUtils.blank(forward)) forward = Tokens.MENU;
+ return mapping.findForward(forward);
+ }
+
+} // end RelayHelperAction
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/NullForm.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/NullForm.java
new file mode 100644
index 0000000..71ff3d6
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/NullForm.java
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.scaffold;
+
+
+import org.apache.struts.action.ActionForm;
+
+
+/**
+ * Empty (or "null") form for use with "formless" forms.
+ * The Struts JSP tags require a form bean to create elements like
+ * buttons, even if one is not actually needed.
+ * The NullForm placates the tag by providing an empty form.
+ */
+public final class NullForm extends ActionForm {
+
+ // blank form for use with command buttons
+
+} // end NullForm
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ParameterAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ParameterAction.java
new file mode 100644
index 0000000..cb87fb6
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ParameterAction.java
@@ -0,0 +1,81 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+
+/**
+ * Standard Action to append a passed parameter to query string.
+ * <p>
+ * This class extends BaseAction to provide
+ * cross-compatibility with Struts 1.1 and 1.0
+ *
+ * @version $Rev$ $Date$
+ */
+public class ParameterAction extends BaseAction {
+
+ /**
+ * Append parameter to a query string.
+ * The "dispatch" parameter is used to select a forward.
+ * The value of the parameter named by the "parameter" property
+ * is concaternated to the forward's path.
+ * No parsing of the path is performed at this time.
+ * The value is simply appended.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // Get "dispatch" parameter
+ String parameter = request.getParameter(Tokens.DISPATCH);
+
+ // Get parameter name for this mapping
+ String paramName = mapping.getParameter();
+
+ // Get stub URI from mapping (/do/whatever?paramName=)
+ StringBuffer path = new StringBuffer(64);
+ ActionForward template = mapping.findForward(parameter);
+ path.append(template.getPath());
+ // Append the value passed (/do/whatever?paramName=paramProperty)
+ path.append(request.getParameter(paramName));
+
+ // Return a new forward based on stub+value
+ return new ActionForward(path.toString(),template.getRedirect());
+
+ }
+
+} // end ParameterAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessAction.java
new file mode 100644
index 0000000..28b6bd0
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessAction.java
@@ -0,0 +1,500 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.scaffold.lang.Log;
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.util.ProcessBean;
+import org.apache.commons.scaffold.util.ProcessResult;
+import org.apache.struts.action.*;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+
+/**
+ * Advanced framework class to instantiate and execute helper beans
+ * and process the result.
+ *
+ * @version $Rev$ $Date$
+ * @deprecated Use BizAction instead
+ */
+public class ProcessAction extends BaseHelperAction {
+
+
+// --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Exposes result in a servlet context.
+ *
+ * @param request the request being serviced
+ * @param name The name to use in scope
+ * @param scope The scope to set the attribute in
+ * @param bean The attribute to be set
+ */
+ protected void exposeInScope(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ String name,
+ String scope,
+ Object bean) {
+
+ if (null==scope) {
+ //
+ }
+ else if (Tokens.REQUEST.equals(scope)) {
+ request.setAttribute(name,bean);
+ }
+ else if (Tokens.SESSION.equals(scope)) {
+ request.getSession().setAttribute(name,bean);
+ }
+ else if (Tokens.APPLICATION.equals(scope)) {
+ servlet.getServletContext().setAttribute(name,bean);
+ }
+ else {
+ StringBuffer sb = new StringBuffer("exposeInScope: ");
+ sb.append(scope);
+ sb.append(Tokens.INVALID_SCOPE);
+ throw new IllegalArgumentException(sb.toString());
+ }
+
+ } // end exposeInScope
+
+
+ /**
+ * Save result object to servlet context.
+ * <p>
+ * <code>result.getData()</code> must return non-null.
+ * If <code>result.getName()</code> is null, the mapping's attribute
+ * (<code>mapping.getAttribute()</code>) is used instead.
+ * By default, this is the <code>form-bean</code>'s name.
+ * <p>
+ * If data is a Collection, only the first element is stored.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param result The ProcessResult we are handling
+ */
+ protected void checkDataSingle(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ProcessResult result) {
+
+ String name = result.getName();
+ if (null==name) {
+ // use form-bean or mapping name
+ name = mapping.getAttribute();
+ result.setName(name);
+ }
+ String scope = result.getScope();
+ Object bean = result.getData();
+
+ // if data is collection, use first element
+ if (bean instanceof Collection) {
+ Collection collection = (Collection) bean;
+ if (collection.isEmpty()) {
+ // for lack of a better idea, get a fresh form-bean
+ // this will return null if there is not a form-bean
+ // associated with this mapping
+ bean = createHelperBean(request,mapping.getName());
+ }
+ else {
+ bean = collection.iterator().next();
+ }
+ }
+ if (result.isExposed()) {
+ exposeInScope(request,response,name,scope,bean);
+
+ }
+
+ } // end checkDataSingle
+
+
+ /**
+ * Save result object to servlet context.
+ * <p>
+ * <code>result.getData()</code> must return non-null.
+ * If <code>result.getName()</code> is null, the mapping's attribute
+ * (<code>mapping.getAttribute()</code>) is used instead.
+ * By default, this is the <code>form-bean</code>'s name.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param result The ProcessResult we are handling
+ */
+ protected void checkData(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ProcessResult result) {
+
+ if (result.isSingleForm()) {
+ checkDataSingle(mapping,request,response,result);
+ }
+ else {
+
+ String name = result.getName();
+ if (null==name) {
+ name = Tokens.LIST_KEY;
+ result.setName(name);
+ }
+ String scope = result.getScope();
+ Object bean = result.getData();
+
+ if (result.isExposed()) {
+ exposeInScope(request,response,name,scope,bean);
+ }
+ }
+
+ } // end checkData
+
+
+ /**
+ * Stores informational messages for display.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param processResult The ProcessResult we are handling
+ */
+ protected void checkMessages(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ProcessResult processResult) {
+
+ saveMessages(request,processResult.getMessages());
+
+ } // end checkMessages
+
+
+ /**
+ * Process new dispatch advice passed by the business tier.
+ * <p>
+ * This is used to route control to another location besides
+ * the default "success" forward registered with the controller.
+ *
+ * The business tier can pass back either a path or the name of
+ * an ActionForward.
+ * checkDispatch() will then create an ActionForward to return
+ * and save it in the request under the SUCCESS token.
+ * The <code>findSuccess()</code> will check for this attribute
+ * before returning the controller's default.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param processResult The ProcessResult we are handling
+ */
+ protected void checkDispatch(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ProcessResult processResult) {
+
+ String dispatch = processResult.getDispatch();
+ ActionForward forward = null;
+
+ if (processResult.isDispatchPath()) {
+ forward = new ActionForward(dispatch);
+ }
+ else {
+ forward = mapping.findForward(dispatch);
+ }
+
+ // Our findSuccess looks for this
+ request.setAttribute(Tokens.SUCCESS,forward);
+
+ } // end checkDispatch
+
+
+// --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Return the appropriate ActionForward for error or failure
+ * conditions.
+ * First checks for a FAILURE ActionForward stored in the request.
+ * If an override is not found, returns the result of the
+ * superclass method.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ * @return The ActionForward representing FAILURE
+ * or null if a FAILURE forward has not been specified.
+ */
+ protected ActionForward findFailure(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // Did someone leave us a forward?
+ ActionForward forward = (ActionForward)
+ request.getAttribute(Tokens.FAILURE);
+
+ if (null==forward) {
+ // No override, use default
+ forward = super.findFailure(mapping,form,request,response);
+ }
+ else {
+ // Clear advice from the request
+ request.setAttribute(Tokens.FAILURE,null);
+ }
+
+ return forward;
+
+ } // end findFailure
+
+
+ /**
+ * Optional extension point for pre-processing.
+ * Default method does nothing.
+ * To branch to another URI, return an non-null ActionForward.
+ * If errors are logged (getErrors() et al),
+ * default behaviour will branch to findFailure().
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The resonse we are creating
+ */
+ protected void preProcess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // Check for cancelled
+ ActionForward forward = mapping.findForward(Tokens.CANCEL);
+ if ((null!=forward) && (isCancelled(request))) {
+ // Our findFailure looks for this
+ request.setAttribute(Tokens.FAILURE,forward);
+ // Post cancel error message
+ ActionErrors errors = getErrors(request,true);
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.ERROR_CANCEL));
+ return;
+ }
+
+ // Check for missing token
+ forward = mapping.findForward(Tokens.GET_TOKEN);
+ if ((null!=forward) && (!isTokenValid(request))) {
+ // Our findFailure looks for this
+ request.setAttribute(Tokens.FAILURE,forward);
+ // Post token error message
+ ActionErrors errors = getErrors(request,true);
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.ERROR_TOKEN));
+ return;
+ }
+ if (null!=forward) {
+ // reset to guard against duplicate request
+ resetToken(request);
+ }
+
+ // Check for save token directive (do this last)
+ forward = mapping.findForward(Tokens.SET_TOKEN);
+ if (null!=forward) saveToken(request);
+
+
+ } // end preProcess
+
+
+ /**
+ * Check outcome, if any; recurse if container for other outcomes.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param request The HTTP request we are processing
+ * @param result The ProcessResult we are handling
+ */
+ protected void checkOutcome(
+ ActionMapping mapping,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ProcessResult result) throws Exception {
+
+ if (result!=null) {
+
+ if (result.isAggregate()) {
+ // recurse for each ProcessResult in collection
+ Collection collection = (Collection)
+ result.getData();
+ Iterator iterator = collection.iterator();
+ while (iterator.hasNext()) {
+ ProcessResult nextResult =
+ (ProcessResult) iterator.next();
+ checkOutcome(mapping,request,response,nextResult);
+ }
+ }
+
+ else {
+ // call extension points for whatever is returned
+ if (result.isData())
+ checkData(mapping,request,response,result);
+
+ if (result.isMessages())
+ checkMessages(mapping,request,response,result);
+
+ if (result.isDispatch())
+ checkDispatch(mapping,request,response,result);
+ }
+ }
+
+ else {
+ throw new Exception(Log.PROCESS_RESULT_NULL);
+ }
+
+ } // end checkOutcome
+
+
+ /**
+ * Return the appropriate ActionForward for the nominal,
+ * non-error state.
+ * First checks for a SUCCESS ActionForward stored in the request.
+ * If an override is not found, returns the result of the
+ * superclass method.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ * @return The ActionForward representing SUCCESS
+ * or null if a SUCCESS forward has not been specified.
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ // Did someone leave us a forward?
+ ActionForward forward = (ActionForward)
+ request.getAttribute(Tokens.SUCCESS);
+
+ if (null==forward) {
+ // No override, use default
+ forward = super.findSuccess(mapping,form,request,response);
+ }
+ else {
+ // Clear advice from the request
+ request.setAttribute(Tokens.SUCCESS,null);
+ }
+
+ return forward;
+
+ } // end findSuccess
+
+
+ /**
+ * Retrieve from session under known key
+ * (<code>ProcessBean.USER_PROFILE_KEY</code>).
+ * Override this approach to implement another method (e.g cookies).
+ * Also revise UpdateProfile action-mapping to store changes.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The ActionForm
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ */
+ protected BaseForm getUserProfile(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ return(BaseForm)
+ request.getSession().getAttribute(ProcessBean.USER_PROFILE_KEY);
+
+ } // end getUserProfile
+
+
+ /**
+ * Assume that helpers are ProcessBeans, execute each, and
+ * process outcome.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The ActionForm
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @param helpers The object instantiated from type given as parameter.
+ * @exception IOException if an input/output error occurs
+ * @exception ServletException if a servlet exception occurs
+ */
+ protected void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ Object[] helpers) throws Exception {
+
+ // Retrieve user profile, if any
+ BaseForm userBean =
+ getUserProfile(mapping,form,request,response);
+
+ Map properties = null;
+ for (int i = 0; i < helpers.length; i++) {
+
+ // Get helper instantiated by ancestor
+ ProcessBean dataBean = (ProcessBean) helpers[i];
+
+ properties = null;
+ if (null!=form) {
+ if (form instanceof BaseForm) {
+
+ BaseForm formBean = (BaseForm) form;
+
+ // Merge user profile (if found)
+ // and our form into a single map
+ properties = formBean.merge(userBean);
+
+ // Pass up the Locale, RemoteNode, and RemoteServer (if any)
+ dataBean.setLocale(formBean.getSessionLocale());
+ dataBean.setRemoteNode(getRemoteNode(request));
+ dataBean.setRemoteServer(getRemoteServer());
+ }
+ else {
+ properties = PropertyUtils.describe(form);
+ }
+ } // end null form
+ else if (null!=userBean) {
+ // if no form, but is profile, still use profile
+ properties = PropertyUtils.describe(userBean);
+ }
+
+ // Execute business logic, using values from map
+ ProcessResult result = (ProcessResult)
+ dataBean.execute(properties);
+
+ // Analyze result of business logic
+ checkOutcome(mapping,request,response,result);
+
+ } // end for
+
+ } // end executeLogic
+
+} // end ProcessAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessDispatchAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessDispatchAction.java
new file mode 100644
index 0000000..3e5434b
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessDispatchAction.java
@@ -0,0 +1,180 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+
+import java.io.IOException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Log;
+import org.apache.commons.scaffold.lang.Tokens;
+import org.apache.commons.scaffold.util.ProcessBean;
+import org.apache.commons.scaffold.util.ProcessResult;
+import org.apache.commons.scaffold.util.ProcessResultBase;
+import org.apache.commons.scaffold.util.ResultList;
+import org.apache.commons.scaffold.util.ResultListBase;
+
+
+/**
+ * ProcessFormAction that accepts the name of a class and a method
+ * with the signature "Object method(Object)" as the parameter.
+ * [org.apache.cerebus.Account;store].
+ *
+ * @version $Rev$ $Date$
+ */
+public class ProcessDispatchAction extends ProcessFormAction {
+
+ /**
+ * The set of argument type classes for the reflected method call.
+ * These are the same for all calls, so calculate them only once.
+ */
+ private static final Class types[] = { Object.class };
+
+
+ /**
+ * Error handler.
+ * Posts a message template and two parameters in a ProcessResult.
+ */
+ public void processError(ProcessResult result, String template,
+ ActionMapping mapping) {
+ result = new ProcessResultBase(this);
+ result.addMessage(template);
+ result.addMessage(mapping.getPath());
+ result.addMessage(mapping.getParameter());
+ }
+
+
+// --------------------------------------------------------- Public Methods
+
+ /**
+ * Instantiate helper object from the type given as the
+ * first ActionMapping parameter and execute the method given
+ * as the second parameter (delimited with semicolons).
+ * <p>
+ * Otherwise operates as a ProcessAction.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The ActionForm
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * <p>
+ * @exception IOException if an input/output error occurs
+ * @exception ServletException if a servlet exception occurs
+ * @todo Refactor so both Process*Actions can call core logic
+ * @todo Add support for mutliple object/methods
+ */
+ public void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Retrieve user profile, if any
+ BaseForm userBean =
+ getUserProfile(mapping,form,request,response);
+
+ Map properties = null;
+
+ // Munge the parameter property
+ String[] tokens = tokenize(mapping.getParameter());
+
+ // Create our ProcessBean helper
+ Object helper = createHelperObject(request,tokens[0]);
+ ProcessBean dataBean = (ProcessBean) helper;
+
+ // Pass along the helper's parameter, if any
+ if (tokens.length>2) {
+ dataBean.setParameter(tokens[2]);
+ }
+
+ properties = null;
+ if (null!=form) {
+ if (form instanceof BaseForm) {
+
+ BaseForm formBean = (BaseForm) form;
+
+ // Merge user profile (if found)
+ // and our form into a single map
+ properties = formBean.merge(userBean);
+
+ // Pass up the Locale and RemoteServer (if any)
+ dataBean.setLocale(formBean.getSessionLocale());
+ dataBean.setRemoteServer(getRemoteServer());
+ }
+ else {
+ properties = PropertyUtils.describe(form);
+ }
+ } // end null form
+ else if (null!=userBean) {
+ // if no form, but is profile, still use profile
+ properties = PropertyUtils.describe(userBean);
+ }
+
+ // Execute business logic, using values from map
+ Method method = dataBean.getClass().getMethod(tokens[1],types);
+ Object args[] = { properties };
+
+ ProcessResult result = null;
+
+ try {
+
+ result = (ProcessResult) method.invoke(dataBean,args);
+
+ }
+
+ catch (ClassCastException e) {
+
+ processError(result,Tokens.ERROR_DISPATCH_RETURN,mapping);
+ }
+
+ catch (IllegalAccessException e) {
+
+ processError(result,Tokens.ERROR_DISPATCH_RETURN,mapping);
+ }
+
+ catch (InvocationTargetException e) {
+
+ // Rethrow the target exception if possible so that the
+ // exception handling machinery can deal with it
+ Throwable t = e.getTargetException();
+ if (t instanceof Exception) {
+ throw ((Exception) t);
+ } else {
+ processError(result,Tokens.ERROR_DISPATCH,mapping);
+ }
+ }
+
+ // Execute business logic, using map
+ checkOutcome(mapping,request,response,result);
+ }
+
+} // end ProcessDispatchAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessFormAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessFormAction.java
new file mode 100644
index 0000000..4aef961
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/ProcessFormAction.java
@@ -0,0 +1,135 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.scaffold;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.beanutils.BeanUtils;
+
+import org.apache.commons.scaffold.lang.Log;
+import org.apache.commons.scaffold.lang.Tokens;
+
+/**
+ * ProcessAction subclass that checks to see if a another
+ * bean exists in the request scope before overwriting it.
+ * If another bean is present, it is populated from the
+ * ProcessBean.
+ * <P>
+ * Any JavaBean can be used to populate a Struts presentation
+ * page, and it is not always necessary to transfer data from
+ * a business bean to a form bean.
+ * Other times, the form bean will have special helper
+ * properties for the benefit of the presentation layer.
+ * For example, a second password field may be needed to
+ * validate the user's data-entry but would not be part of
+ * the business API.
+ * <P>
+ * The <CODE>ProcessFormAction</CODE> will check to see if
+ * another bean is in scope (presumably a form bean).
+ * If another bean exists, ProcessFormAction populates it
+ * from the business bean,
+ * The net result is an automatic data transfer from a
+ * business bean to the form bean.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ProcessFormAction extends ProcessAction {
+
+
+// --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Exposes result in a servlet context.
+ * If there is an existing bean with same attribute name in the target
+ * context,
+ * then the matching properties on that bean are populated with the
+ * result.
+ * :TODO: Change from BeanUtil.populate to copyProperties
+ * in 1.1 version.
+ *
+ * @param request the request being serviced
+ * @param name The name to use in scope
+ * @param scope The scope to set the attribute in
+ * @param bean The attribute to be set
+ */
+ protected void exposeInScope(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ String name,
+ String scope,
+ Object bean) {
+
+ if (null==scope) {
+ //
+ }
+ if (null==bean) super.exposeInScope(request,response,name,scope,bean);
+ else if (Tokens.REQUEST.equals(scope)) {
+ Object form = request.getAttribute(name);
+ if (null==form) {
+ request.setAttribute(name,bean);
+ }
+ else {
+ try {
+ BeanUtils.copyProperties(form,bean);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+ else if (Tokens.SESSION.equals(scope)) {
+ Object form = request.getSession().getAttribute(name);
+ if (null==form) {
+ request.getSession().setAttribute(name,bean);
+ }
+ else {
+ try {
+ BeanUtils.copyProperties(form,bean);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+ else if (Tokens.APPLICATION.equals(scope)) {
+ Object form = servlet.getServletContext().getAttribute(name);
+ if (null==form) {
+ servlet.getServletContext().setAttribute(name,bean);
+ }
+ else {
+ try {
+ BeanUtils.copyProperties(form,bean);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+ else {
+ StringBuffer sb = new StringBuffer("exposeInScope: ");
+ sb.append(scope);
+ sb.append(Tokens.INVALID_SCOPE);
+ throw new IllegalArgumentException(sb.toString());
+ }
+
+ } // end exposeInScope()
+
+} // end ProcessFormAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RecreateSessionAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RecreateSessionAction.java
new file mode 100644
index 0000000..2768dd3
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RecreateSessionAction.java
@@ -0,0 +1,76 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import java.util.Locale;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.Globals;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+
+/**
+ * Create a new session, perserving any locale attribute
+ * from the current session.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class RecreateSessionAction extends BaseAction {
+
+
+ /**
+ * Creates a new session, perserving any prior Locale attribute.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ * @todo Add support for multiple attributes
+ * @fixme Needs to be tested.
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ HttpSession session = request.getSession();
+
+ Locale locale = (Locale) session.getAttribute(Globals.LOCALE_KEY);
+
+ session.invalidate();
+
+ session = request.getSession(true);
+
+ session.setAttribute(Globals.LOCALE_KEY,locale);
+
+ return mapping.findForward(Tokens.SUCCESS);
+ }
+
+} // end RecreateSessionAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RelayAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RelayAction.java
new file mode 100644
index 0000000..7060dc4
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RelayAction.java
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+
+/**
+ * Standard Action to forward control to another mapping
+ * given as a runtime parameter (?dispatch=).
+ * <p>
+ * This class extends BaseAction to provide
+ * cross-compatibility with Struts 1.1 and 1.0
+ *
+ * @version $Rev$ $Date$
+ */
+public final class RelayAction extends BaseAction {
+
+ /**
+ * Looks for a runtime parameter named "dispatch",
+ * and uses its value to search for an ActionForward.
+ * <p>
+ * <code>dispatch=findByTile</code> will return
+ * the ActionForward named "findByTitle".
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ return mapping.findForward(request.getParameter(Tokens.DISPATCH));
+
+ } // end findSuccess
+
+} // end RelayAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RemoveAttributeAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RemoveAttributeAction.java
new file mode 100644
index 0000000..c4ecdba
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/RemoveAttributeAction.java
@@ -0,0 +1,143 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+import org.apache.struts.action.ActionError;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+
+/**
+ * Remove an object from the user's session.
+ * The name of the attribute is passed via the parameter property.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class RemoveAttributeAction extends BaseAction {
+
+
+ /**
+ * // :FIXME: Needs to be tested.<p>
+ * Attempt to remove an attribute from a servlet context.
+ * Find "success" if attribute exists, or "failure" if not.
+ *
+ * The servlet context and attributes are specified as the
+ * parameters property, seperated by semi-colons
+ * [parameter="application;HOURS].
+ * non-error state.
+ *
+ * To indicate that all scopes are to be checked,
+ * specify an asterisk instead of the scope name
+ * [parameter="*;HOURS]. The attribute will be removed
+ * from <b>only</b> the first context found.
+ *
+ * If both parameters are not given, an error is set.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request
+ * @param request The HTTP request we are processing
+ * @param response The response we are creating
+ * @todo Add support for multiple attributes
+ * @fixme Needs to be tested.
+ */
+ protected ActionForward findSuccess(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ String[] parameters = tokenize(mapping.getParameter());
+
+ // If not 2+ parameters, bail
+ if (2>parameters.length) {
+ ActionErrors errors = new ActionErrors();
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError(Tokens.PROCESS_MISSING_PARAMETER));
+ saveErrors(request,errors);
+ return mapping.findForward(Tokens.FAILURE);
+ }
+
+ String scope = parameters[0];
+ Object bean = null;
+ String name = parameters[1];
+
+ // :TODO: Add support for multiple attributes
+
+ boolean any = ("*".equals(scope));
+
+ if (any) {
+
+ bean = request.getAttribute(name);
+ if (null!=bean)
+ request.removeAttribute(name);
+
+ if (null==bean) {
+ bean = request.getSession().getAttribute(name);
+ if (null!=bean)
+ request.getSession().removeAttribute(name);
+ }
+
+ if (null==bean) {
+ bean = servlet.getServletContext().getAttribute(name);
+ if (null!=bean)
+ servlet.getServletContext().removeAttribute(name);
+ }
+
+ } // end any
+
+ else {
+
+ if (Tokens.REQUEST.equals(scope)) {
+ bean = request.getAttribute(name);
+ request.removeAttribute(name);
+ }
+
+ if (Tokens.SESSION.equals(scope)) {
+ bean = request.getSession().getAttribute(name);
+ request.getSession().removeAttribute(name);
+ }
+
+ if (Tokens.APPLICATION.equals(scope)) {
+ bean = servlet.getServletContext().getAttribute(name);
+ servlet.getServletContext().removeAttribute(name);
+ }
+
+ } // end !any
+
+
+ if (null==bean) {
+
+ return mapping.findForward(Tokens.FAILURE);
+
+ }
+
+ return mapping.findForward(Tokens.SUCCESS);
+ }
+
+} // end RemoveAttribute
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/Resources.properties b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/Resources.properties
new file mode 100644
index 0000000..a3b8e67
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/Resources.properties
@@ -0,0 +1,44 @@
+# @version $Revision: 1.4 $ $Date$
+#
+# --!! FOR REFERENCE ONLY !!--
+# --!! YOU MUST COPY THESE TO YOUR APPLICATION'S FILE !!--
+# -- See also constants in lang/Tokens --
+#
+#
+errors.header=
+errors.footer=
+error.cancel=Operation cancelled.
+error.detail={0}
+error.general=The process did not complete. Details should follow.
+error.token=Request could not be completed. Operation is not in sequence.
+error.dispatch=Process could not be dispatched. Path: [{0}]. Parameter: [{1}].
+error.dispatch.return=The return value of the process is not correct. Path: [{0}]. Parameter: [{1}].
+# -- validator --
+errors.required={0} is required.
+errors.minlength={0} can not be less than {1} characters.
+errors.maxlength={0} can not be greater than {1} characters.
+errors.invalid={0} is invalid.
+errors.byte={0} must be an byte.
+errors.short={0} must be an short.
+errors.integer={0} must be an integer.
+errors.long={0} must be an long.
+errors.float={0} must be an float.
+errors.double={0} must be an double.
+errors.date={0} is not a date.
+errors.range={0} is not in the range {1} through {2}.
+errors.creditcard={0} is not a valid credit card number.
+errors.email={0} is an invalid e-mail address.
+# -- data --
+data.access.denied=Access denied.
+data.access.error=Unable to access database.
+data.access.empty=Requested records were not found.
+data.record.inserted=Record {0} inserted.
+data.record.updated=Record {0} updated.
+data.record.deleted=Record {0} deleted.
+data.record.recycled=Record {0} marked for deletion.
+data.record.restored=Record {0} restored.
+data.record.duplicate={0} is already in use. Please select another value.
+data.transfer.error=Unable to transfer data.
+# -- process --
+process.complete=Process complete.
+process.missing.parameter=A required parameter is missing.
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SetPathsAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SetPathsAction.java
new file mode 100644
index 0000000..e20d341
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SetPathsAction.java
@@ -0,0 +1,73 @@
+/*
+ * $Id$
+ *
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.struts.scaffold.BaseAction;
+
+
+/**
+ * Standard Action to set the paths from
+ * enumerated forwards as request attributes.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class SetPathsAction extends BaseAction {
+
+
+ /**
+ * Lookup the forward each token given on the parameter property,
+ * and set its path as a request attribute under the token name.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The ActionForm
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * <p>
+ * @exception IOException if an input/output error occurs
+ * @exception ServletException if a servlet exception occurs
+ */
+ public void executeLogic(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ String[] tokens = tokenize(mapping.getParameter());
+ int helperCount = tokens.length;
+
+ for (int i=0; i<helperCount; i++) {
+ request.setAttribute(
+ tokens[i],
+ mapping.findForward(tokens[i]).getPath());
+ }
+
+ }
+
+} // end SetPathsAction
\ No newline at end of file
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SnoopAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SnoopAction.java
new file mode 100644
index 0000000..e56aee3
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SnoopAction.java
@@ -0,0 +1,174 @@
+/*
+ * $Id$
+ *
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /*
+ * Derived from the Jetty SnoopServlet
+ * <http://www.thecortex.net/clover/eg/jetty/report/default-pkg/SnoopServlet.html>
+ * and distributed under its open source license
+ * <http://jetty.mortbay.org/jetty/LICENSE.html>.
+ * The only modifications were to change the method
+ * signatures to make the servlet an Action.
+ */
+
+package org.apache.struts.scaffold;
+
+import org.apache.struts.action.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+/**
+ *
+ */
+
+public final class SnoopAction extends Action {
+
+ public ActionForward perform(ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws IOException, ServletException {
+ ActionServlet servlet = getServlet();
+ PrintWriter out = response.getWriter();
+ response.setContentType("text/plain");
+ out.println("Snoop Servlet");
+ out.println();
+ out.println("Servlet init parameters:");
+ Enumeration e = servlet.getInitParameterNames();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ String value = servlet.getInitParameter(key);
+ out.println(" " + key + " = " + value);
+ }
+ out.println();
+
+ out.println("Context init parameters:");
+ ServletContext context = servlet.getServletContext();
+ e = context.getInitParameterNames();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ Object value = context.getInitParameter(key);
+ out.println(" " + key + " = " + value);
+ }
+ out.println();
+
+ out.println("Context attributes:");
+ e = context.getAttributeNames();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ Object value = context.getAttribute(key);
+ out.println(" " + key + " = " + value);
+ }
+ out.println();
+
+ out.println("Request attributes:");
+ e = request.getAttributeNames();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ Object value = request.getAttribute(key);
+ out.println(" " + key + " = " + value);
+ }
+ out.println();
+
+ out.println("Servlet Name: " + servlet.getServletName());
+ out.println("Protocol: " + request.getProtocol());
+ out.println("Scheme: " + request.getScheme());
+ out.println("Server Name: " + request.getServerName());
+ out.println("Server Port: " + request.getServerPort());
+ out.println("Server Info: " + context.getServerInfo());
+ out.println("Remote Addr: " + request.getRemoteAddr());
+ out.println("Remote Host: " + request.getRemoteHost());
+ out.println("Character Encoding: " + request.getCharacterEncoding());
+ out.println("Content Length: " + request.getContentLength());
+ out.println("Content Type: " + request.getContentType());
+ out.println("Locale: " + request.getLocale());
+ out.println("Default Response Buffer: " + response.getBufferSize());
+ out.println();
+
+ out.println("Parameter names in this request:");
+ e = request.getParameterNames();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ String[] values = request.getParameterValues(key);
+ out.print(" " + key + " = ");
+ for (int i = 0; i < values.length; i++) {
+ out.print(values[i] + " ");
+ }
+ out.println();
+ }
+ out.println();
+
+ out.println("Headers in this request:");
+ e = request.getHeaderNames();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ String value = request.getHeader(key);
+ out.println(" " + key + ": " + value);
+ }
+ out.println();
+
+ out.println("Cookies in this request:");
+ Cookie[] cookies = request.getCookies();
+ if (cookies != null) {
+ for (int i = 0; i < cookies.length; i++) {
+ Cookie cookie = cookies[i];
+ out.println(" " + cookie.getName() + " = "
+ + cookie.getValue());
+ }
+ }
+ out.println();
+
+ out.println("Request Is Secure: " + request.isSecure());
+ out.println("Auth Type: " + request.getAuthType());
+ out.println("HTTP Method: " + request.getMethod());
+ out.println("Remote User: " + request.getRemoteUser());
+ out.println("Request URI: " + request.getRequestURI());
+ out.println("Context Path: " + request.getContextPath());
+ out.println("Servlet Path: " + request.getServletPath());
+ out.println("Path Info: " + request.getPathInfo());
+ out.println("Path Trans: " + request.getPathTranslated());
+ out.println("Query String: " + request.getQueryString());
+ out.println();
+
+ HttpSession session = request.getSession();
+ out.println("Requested Session Id: " +
+ request.getRequestedSessionId());
+ out.println("Current Session Id: " + session.getId());
+ out.println("Session Created Time: " + session.getCreationTime());
+ out.println("Session Last Accessed Time: " +
+ session.getLastAccessedTime());
+ out.println("Session Max Inactive Interval Seconds: " +
+ session.getMaxInactiveInterval());
+ out.println();
+
+ out.println("Session values: ");
+ Enumeration names = session.getAttributeNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ out.println(" " + name + " = " + session.getAttribute(name));
+ }
+ out.println("###");
+
+ return null;
+
+ }
+}
+
diff --git a/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SuccessAction.java b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SuccessAction.java
new file mode 100644
index 0000000..30240a6
--- /dev/null
+++ b/struts-sandbox/scaffold/src/java/org/apache/struts/scaffold/SuccessAction.java
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.scaffold;
+
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+
+import org.apache.commons.scaffold.lang.Tokens;
+
+
+/**
+ * Standard Action to forward control to "success".
+ * Useful for prototyping flow during development,
+ * and for creating blank forms for new input.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class SuccessAction extends Action {
+
+ /**
+ * Forward to "success" [Tokens.SUCCESS].
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ * @exception IOException if an input/output error occurs
+ * @exception ServletException if a servlet exception occurs
+ */
+ public ActionForward perform(ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws IOException, ServletException {
+
+ return mapping.findForward(Tokens.SUCCESS);
+
+ }
+
+} // end SuccessAction
\ No newline at end of file
diff --git a/struts-sandbox/struts-jericho/OVERVIEW.txt b/struts-sandbox/struts-jericho/OVERVIEW.txt
new file mode 100644
index 0000000..5d9240d
--- /dev/null
+++ b/struts-sandbox/struts-jericho/OVERVIEW.txt
@@ -0,0 +1,56 @@
+-COMPONENT OVERVIEW-
+
+Configuration registry
+* At initialization, each request adapter (servlet, filter, et cetera), adds its configuration to a single registry at a global location under a unique key.
+
+Command Context
+* Extends CoR Context to encapsulate framework members needed to process request and render response
+
+Request Adapter (servlet module, portlet, SOAP, mock)
+* Receives request from container (or TestRunner)
+* Normalizes request path (masks pattern registered with container)
+* Creates context to wrap request and response objects
+* Adds reference to its configuration (stored in global registry)
+* Invokes Controller
+* When control returns, dispatches to Location (if any)
+
+Controller
+* Receives context and selects the matching mapping
+* Adds reference to mapping instance to context
+* Sets mapping's default Location to context
+* Removes any expired messages from context
+* Invokes processor for mapping
+
+Processor
+* Invokes series of methods ("Chain of Commands") to handle request. The default series includes
+ * Multipart
+ * Locale
+ * ContentType
+ * NoCache
+ * PreProcess
+ * Roles
+ * InputHandler
+ * Cancel
+ * Reset
+ * Populate
+ * Validate
+ * Invalid
+ * MappingHandler
+ * Command | Script
+ * Invoke business logic
+ * Affect context state
+ * Identify resource to render response
+ * Location
+ * Identify resource to render response
+
+ExceptionHandler
+* Intercept any Exception thrown by Processor and set Location to designated error page.
+
+Tags/Tools
+* Reference Command Context (stored in request) to access framework members
+
+Server Pages
+* Utilize tags and tools to render dynamic data.
+
+###
+
diff --git a/struts-sandbox/struts-jericho/README.txt b/struts-sandbox/struts-jericho/README.txt
new file mode 100644
index 0000000..8515a04
--- /dev/null
+++ b/struts-sandbox/struts-jericho/README.txt
@@ -0,0 +1,65 @@
+Jericho is a whiteboard proposal describing one possible implementation of Struts 2.x.
+
+Since Struts 2.x is slated as a "revolution", the Apache practice is to assign a codename to a proposal until the Community comes to a consensus.
+
+This proposal is called "Jericho" since it tries to tear-down the walls within the Struts architecture. Jericho proposes to open-up Struts by
+
+* Declaring interfaces for all core components.
+
+* Providing working base implementations for all core components.
+
+* Encapsulating all path references within "Location" objects (aka ActionForwards)and referring only to Locations from all other objects.
+
+* Providing additional extension points from core components so that the "Inversion of Control" pattern is fully realized. (e.g., a populate method for the FormHandler.)
+
+* Providing "POJO" signatures that encapsulate servlet/portlet/soap behavior so that applications can be freed of servlet/portlet/soap semantics, if so desired. This strategy would also be applied to optional packages like Validator and Tiles.
+
+* Retain optional access to servlet/portlet objects so that applications can be free to do whatever they need to do.
+
+-Backward Compatibility-
+
+Jericho is a revolution and backward compatibility with prior versions of Struts is not the prime consideration. However, care is being taken to create a clear migration path, where practical, so that Jericho is available to the widest community possible.
+
+-Taglibs/Tools-
+
+JSP taglibs and other presentation tools will be packaged separately from the core controller classes. Tags and tools can access the framework through a StrutsContext object passed through the request, rather than searching through the servlet or portlet contexts.
+
+-ActionForms/Actions, et al-
+
+New implementations of Struts 1.x base classes will be provided. These classes will provide the Struts 1.x behavior, but will also implement the Jericho interfaces. (Much the same way perform was supported in Struts 1.1.)
+
+These same techniques may be applied to provide adaptors for other frameworks, so as to make Struts Jericho available to the widest community possible.
+
+-Configuration-
+
+The Jericho Configuration builds on the best aspects of Struts 1.2. The elements are different but still similar. Our goal is to allow a tool, such as a XLST processor, to migrate a Struts 1.2 DTD to Struts Jericho.
+
+A second alternative might be to provide an alternate configuration loader that would map the Struts 1.2 elements to Struts Jericho objects at initialization.
+
+-Servlet/Portlet/Soap/Mock support-
+
+Core components will implement signatures that reference a StrutsContext. Implementations of this interface can be backed by servlet, portlet, soap, or mock implementations as needed.
+
+-Also under consideration-
+
+* Services framework. Utilize Spring IoC, HiveMind, Avalon, Pico, Cornerstone, et cetera, to configure services.
+
+* Configuration testing. Integrate utility of Struts TestCase, ideally configured from an XML configuration (a la Canoo Webtest).
+
+* Replace DTD with XML Schema.
+
+* Utilize protocols in resource paths. An mapped path would look like "mapping://foo" or a tiles forward would be "tiles://tilesdef" This would make it easy to plug in handlers to support different presentation engines. If no protocol is specified, the path is handled as usual.
+
+* Combine form-bean and validator-form configurations. A single element would allow everything Struts knows about a form to be configured in one place.
+
+* Integrate Tiles definitions into core configuration.
+
+* Adopt Struts Workflow and Struts Menu as standard options, like Validator and Tiles.
+
+* Utilize JodaBeans <http://www.joda.org/> as a foundation class for core components.
+
+* Load all configuration defaults form a core.properties file so that less is hardcoded, including a PlugIn class to bootstrap loading the core configuration.
+
+* Ensure that all framework objects in 2.0 have consistent factory-based mechanisms to instantiate instances. <http://issues.apache.org/bugzilla/show_bug.cgi?id=15604>
+
+###
\ No newline at end of file
diff --git a/struts-sandbox/struts-jericho/project.properties b/struts-sandbox/struts-jericho/project.properties
new file mode 100644
index 0000000..45844f6
--- /dev/null
+++ b/struts-sandbox/struts-jericho/project.properties
@@ -0,0 +1,14 @@
+# -------------------------------------------------------------------
+# P R O J E C T P R O P E R T I E S
+# -------------------------------------------------------------------
+
+compile.debug = on
+compile.optimize = off
+compile.deprecation = off
+
+maven.linkcheck.enable=true
+
+# documentation properties
+maven.xdoc.date=left
+maven.xdoc.version=${pom.currentVersion}
+maven.xdoc.developmentProcessUrl=http://struts.apache.org/status.html
diff --git a/struts-sandbox/struts-jericho/project.xml b/struts-sandbox/struts-jericho/project.xml
new file mode 100644
index 0000000..e4a0338
--- /dev/null
+++ b/struts-sandbox/struts-jericho/project.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project>
+ <extend>../project.xml</extend>
+ <name>Jericho</name>
+ <artifactId>struts-jericho</artifactId>
+ <currentVersion>0.1-dev</currentVersion>
+ <inceptionYear>2003</inceptionYear>
+ <shortDescription>Struts Jericho 2.x Whiteboard</shortDescription>
+ <description>
+ Jericho is a whiteboard proposal describing one possible implementation of Struts 2.x.
+ Since Struts 2.x is slated as a "revolution", the Apache practice is to assign a codename to a proposal
+ until the Community comes to a consensus.
+ This proposal is called "Jericho" since it tries to tear-down the walls within the Struts architecture.
+ </description>
+ <developers>
+ <developer>
+ <name>Ted Husted</name>
+ <id>husted</id>
+ <email>husted@apache.org</email>
+ <organization></organization>
+ </developer>
+ </developers>
+
+ <build>
+ <unitTest>
+ <includes>
+ <include>**/*Test.java</include>
+ </includes>
+ </unitTest>
+ </build>
+
+</project>
diff --git a/struts-sandbox/struts-jericho/src/conf/struts-jericho-config_2_0.dtd b/struts-sandbox/struts-jericho/src/conf/struts-jericho-config_2_0.dtd
new file mode 100644
index 0000000..3376514
--- /dev/null
+++ b/struts-sandbox/struts-jericho/src/conf/struts-jericho-config_2_0.dtd
@@ -0,0 +1,771 @@
+<!--
+ DTD for the Struts Application Configuration File
+
+ To support validation of your configuration file, include the following
+ DOCTYPE element at the beginning (after the "xml" declaration):
+
+ <!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
+ "http://jakarta.apache.org/struts/dtds/struts-jericho-config_2_0.dtd">
+
+ $Id: struts-jericho-config_2_0.dtd,v 1.5 2003/12/19 02:35:07 husted Exp $
+-->
+
+
+<!-- ========== Defined Types ============================================= -->
+
+
+<!-- An "Identifier" is the name of a programming construct and must conform
+ to the rules for identifiers in the Java language.
+-->
+<!ENTITY % Identifier "CDATA">
+
+
+<!-- An "AttributeName" is the identifier of a page, request, session, or
+ application scope attribute.
+-->
+<!ENTITY % AttributeName "CDATA">
+
+
+<!-- A "PropObject" is the identifier of an object, such as an input form,
+ and also serves as the name of the corresponding scripting variable
+ and the name of the attribute under which the object is accessed.
+ Therefore, it must conform to the rules for an Identifier.
+-->
+<!ENTITY % PropObject "CDATA">
+
+
+<!-- A "Boolean" is the string representation of a boolean (true or false)
+ variable.
+-->
+<!ENTITY % Boolean "(true|false)">
+
+
+<!-- A "ClassName" is the fully qualified name of a compiled class that is
+ instantiated to provide the functionality of the enclosing element.
+-->
+<!ENTITY % ClassName "CDATA">
+
+
+<!-- An "Integer" is a character string consisting solely of numeric digits,
+ optionally preceeded by a minus sign, that can be converted to a
+ 32-bit integer.
+-->
+<!ENTITY % Integer "CDATA">
+
+
+<!-- A "Resource" is a relative path, delimited by "/" characters, that
+ defines the location of a resource relative to the location of the
+ Struts configuration file itself.
+-->
+<!ENTITY % Resource "#PCDATA">
+
+
+<!-- A "PropName" is the name of an object property, and must begin with
+ a lower case letter and contain only characters that are legal in a
+ identifier.
+-->
+<!ENTITY % PropName "CDATA">
+
+
+<!-- A "RequestPath" is an application-relative URI path, beginning with a
+ slash, that identifies a mapped resource (such as a server page or a
+ servlet) within this web application.
+-->
+<!ENTITY % RequestPath "CDATA">
+
+
+<!-- The name of a scope within which a object, such as an input handler, may be accessed.
+-->
+<!ENTITY % Scope "(request|session|application)">
+
+
+<!-- A "LocationType" is the string representation of the alternate ways a response
+ can be rendered
+-->
+<!ENTITY % LocationType "(forward|include|redirect)">
+
+
+<!-- ========== Top Level Elements ======================================== -->
+
+
+<!-- The "struts-config" element is the root of the configuration file
+ hierarchy, and contains nested elements for all of the other
+ configuration settings.
+-->
+<!ELEMENT struts-config (
+ display-name?,
+ description?,
+ property*,
+ catalog*,
+ inputs?,
+ locations?,
+ exceptions?,
+ processors?,
+ mappings?,
+ bundles,
+ plug-in*)>
+
+<!ATTLIST struts-config id ID #IMPLIED>
+
+<!-- The <property> element refers to the location of a properties file,
+ relative to the Struts configuration file, that contains replacement
+ variables to use when processing the elements. The properties defined
+ can be referred to using the standard "shell" notation: ${property}.
+
+ Properties can be used to avoid redundacy. For example, an often-used
+ class name can be listed in the properties file:
+
+ inputHandler = app.struts.MyInputHandler
+
+ and then referred to as the value for an attribute:
+
+ handler = ${inputHandler}
+
+ The following attribute is defined:
+
+ resource The path to the properties file, relative to the Struts
+ Configuration file being processed.
+-->
+<!ELEMENT property>
+<!ATTLIST property id ID #IMPLIED>
+<!ATTLIST property resource %Resource; #REQUIRED>
+
+
+<!-- The <catalog> element refers to the location of a Catalog file,
+ relative to the Struts configuration file, that contains a registry
+ of Command Chains that can be referred to in the "command" attributes
+ of other elements.
+
+ The following attribute is defined:
+
+ resource The path to the Catalog file, relative to the Struts
+ Configuration file being processed.
+-->
+<!ELEMENT property>
+<!ATTLIST property id ID #IMPLIED>
+<!ATTLIST property resource %Resource; #REQUIRED>
+
+
+<!-- The <inputs> element describes the set of input descriptors.
+The following attribute is defined:
+
+ config Fully qualified Java class to use when instantiating
+ Input objects. If specified, the object must implement
+ org.apache.struts.core.Input.
+ ["org.apache.struts.core.InputBase"]
+
+ handler Fully qualified Java class to use when instantiating
+ InputHandler objects. If specified, the object must implement
+ org.apache.struts.core.InputHandler.
+ ["org.apache.struts.core.DynaInputHandlerBase"]
+-->
+<!ELEMENT inputs (input*)>
+<!ATTLIST inputs id ID #IMPLIED>
+<!ATTLIST inputs config %ClassName; #IMPLIED>
+<!ATTLIST inputs handler %ClassName; #IMPLIED>
+
+
+<!-- The <input> element describes an InputHandler (org.apache.struts.core.InputHandler)
+ instance that can be referenced by a Mapping instance.
+
+ name The unique identifier for this input descriptor.
+ Referenced by the "input" attribute of the <mapping> element
+ to specify which input handler to use with a matching request. May also
+ be referenced by an "extends" attribute in another <input> element.
+
+ extends Name of an input descriptor that is used as a value template for
+ this element. All attributes from the template are available to
+ the new element. Any attribute inherited from the template can
+ be overloaded by providing a new value.
+
+ config Fully qualified class name of the Input class to use with
+ this input that implements org.apache.struts.core.Input.
+ ["org.apache.struts.core.InputBase"]
+
+ handler Fully qualified class name of the InputHandler class to use with
+ this input that implements org.apache.struts.core.InputHandler.
+ ["org.apache.struts.core.DynaInputHandlerBase"]
+
+-->
+<!ELEMENT input (icon?, display-name?, description?, set-property*, input-property*)>
+<!ATTLIST input id ID #IMPLIED>
+<!ATTLIST input name CDATA #REQUIRED>
+<!ATTLIST input extends CDATA #IMPLIED>
+<!ATTLIST input config %ClassName; #IMPLIED>
+<!ATTLIST input handler %ClassName; #REQUIRED>
+
+
+<!-- The <input-property> element describes an object property that can be used to
+ configure an instance of a DynaInputHandler. This element is only utilized when the
+ "handler" attribute of the enclosing <input> element implements
+ org.apache.struts.core.DynaInputHandler.
+
+ name The name of the object property described by this element.
+
+ extends Name of an input descriptor that is used as a value template for
+ this element. All attributes from the template are available to
+ the new element. Any attribute inherited from the template can
+ be overloaded by providing a new value.
+
+ config Fully qualified Java class to use when instantiating
+ DynaInputProperty objects. If specified, the object must implement
+ org.apache.struts.core.DynaInputProperty.
+ ["org.apache.struts.core.DynaInputPropertyBase"]
+
+ handler Fully qualified class name of the field that will handle this
+ property, optionally followed by "[]" to indicate that the
+ field is indexed.
+
+ initial String representation of the initial value for this property.
+ If not specified, primitives will be initialized to zero and
+ objects initialized to the zero-argument instantiation of that
+ object class. For example, Strings will be initialized to ""
+
+ size The number of array elements to create if the value of the
+ "handler" attribute specifies an array, but there is no value
+ specified for the "initial" attribute.
+-->
+<!ELEMENT input-property (set-property*)>
+<!ATTLIST input-property name CDATA #REQUIRED>
+<!ATTLIST input-property extends CDATA #IMPLIED>
+<!ATTLIST input-property config %ClassName; #IMPLIED>
+<!ATTLIST input-property handler %ClassName; #REQUIRED>
+<!ATTLIST input-property initial CDATA #IMPLIED>
+<!ATTLIST input-property size %Integer; #IMPLIED>
+
+
+<!-- The <locations> element describes a set of Location objects
+ (org.apache.struts.core.Location) that may be referenced by other elements
+ and returned by an MappingHandler's execute method. The individual Locations
+ are configured through nested <location> elements. Other elements, such
+ as <exception> and <mapping>, may also provide nested locations specific
+ to that element (local scope). The following attribute is defined:
+
+ handler Fully qualified Java class to use when instantiating
+ Location objects. If specified, the object must implement
+ org.apache.struts.core.Location.
+ ["org.apache.struts.core.LocationBase"]
+-->
+<!ELEMENT locations (location*)>
+<!ATTLIST locations id ID #IMPLIED>
+<!ATTLIST locations className %ClassName; #IMPLIED>
+
+
+<!-- The <location> element is referenced by
+ a logical name and encapsulates a URI or a reference to a mapping. A
+ "location" element may be used to describe both global and local locations.
+ Global locations are available to all the elements. Local locations can be
+ nested within an <exception> or <mapping> element and only available when it
+ is invoked in that context.
+
+ name The unique identifier for this location. Referenced by
+ other elements and by the MappingHandler object at runtime
+ to select - by its logical name - the resource that should
+ complete the request/response. May also be referenced by
+ an "extends" attribute of another <location> element.
+
+ extends Name of a location descriptor that is used as a value template for
+ this element. All attributes from the template are available to
+ the new element. Any attribute inherited from the template can
+ be overridden by providing a new value.
+
+ command Name of a Command to execute before dispatching control to
+ the resource for this element. The Command can be used to
+ prepare the contexts for the resource.
+
+ resource The module-relative or context-relative path to the resource
+ that is encapsulated by the logical name of this Location.
+ If the path is to be considered relative to the root application
+ context when used in a modular application, then the "appRelative"
+ attribute should be set to "true". This value should begin with
+ a slash ("/") character.
+
+ mappingRef Set to "true" if the path specified for "resource" is a reference
+ to a Mapping. If "true", calling "getResource" will return a URI to
+ the Mapping with the appropriate prefix or extension resolved.
+ ["false"]
+
+ appRelative Set to "true" if, in a modular application, the resource
+ attribute starts with a slash "/" and should be considered
+ relative to the application root rather than the current module.
+ ["false"]
+
+ merge Set to "true" if the resource path should be scanned for replacement
+ parameters: {[scope:]xyz}. Replacement parameters must begin
+ with a letter. If a scope is not specified, all scopes are
+ checked in turn (request, session, application).
+
+ type May be set to "forward", "include", or "redirect" to indicate
+ what approach is to be taken to render response.
+ ["forward"]
+-->
+<!ELEMENT location (icon?, display-name?, description?, set-property*)>
+<!ATTLIST location id ID #IMPLIED>
+<!ATTLIST location name CDATA #IMPLIED>
+<!ATTLIST location extends CDATA #IMPLIED>
+<!ATTLIST location command CDATA #IMPLIED>
+<!ATTLIST location resource %RequestPath; #REQUIRED>
+<!ATTLIST location mappingRef %Boolean; #IMPLIED>
+<!ATTLIST location appRelative %Boolean; #IMPLIED>
+<!ATTLIST location merge %Boolean; #IMPLIED>
+<!ATTLIST location redirect %Boolean; #IMPLIED>
+<!ATTLIST location type %LocationType; #IMPLIED>
+
+
+<!-- The <exceptions> element describes a set of exceptions that might be
+ thrown by an MappingHandler object. The handling of individual exception
+ classes can be configured through nested exception elements.
+ If a <mapping> element registers a local exception handler for the same
+ exception type, the local handler overrides the global exception handler.
+ The following attribute is defined:
+
+ handler Fully qualified Java class to use when instantiating
+ ExceptionConfig objects. If specified, the object must implement
+ org.apache.struts.core.ExceptionConfig.
+-->
+<!ELEMENT exceptions (exception*)>
+<!ATTLIST exceptions id ID #IMPLIED>
+
+
+<!-- The <exception> element registers an ExceptionHandler
+ (org.apache.struts.core.ExceptionHandler) for an exception class.
+ The following attributes are defined:
+
+ name A unique identifier for this <exception> element so that it
+ can be referenced by an "extends" attribute.
+
+ extends Name of an <exception> element that is used as a value template
+ for this element. All attributes from the template are available
+ to the new element. Any attribute inherited from the template
+ can be overridden by providing a new value.
+
+ config Fully qualified class name to use when instantiating
+ ExceptionConfig objects. If specified, the object must implement
+ org.apache.struts.core.ExceptionConfig.
+ ["org.apache.struts.core.ExceptionConfigBase"]
+
+ handler Fully qualified class name of the exception handler to use
+ with this exception.
+ ["org.apache.struts.core.ExceptionHandlerBase"]
+
+ location The name of the <location> element (local or global) that will
+ complete the request/response if the Exception specified by the
+ "trigger" attribute is thrown.
+
+ scope The scope ("request" or "session") that is used to access
+ the Message object (org.apache.struts.core.Message)
+ for this exception.
+
+ bundleName Attribute name for the message bundle associated with this
+ handler. [org.apache.struts.core.Keys.BUNDLE_KEY]
+
+ key The key to use with this handler's message bundle
+ that will retrieve the message template to use with this
+ exception.
+
+ trigger Fully qualified class name of the Exception class to
+ register with this handler.
+-->
+<!ELEMENT exception (icon?, display-name?, description?, set-property*, location*)>
+<!ATTLIST exception id ID #IMPLIED>
+<!ATTLIST exception name CDATA #IMPLIED>
+<!ATTLIST exception extends CDATA #IMPLIED>
+<!ATTLIST exception config %ClassName; #IMPLIED>
+<!ATTLIST exception handler %ClassName; #IMPLIED>
+<!ATTLIST exception location CDATA #IMPLIED>
+<!ATTLIST exception scope %Scope; #IMPLIED>
+<!ATTLIST exception bundleName %AttributeName; #IMPLIED>
+<!ATTLIST exception key CDATA #REQUIRED>
+<!ATTLIST exception trigger %ClassName; #REQUIRED>
+
+
+<!-- The <processors> element describes a set of Processor objects
+ (org.apache.struts.core.Processor) that are available to process
+ requests. The individual Processors are configured through nested
+ <processor> elements. The following attributes are defined:
+
+ config Fully qualified class name to use when instantiating
+ Processor objects. If specified, the object must implement
+ org.apache.struts.core.Processor.
+ ["org.apache.struts.core.ProcessorBase"]
+-->
+<!ELEMENT processors (processor*)>
+<!ATTLIST processors id ID #IMPLIED>
+<!ATTLIST processors config %ClassName; #IMPLIED>
+
+
+<!-- The <processor> element describes the a Processor object
+ [org.apache.struts.core.Processor] that is used to manage a
+ request/response event. Each <mapping> element can specify
+ its own Processor object, if needed. The following attributes
+ are defined:
+
+ name A unique identifier for this <processor> element so that it
+ can be referenced by an "extends" attribute.
+
+ extends Name of a <processor> element that is used as a value template
+ for this element. All attributes from the template are available
+ to the new element. Any attribute inherited from the template
+ can be overridden by providing a new value.
+
+ config Fully qualified class name to use when instantiating
+ Processor objects. If specified, the object must implement
+ org.apache.struts.core.Processor.
+ ["org.apache.struts.core.ProcessorBase"]
+
+ handler The fully qualified class name of the
+ RequestHandler subclass to be used with this module.
+ ["org.apache.struts.core.RequestHandler"]
+
+ locale Set to "false" if you do not want a Locale object stored in the
+ user's session.
+ ["true"]
+
+ pathPattern Replacement pattern defining how the "resource" attribute of a
+ <location> element is mapped to a context-relative URL when
+ it starts with a slash (and when the appRelative
+ property is false). This value may consist of any
+ combination of the following:
+ - "$M" - Replaced by the module prefix of this module
+ - "$R" - Replaced by the "resource" attribute of the
+ selected "location" element
+ - "$P" - Same as "$R".
+ - "$$" - Causes a literal dollar sign to be rendered
+ - "$x" - (Where "x" is any character not defined above)
+ Silently swallowed, reserved for future use
+ ["$M$R"]
+
+ pagePattern Replacement pattern defining how the "page" attribute of
+ custom tags using it is mapped to a context-relative URL
+ of the corresponding resource. This value may consist of
+ any combination of the following:
+ - "$M" - Replaced by the module prefix of this module
+ - "$P" - Replaced by the value of the "page" attribute
+ - "$$" - Causes a literal dollar sign to be rendered
+ - "$x" - (Where "x" is any character not defined above)
+ Silently swallowed, reserved for future use
+ ["$M$P"]
+
+ contentType Default content type (and optional character encoding) to
+ be set on each response. May be overridden by the Action,
+ server page, or other resource to which the request is forwarded.
+ ["text/html"]
+
+ nocache Set to "true" if you want the controller to add HTTP
+ headers for defeating caching to every response from
+ this module.
+ ["false"]
+
+ bufferSize The size of the input buffer used when processing
+ file uploads.
+ ["4096"]
+
+ maxFileSize The maximum size (in bytes) of a file to be accepted as a
+ file upload. Can be expressed as a number followed by a
+ "K", "M", or "G", which are interpreted to mean kilobytes,
+ megabytes, or gigabytes, respectively.
+ ["250M"]
+
+ memFileSize The maximum size (in bytes) of a file whose contents will
+ be retained in memory after uploading. Files larger than
+ this threshold will be written to some alternative storage
+ medium, typically a hard disk. Can be expressed as a number
+ followed by a "K", "M", or "G", which are interpreted to
+ mean kilobytes, megabytes, or gigabytes, respectively.
+ ["256K"]
+
+ multipartClass The fully qualified Java class name of the multipart
+ request handler class to be used with this module.
+ ["org.apache.struts.upload.CommonsMultipartRequestHandler"]
+
+ tempDir Temporary working directory to use when processing
+ file uploads.
+ [{Directory provided by servlet container}]
+-->
+<!ELEMENT processor (set-property*)>
+<!ATTLIST processor id ID #IMPLIED>
+<!ATTLIST processor name CDATA #IMPLIED>
+<!ATTLIST processor extends CDATA #IMPLIED>
+<!ATTLIST processor config %ClassName; #IMPLIED>
+<!ATTLIST processor handler %ClassName; #IMPLIED>
+<!ATTLIST processor locale %Boolean; #IMPLIED>
+<!ATTLIST processor pathPattern CDATA #IMPLIED>
+<!ATTLIST processor pagePattern CDATA #IMPLIED>
+<!ATTLIST processor contentType CDATA #IMPLIED>
+<!ATTLIST processor nocache %Boolean; #IMPLIED>
+<!ATTLIST processor bufferSize %Integer; #IMPLIED>
+<!ATTLIST processor maxFileSize CDATA #IMPLIED>
+<!ATTLIST processor memFileSize CDATA #IMPLIED>
+<!ATTLIST processor multipartClass %ClassName; #IMPLIED>
+<!ATTLIST processor tempDir CDATA #IMPLIED>
+
+
+<!-- The <mappings> element describes a set of Mapping objects
+ (org.apache.struts.core.Mapping) that are available to process
+ requests. The individual Mappings are configured through nested
+ <mapping> elements. The following attributes are defined:
+
+ config Fully qualified class name to use when instantiating
+ Mapping objects. If specified, the object must implement
+ org.apache.struts.core.Mapping.
+ ["org.apache.struts.core.MappingBase"]
+-->
+<!ELEMENT mappings (action*)>
+<!ATTLIST mappings id ID #IMPLIED>
+<!ATTLIST mappings config %ClassName; #IMPLIED>
+
+
+<!-- The <mapping> element describes an Mapping object that is to be used
+ to process a request. The following attributes are defined:
+
+ name A unique identifier for this exception element so that it
+ can be referenced by an "extends" attribute. (This is *not*
+ a reference to an <input> element!)
+
+ extends Name of an <mapping> element that is used as a value template
+ for this element. All attributes from the template are available
+ to the new element. Any attribute inherited from the template
+ can be overridden by providing a new value.
+
+ config The fully qualified class name of the Mapping object to use
+ with this instance. Defaults to the type specified by the
+ enclosing <mappings> element or to
+ "org.apache.struts.core.MappingBase" if not specified.
+ ["org.apache.struts.core.MappingBase"]
+
+ command Name of a Command to execute in order to process this
+ request. The Command is passed a StrutsContext object wrapping
+ the request. If the Command returns "false", the Location
+ object is processed to complete the response.
+ (org.apache.struts.action.Action now implements Command
+ and provides default behavior for backward compatibility.)
+
+ location The default location to set in the Context for this Mapping.
+ If not changed by a Command, this Location will be used to render
+ the reponse.
+ [null]
+
+ matches The path to match against the submitted request,
+ starting with a "/" character, and without the filename extension
+ if extension mapping is used.
+
+ NOTE: Do *not* include a period in your path name,
+ because it will look like a filename extension and
+ may cause your Mapping not to found.
+
+ processor Name of a Processor object to use when handling this request.
+ If not specified, the "unnamed" processor is used.
+
+ default Set to "true" if this object should be configured as the
+ default mapping. If a request does not match another mapping,
+ it will be passed to the Mapping object with default set to
+ "true". Only one Mapping can be marked as "default" within a
+ module.
+ [false]
+
+ secure whether to force secure access to this mapping (via SSL).
+
+ roles Comma-delimited list of security role names that are allowed
+ access to this Mapping object.
+
+ parameter General-purpose configuration parameter that can be used to
+ pass extra information to the Command object selected by
+ this mapping.
+
+ attribute Name of the request-scope or session-scope attribute that
+ is used to access our InputHandler object, if it is other than
+ the object's default "input". Optional if "input" is specified,
+ else not valid.
+
+ input Name of the input descriptor, if any, to use with this mapping.
+ (This is *not* the dispatch Location if validate fails.)
+
+ scope The scope ("request" or "session") that is used to
+ access our InputHandler, if any. Optional if <input> is
+ specified, else not valid.
+
+ populate Set to "false" if the populate method of the InputHandler
+ should not be called prior to calling the MappingHandler for
+ this request. If "false", the reset method is also bypassed.
+ [true]
+
+ validate Set to "false" if the validate method of the InputHandler
+ should not be called prior to calling the MappingHandler for
+ this request.
+ [true]
+
+ onInvalid Name of a local or global Location that should handle the
+ response if a validation message is generated.
+ Valid only when "input" is specified.
+ Required if "input" is specified and the InputHandler returns
+ validation messages.
+ Optional if "input" is specified and the
+ InputHandler does not return validation messages.
+
+ onCancel Name of a local or global Location that should handle the
+ response if "cancel" is signaled in the request.
+ -->
+<!ELEMENT mapping (icon?, display-name?, description?, set-property*, exception*, location*)>
+<!ATTLIST mapping id ID #IMPLIED>
+<!ATTLIST mapping name CDATA #IMPLIED>
+<!ATTLIST mapping extends CDATA #IMPLIED>
+<!ATTLIST mapping config %ClassName; #IMPLIED>
+<!ATTLIST mapping command CDATA #IMPLIED>
+<!ATTLIST mapping forward %RequestPath; #IMPLIED>
+<!ATTLIST mapping include %RequestPath; #IMPLIED>
+<!ATTLIST mapping matches %RequestPath; #REQUIRED>
+<!ATTLIST mapping processor CDATA #IMPLIED>
+<!ATTLIST mapping default %Boolean; #IMPLIED>
+<!ATTLIST mapping secure %Boolean; #IMPLIED>
+<!ATTLIST mapping roles CDATA #IMPLIED>
+<!ATTLIST mapping parameter CDATA #IMPLIED>
+<!ATTLIST mapping attribute %PropName; #IMPLIED>
+<!ATTLIST mapping input CDATA; #IMPLIED>
+<!ATTLIST mapping scope %Scope; #IMPLIED>
+<!ATTLIST mapping populate %Boolean; #IMPLIED>
+<!ATTLIST mapping validate %Boolean; #IMPLIED>
+<!ATTLIST mapping onInvalid CDATA #IMPLIED>
+<!ATTLIST mapping onCancel CDATA #IMPLIED>
+
+
+<!-- The <bundles> element describes a set of Bundle objects
+ (org.apache.struts.core.MessageBundle) that are available to provide
+ message bundles. The individual Bundles are configured through nested
+ <bundle> elements. The following attributes are defined:
+
+ config Fully qualified class name to use when instantiating
+ Bundle objects. If specified, the object must implement
+ org.apache.struts.core.MessageBundle.
+ ["org.apache.struts.core.MessageBundleBase"]
+-->
+<!ELEMENT bundles (processor*)>
+<!ATTLIST bundles id ID #IMPLIED>
+<!ATTLIST bundles config %ClassName; #IMPLIED>
+
+
+<!-- The <bundle> element describes a MessageBundle object with
+ message templates for this module. The following attributes are defined:
+
+ name A unique identifier for this bundle element so that it
+ can be referenced by an "extends" attribute.
+
+ extends Name of an <bundle> element that is used as a value template
+ for this element. All attributes from the template are available
+ to the new element. Any attribute inherited from the template
+ can be overridden by providing a new value.
+
+ config The fully qualified class name of the MessageBundle object to use
+ with this instance. Defaults to the type specified by the
+ enclosing <bundles> element or to
+ "org.apache.struts.core.MessageBundleBase" if not specified.
+ ["org.apache.struts.core.MappingBase"]
+
+ factory Fully qualified Java class name of the
+ MessageBundleFactory subclass to use for this message
+ bundle object.
+ ["org.apache.struts.util.PropertyMessageBundleFactory"]
+
+ key Servlet context attribute under which this message
+ bundle will be stored. The default attribute is
+ the value specified by the string constant at
+ [Keys.BUNDLE_KEY]. The application module prefix (if
+ any) is appended to the key (${key}${prefix}).
+ [org.apache.struts.core.Keys.BUNDLE_KEY]
+
+ NOTE: The application module prefix includes the leading
+ slash, so the default message resource bundle for a module
+ named "foo" is stored under
+ "org.apache.struts.core.BUNDLE/foo".
+
+ null Set to "true" if you want this message bundle to return a
+ null string for unknown message keys, or "false" to return a
+ message with the bad key value.
+
+ parameter Configuration parameter to be passed to the createBundle
+ method of our factory object.
+-->
+<!ELEMENT bundle (set-property*)>
+<!ATTLIST bundle id ID #IMPLIED>
+<!ATTLIST bundle handler %ClassName; #IMPLIED>
+<!ATTLIST bundle factory %ClassName; #IMPLIED>
+<!ATTLIST bundle key %AttributeName; #IMPLIED>
+<!ATTLIST bundle null %Boolean; #IMPLIED>
+<!ATTLIST bundle parameter CDATA #REQUIRED>
+
+
+<!-- The <plug-in> element specifies the fully qualified class name of a
+ general-purpose application plug-in component that receives notification of
+ application startup and shutdown events. An instance of the specified class
+ is created for each element, and can be configured with nested <set-property>
+ elements. The following attributes are supported:
+
+ handler Fully qualified Java class name of the plug-in class; must
+ implement [org.apache.struts.action.PlugIn].
+-->
+<!ELEMENT plug-in (set-property*)>
+<!ATTLIST plug-in id ID #IMPLIED>
+<!ATTLIST plug-in handler %ClassName; #REQUIRED>
+
+
+<!-- ========== Subordinate Elements ====================================== -->
+
+
+<!-- The "description" element contains descriptive (paragraph length) text
+ about the surrounding element, suitable for use in GUI tools.
+-->
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description id ID #IMPLIED>
+
+
+<!-- The "display-name" element contains a short (one line) description of
+ the surrounding element, suitable for use in GUI tools.
+-->
+<!ELEMENT display-name (#PCDATA)>
+<!ATTLIST display-name id ID #IMPLIED>
+
+
+<!-- The "icon" element contains a small-icon and large-icon element which
+ specify the location, relative to the Struts configuration file, for small
+ and large images used to represent the surrounding element in GUI tools.
+-->
+<!ELEMENT icon (small-icon?, large-icon?)>
+<!ATTLIST icon id ID #IMPLIED>
+
+
+<!-- The "large-icon" element specifies the location, relative to the Struts
+ configuration file, of a resource containing a large (32x32 pixel)
+ icon image.
+-->
+<!ELEMENT large-icon (%Location;)>
+<!ATTLIST large-icon id ID #IMPLIED>
+
+
+<!-- The "set-property" element specifies the method name and initial value of
+ an additional JavaBean configuration property. When the object representing
+ the surrounding element is instantiated, the accessor for the indicated
+ property is called and passed the indicated value. The "set-property"
+ element is especially useful when a custom subclass is used with
+ <location>, <mapping>, or <plug-in> elements. The subclass
+ can be passed whatever other properties may be required to configure the
+ object without changing how the struts-config is parsed.
+
+ property Name of the JavaBeans property whose setter method
+ will be called.
+
+ value String representation of the value to which this
+ property will be set, after suitable type conversion
+-->
+<!ELEMENT set-property EMPTY>
+<!ATTLIST set-property id ID #IMPLIED>
+<!ATTLIST set-property property %PropName; #REQUIRED>
+<!ATTLIST set-property value CDATA #REQUIRED>
+
+
+<!-- The "small-icon" element specifies the location, relative to the Struts
+ configuration file, of a resource containing a small (16x16 pixel)
+ icon image.
+-->
+<!ELEMENT small-icon (%Location;)>
+<!ATTLIST small-icon id ID #IMPLIED>
+
diff --git a/struts-sandbox/struts2/LICENSE.txt b/struts-sandbox/struts2/LICENSE.txt
new file mode 100644
index 0000000..dd5b3a5
--- /dev/null
+++ b/struts-sandbox/struts2/LICENSE.txt
@@ -0,0 +1,174 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/struts-sandbox/struts2/NOTICE.txt b/struts-sandbox/struts2/NOTICE.txt
new file mode 100644
index 0000000..8d09a9f
--- /dev/null
+++ b/struts-sandbox/struts2/NOTICE.txt
@@ -0,0 +1,9 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+This product includes the ANTLR parsing library,
+developed by JGuru.com (http://www.antlr.org and
+http://www.jguru.com).
+
+This product includes software developed by
+The OpenSymphony Group (http://www.opensymphony.com/).
diff --git a/struts-sandbox/struts2/PRACTICES.txt b/struts-sandbox/struts2/PRACTICES.txt
new file mode 100644
index 0000000..9e9e717
--- /dev/null
+++ b/struts-sandbox/struts2/PRACTICES.txt
@@ -0,0 +1,57 @@
+Action2 Apps Best Practices
+
+* Link only to actions, never to server pages or templates
+
+* Do not expose the action extension in your tags. Use the action parameter instead.
+
+* Use namespaces to organize your application into logical "modules" or units of work.
+
+* Place each namespace into it's own Xwork config.
+ ** Try to keep the Actions classes for the namespace in a common package.
+ ** Store the Xwork configuration for that namespace with the Actions.
+ ** If you are using JSPs, try to name the JSP folder after the Action package.
+ ** If you using templates, bundle the templates with the Actions.
+ ** Remember, if the namespace needs to change, you do not need to change packages or JSP folders, if you don't want to.
+
+* Within a namespace, reuse names for common concepts. If each namespace has an entry page, use the same action name in each namespace. For example, each namespace in the Cookbook has an "Open" action.
+
+* Unit test actions before trying them in a web application.
+ ** Since JUnit is integrated in most IDEs now, there is no excuse.
+
+* Consider using WebCanoo, HtmlUnit, or HttpUnit to test navigation, as the application is being developed.
+
+* Use SiteMesh, or the equivalent, to separate application "chrome" from the core utility of the server pages.
+
+* Specify the POST method for forms, unless there is a reason to use the default GET method.
+
+* If an image, or other swatch of markup, is being used by multiple pages, remove it to its own server page and include it where necessary.
+ ** Better yet, encapsulate the markup in its own UI tag.
+
+* Extend the UI tags as needed.
+
+* Consider using the message resources for page titles, control labels, and so forth, even if the application is not being localized.
+ ** It is often useful to seperate the concern of what message to display from the concern of where to display it.
+
+* Use the XML framework to validate input.
+
+* Do not embed business logic in action classes.
+ ** Remove business logic to a business facade that the actions can call. (Spring is an excellent way to build a business facade.)
+ ** Actions are a necessary evil. Every line of code in an Action is guilty until proven innocent. Ideally, there should be one line of code that calls the business facade, and every other line of a code in an action should be bound to the framework.
+
+* Centralize other application and business logic into a base class that action can share.
+
+
+----
+
+Other Best Practice Resources
+
+* Showcase Best Practices thread - http://forums.opensymphony.com/thread.jspa?messageID=24691恳
+
+* Original "Action 1" Catalog - http://husted.com/struts/catalog.html
+
+* Wiki version - http://wiki.apache.org/struts/StrutsCatalog
+
+* "Action 1" Best Practices - http://opensource.atlassian.com/confluence/oss/pages/viewpageattachments.action?pageId=829
+
+
+
diff --git a/struts-sandbox/struts2/README.txt b/struts-sandbox/struts2/README.txt
new file mode 100644
index 0000000..eaedc5a
--- /dev/null
+++ b/struts-sandbox/struts2/README.txt
@@ -0,0 +1,266 @@
+This directory is a whiteboard area for working on new material related to
+the adoption of WebWork2 as Action2.
+
+While WebWork2/Action2 is passing through the incubator, this material is
+being based on OS WebWork 2.2.2.
+
+Note this area is intended for *NEW* material only. Existing material must
+enter Apache Struts through the incubation process.
+
+At this time, the material is being built directly with IDEA, and a standard
+build file is not yet available.
+
+For the time being, the dependencies required to build this material may be
+downloaded here:
+
+* http://people.apache.org/~husted/sandbox-action2-lib.zip
+
+For more about the materials under construction, visit
+
+* http://www.StrutsUniversity.org/Application+Use+Cases
+
+----------------------------------------------------------------------------
+
+APPS
+
+Under the apps folder, two applications are now being constructed
+
+ * Cookbook, and
+ * Mailreader
+
+The goal of the Cookbook is to combine the WebWork 2.2.2 Showcase with the
+Struts 1.3 Examples and the Struts 1.3 Cookbook.
+
+The Cookbook demonstrates working code and provides links to display the
+code for each example.
+
+The goal of the Mailreader is to provide a simple application that
+demonstrates best practices.
+
+The Mailreader is a simple parent/child workflow, where visitors can register
+with the application and the create child records related to the user's
+master account.
+
+Other new applications may include the iBATIS JPetstore example,
+which was based on Struts Action 1.
+
+Other WebWork example applications, like the shopping cart, could also be
+kept here.
+
+----------------------------------------------------------------------------
+
+STATUS - COOKBOOK
+
+* Several examples have been added.
+
+* The "Select" example could be streamlined to use one example of each
+Select control.
+
+* Other examples can be added at will.
+
+----
+
+Hmmmm ...
+
+* Are the validator objects singletons?
+
+
+----
+
+Example idea jar
+
+* See http://www.niallp.pwp.blueyonder.co.uk/strutsvalidatorextends.html
+for some validation use cases.
+
+* http://wiki.opensymphony.com/display/WW/Cookbook
+
+
+* Display an unexpected exception on an error page.
+** What's the conditional logic using JSP tags?
+
+* "param->prepare->param interceptor pattern"
+** http://forums.opensymphony.com/thread.jspa?threadID=23750&tstart=0
+
+* Using proxy objects to restrict access to domain objects
+** http://forums.opensymphony.com/thread.jspa?threadID=23750&tstart=0
+
+* Using an authentification interceptor.
+**
+
+* Overriding a bundled UI Tag.
+
+* Creating a custom UI Tag.
+
+* Canceling a form with client-side validation.
+** (Should there be a "validate" attribute to generate the "form.onsubmit=null" script?)
+** (Should ActionSupport provide "public String cancel() {return CANCEL;} ?
+** (Should we support action="!cancel" to be consistent with form tag.)
+*** (Trying !cancel in WW2.2.2 carries cancel over to the next action.)
+
+* Setting form type to "POST"
+** (Should POST be the default?)
+
+* Switching to SSL after login
+** http://forums.opensymphony.com/thread.jspa?messageID=11452Ⲽ
+
+* Customizing pages for multiple installations across multiple releases
+** http://forums.opensymphony.com/thread.jspa?messageID=23991嶷
+
+----
+
+Examples that might involve new development
+
+* How do we set checkboxes false (on uncheck)?
+** http://forums.opensymphony.com/thread.jspa?threadID=23601&tstart=0
+
+* How to set the focus on a form field?
+** http://forums.opensymphony.com/thread.jspa?threadID=23777&tstart=0
+
+* Populating POJO that implements an Interface
+** http://forums.opensymphony.com/thread.jspa?threadID=23750&tstart=0
+
+* Wizard
+** http://forums.opensymphony.com/thread.jspa?threadID=23778&tstart=15
+
+* DRY UI Tags
+** http://forums.opensymphony.com/thread.jspa?threadID=24140&tstart=0
+
+* Default package names
+** Allow a default package name to be set for Action classes
+ so that .MyAction could resolve to org.mycorp.myapp.mypackage.MyAction
+
+* Proxy Result
+** http://forums.opensymphony.com/thread.jspa?threadID=23621&tstart=0
+
+
+----------------------------------------------------------------------------
+
+STATUS - MAILREADER
+
+* Feature complete, but some marginal issue remain.
+* Could use a screen shot next to the code for each page.
+
+----
+
+Welcome
+
+Nominal
++ Logon - Cancel
++ Register - Cancel
+
+----
+
+Logon
+
+Nominal
++ Cancel
++ Reset
+- Submit (invalid)
++ Submit (incorrect)
++ Submit
+
+----
+
+Registraton Edit
+
+Nominal
++ Cancel
++ Reset
++ Submit (no change)
++ Submit (change)
++ Submit (invalid change)
+
+Issues
+* When client-side validation is enabled, messages stack up on multiple invalid submits. Sever-side only OK.
+*** This doesn't happen with Logon page, only Registration and Subscription (!?)(
+*** Asked on forum - http://forums.opensymphony.com/thread.jspa?threadID=23871&tstart=0
+
+----
+
+Subscription Edit
+
+Nominal
++ Cancel
++ Save (no changes)
++ Save (changes)
+
+----
+
+Subscription Delete
+
+Norminal
++ Cancel
++ Confirm
+
+----
+
+Subscription Add
++ Cancel
++ Submit
++ Submit (bad data)
++ Double submit
+
+----
+
+Logoff
+
+Nominal
++ Logoff - Refresh
++ Logoff - Skip to Registeration page
+
+----
+
+Registration Create
+
+Nominal
++ Cancel
++ Reset
++ Submit (no data)
++ Submit (invalid data)
++ Submit (data)
++ Submit (duplicate data)
++ Double submit
+
+----
+
+Locale change
++ Change locale from Welcome page.
++ Buttons and Labels reflect changed locale
+
+----
+
+Tour
+* In progress
+
+----
+
+Error
++ Need to log and present unexpected exceptions
+
+
+Issue
+* If the error page is fired by a global exception handler, is the exception going to be logged. Do we need to use a chain result to an action that would log the exception? What would be the Java syntax?
+
+* It would be nice to omit the message markup if there is not message.
+** http://forums.opensymphony.com/thread.jspa?threadID=7480&messageID=16618#16618
+
+Things that didn't work:
+
+<saf:if test=" %(exception.message}?exists">
+
+<saf:if test=" %this.exception.message?exists">
+
+<saf:if test=" #(exception.message} != null ">
+
+----
+
+ApplicationListener
+* Another approach would be to instantiate the database via Spring.
+
+
+----
+
+VerifyResourcesInterceptor
+* Could use a better test to detect whether message resources loaded
+
+====
diff --git a/struts-sandbox/struts2/apps/blank/META-INF/context.xml b/struts-sandbox/struts2/apps/blank/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/struts2/apps/blank/src/java/blank2/Home.java b/struts-sandbox/struts2/apps/blank/src/java/blank2/Home.java
new file mode 100644
index 0000000..4d104e0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/src/java/blank2/Home.java
@@ -0,0 +1,18 @@
+package blank2;
+
+import com.opensymphony.xwork.ActionSupport;
+
+/**
+ * Utilize the SUCCESS result.
+ */
+public class Home extends ActionSupport {
+
+ /**
+ * Return the default SUCCESS token.
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/applicationContext.xml b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 0000000..b98e1d8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans default-autowire="autodetect">
+ <!-- add your spring beans here -->
+</beans>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/classes/webwork.properties b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/classes/webwork.properties
new file mode 100644
index 0000000..0615c45
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/classes/webwork.properties
@@ -0,0 +1,2 @@
+webwork.objectFactory = spring
+webwork.devMode = true
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/classes/xwork.xml b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/classes/xwork.xml
new file mode 100644
index 0000000..bc8f123
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/classes/xwork.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+ <include file="webwork-default.xml"/>
+
+ <package name="default" extends="webwork-default">
+
+ <default-action-ref name="home"/>
+
+ <action name="Hello" class="Action2.Hello">
+ <result>/pages/Hello.jsp</result>
+ </action>
+
+ <!-- Add your actions here -->
+ </package>
+</xwork>
diff --git a/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/web.xml b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5328756
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Acme Corp</display-name>
+
+ <filter>
+ <filter-name>webwork</filter-name>
+ <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>webwork</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.jsp</welcome-file>
+ <welcome-file>default.jsp</welcome-file>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ <!--
+ This typically isn't required, as the taglib is included in webwork.jar.
+ If you really need a taglib configuration within web.xml, copy webwork/src/java/META-INF/taglib.tld
+ to the WEB-INF directory as webwork.tld.
+ -->
+ <!--taglib>
+ <taglib-uri>webwork</taglib-uri>
+ <taglib-location>/WEB-INF/webwork.tld</taglib-location>
+ </taglib-->
+</web-app>
diff --git a/struts-sandbox/struts2/apps/blank/src/webapp/index.jsp b/struts-sandbox/struts2/apps/blank/src/webapp/index.jsp
new file mode 100644
index 0000000..ec3143b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/src/webapp/index.jsp
@@ -0,0 +1 @@
+<% response.sendRedirect(request.getContextPath() + "/Hello.action"); %>
diff --git a/struts-sandbox/struts2/apps/blank/src/webapp/pages/Hello.jsp b/struts-sandbox/struts2/apps/blank/src/webapp/pages/Hello.jsp
new file mode 100644
index 0000000..8e86e6b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/blank/src/webapp/pages/Hello.jsp
@@ -0,0 +1,9 @@
+<html>
+<head>
+ <title>Welcome</title>
+</head>
+
+<body>
+<h1>Don't panic! Struts is mostly harmless ... </h1>
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/META-INF/context.xml b/struts-sandbox/struts2/apps/cookbook/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/struts2/apps/cookbook/README.txt b/struts-sandbox/struts2/apps/cookbook/README.txt
new file mode 100644
index 0000000..bf5a3ea
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/README.txt
@@ -0,0 +1,13 @@
+README.txt - cookbook
+
+The Cookbook is a collection of working examples which demonstrate how to
+code common web application use cases.
+
+The application is designed so that the code used to impolement the
+examples can be viewed online.
+
+This application is being retained as a placeholder until we can refactor
+the Showcase to use a similar format.
+
+
+----------------------------------------------------------------------------
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Buttons-config.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Buttons-config.xml
new file mode 100644
index 0000000..5f3aceb
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Buttons-config.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <package name="Buttons" namespace="/Buttons" extends="webwork-default">
+
+ <action name="Open" class="cookbook2.Buttons">
+ <result>/pages/Buttons/Result.jsp</result>
+ <result name="input">/pages/Buttons/Input.jsp</result>
+ </action>
+
+ <action name="View">
+ <result>/pages/Buttons/index.jsp</result>
+ </action>
+
+ <action name="View-Input">
+ <result type="plaintext">/pages/Buttons/Input.jsp</result>
+ </action>
+
+ <action name="View-Result">
+ <result type="plaintext">/pages/Buttons/Result.jsp</result>
+ </action>
+
+ <action name="View-Action">
+ <result type="plaintext">/WEB-INF/src/java/cookbook2/Buttons.java</result>
+ </action>
+
+ <action name="View-Config">
+ <result type="plaintext">/WEB-INF/classes/cookbook2/Buttons-config.xml</result>
+ </action>
+
+ </package>
+</xwork>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Buttons.java b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Buttons.java
new file mode 100644
index 0000000..4a6e450
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Buttons.java
@@ -0,0 +1,39 @@
+package cookbook2;
+
+import com.opensymphony.xwork.ActionSupport;
+
+public class Buttons extends ActionSupport {
+
+ private String recipient = "Nobody";
+
+ public String getRecipient() {
+ return recipient;
+ }
+
+ public void setRecipient(String value) {
+ recipient = value;
+ }
+
+ private String message;
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String value) {
+ message = value;
+ }
+
+ public void setFord(String value) {
+ setRecipient("Ford");
+ }
+
+ public void setMarvin(String value) {
+ setRecipient("Marvin");
+ }
+
+ public void setTrillian(String value) {
+ setRecipient("Trillian");
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Hello-config.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Hello-config.xml
new file mode 100644
index 0000000..5fab6c5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Hello-config.xml
@@ -0,0 +1,24 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <package name="Hello" namespace="/Hello" extends="webwork-default">
+
+ <action name="Open">
+ <result>/pages/Hello/Result.jsp</result>
+ </action>
+
+ <action name="View">
+ <result>/pages/Hello/index.jsp</result>
+ </action>
+
+ <action name="View-Result">
+ <result type="plaintext">/pages/Hello/Result.jsp</result>
+ </action>
+
+ <action name="View-Config">
+ <result type="plaintext">/WEB-INF/classes/cookbook2/Hello-config.xml</result>
+ </action>
+
+ </package>
+</xwork>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Home-config.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Home-config.xml
new file mode 100644
index 0000000..460ecaf
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Home-config.xml
@@ -0,0 +1,12 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <package name="Home" extends="webwork-default">
+
+ <action name="Home">
+ <result>/Home.jsp</result>
+ </action>
+
+ </package>
+</xwork>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Select-config.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Select-config.xml
new file mode 100644
index 0000000..b3545eb
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Select-config.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <package name="Select" namespace="/Select" extends="webwork-default">
+
+ <action name="Open" class="cookbook2.Select">
+ <result>/pages/Select/Result.jsp</result>
+ <result name="input">/pages/Select/Input.jsp</result>
+ </action>
+
+ <action name="View">
+ <result>/pages/Select/index.jsp</result>
+ </action>
+
+ <action name="View-Input">
+ <result type="plaintext">/pages/Select/Input.jsp</result>
+ </action>
+
+ <action name="View-Result">
+ <result type="plaintext">/pages/Select/Result.jsp</result>
+ </action>
+
+ <action name="View-Action">
+ <result type="plaintext">/WEB-INF/src/java/cookbook2/Select.java</result>
+ </action>
+
+ <action name="View-Config">
+ <result type="plaintext">/WEB-INF/classes/cookbook2/Select-config.xml</result>
+ </action>
+
+ </package>
+</xwork>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Select.java b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Select.java
new file mode 100644
index 0000000..0079d2b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Select.java
@@ -0,0 +1,318 @@
+package cookbook2;
+
+import com.opensymphony.webwork.ServletActionContext;
+import com.opensymphony.xwork.ActionSupport;
+import com.opensymphony.xwork.Validateable;
+import com.opensymphony.xwork.util.OgnlValueStack;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Select extends ActionSupport implements Validateable {
+
+ String name;
+ Date birthday;
+ String bio;
+ String favoriteColor;
+ List friends;
+ boolean legalAge;
+ String state;
+ String region;
+ File picture;
+ String pictureContentType;
+ String pictureFileName;
+ String favouriteLanguage;
+ String favouriteVehicalType = "MotorcycleKey";
+ String favouriteVehicalSpecific = "YamahaKey";
+
+ List leftSideCartoonCharacters;
+ List rightSideCartoonCharacters;
+
+ List favouriteLanguages = new ArrayList();
+ List vehicalTypeList = new ArrayList();
+ Map vehicalSpecificMap = new HashMap();
+
+ String thoughts;
+
+ /**
+ * The constructor pre-populates the controsl for us.
+ */
+ public Select() {
+ favouriteLanguages.add(new Language("EnglishKey", "English Language"));
+ favouriteLanguages.add(new Language("FrenchKey", "French Language"));
+ favouriteLanguages.add(new Language("SpanishKey", "Spanish Language"));
+
+ VehicalType car = new VehicalType("CarKey", "Car");
+ VehicalType motorcycle = new VehicalType("MotorcycleKey", "Motorcycle");
+ vehicalTypeList.add(car);
+ vehicalTypeList.add(motorcycle);
+
+ List cars = new ArrayList();
+ cars.add(new VehicalSpecific("MercedesKey", "Mercedes"));
+ cars.add(new VehicalSpecific("HondaKey", "Honda"));
+ cars.add(new VehicalSpecific("FordKey", "Ford"));
+
+ List motorcycles = new ArrayList();
+ motorcycles.add(new VehicalSpecific("SuzukiKey", "Suzuki"));
+ motorcycles.add(new VehicalSpecific("YamahaKey", "Yamaha"));
+
+ vehicalSpecificMap.put(car, cars);
+ vehicalSpecificMap.put(motorcycle, motorcycles);
+ }
+
+ /**
+ * Prepare form for display.
+ *
+ * <p> In this example, all the work is done in the constructor. Other cases may need to consult data access logic
+ * to populate the controls. </p>
+ *
+ * @return Result
+ */
+ public String setup() {
+ return SUCCESS;
+ }
+
+ /**
+ * Execute the "Select" action.
+ *
+ * <p> In this example, we are simply displaying the input. Other cases may need to consult business or data access
+ * logic. </p>
+ *
+ * @return Result
+ * @throws Exception on any error
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+
+ // -- Methods that populate controls from data prepared in the constructor --
+
+ public List getLeftSideCartoonCharacters() {
+ return leftSideCartoonCharacters;
+ }
+
+ public void setLeftSideCartoonCharacters(List leftSideCartoonCharacters) {
+ this.leftSideCartoonCharacters = leftSideCartoonCharacters;
+ }
+
+
+ public List getRightSideCartoonCharacters() {
+ return rightSideCartoonCharacters;
+ }
+
+ public void setRightSideCartoonCharacters(List rightSideCartoonCharacters) {
+ this.rightSideCartoonCharacters = rightSideCartoonCharacters;
+ }
+
+
+ public String getFavouriteVehicalType() {
+ return favouriteVehicalType;
+ }
+
+ public void setFavouriteVehicalType(String favouriteVehicalType) {
+ this.favouriteVehicalType = favouriteVehicalType;
+ }
+
+ public String getFavouriteVehicalSpecific() {
+ return favouriteVehicalSpecific;
+ }
+
+ public void setFavouriteVehicalSpecific(String favouriteVehicalSpecific) {
+ this.favouriteVehicalSpecific = favouriteVehicalSpecific;
+ }
+
+
+ public List getVehicalTypeList() {
+ return vehicalTypeList;
+ }
+
+ public List getVehicalSpecificList() {
+ OgnlValueStack stack = ServletActionContext.getValueStack(ServletActionContext.getRequest());
+ VehicalType vehicalType = (VehicalType) stack.findValue("top");
+ System.out.println("vehicalType.getKey()" + vehicalType.getKey());
+ return (List) vehicalSpecificMap.get(vehicalType);
+ }
+
+ public List getFavouriteLanguages() {
+ return favouriteLanguages;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Date getBirthday() {
+ return birthday;
+ }
+
+ public void setBirthday(Date birthday) {
+ this.birthday = birthday;
+ }
+
+ public String getBio() {
+ return bio;
+ }
+
+ public void setBio(String bio) {
+ this.bio = bio;
+ }
+
+ public String getFavoriteColor() {
+ return favoriteColor;
+ }
+
+ public void setFavoriteColor(String favoriteColor) {
+ this.favoriteColor = favoriteColor;
+ }
+
+ public List getFriends() {
+ return friends;
+ }
+
+ public void setFriends(List friends) {
+ this.friends = friends;
+ }
+
+ public boolean isLegalAge() {
+ return legalAge;
+ }
+
+ public void setLegalAge(boolean legalAge) {
+ this.legalAge = legalAge;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getRegion() {
+ return region;
+ }
+
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ public void setPicture(File picture) {
+ this.picture = picture;
+ }
+
+ public void setPictureContentType(String pictureContentType) {
+ this.pictureContentType = pictureContentType;
+ }
+
+ public void setPictureFileName(String pictureFileName) {
+ this.pictureFileName = pictureFileName;
+ }
+
+ public void setFavouriteLanguage(String favouriteLanguage) {
+ this.favouriteLanguage = favouriteLanguage;
+ }
+
+ public String getFavouriteLanguage() {
+ return favouriteLanguage;
+ }
+
+
+ public void setThoughts(String thoughts) {
+ this.thoughts = thoughts;
+ }
+
+ public String getThoughts() {
+ return this.thoughts;
+ }
+
+ // -- inner classes --
+
+ public static class Language {
+ String description;
+ String key;
+
+ public Language(String key, String description) {
+ this.key = key;
+ this.description = description;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ }
+
+ public static class VehicalType {
+ String key;
+ String description;
+
+ public VehicalType(String key, String description) {
+ this.key = key;
+ this.description = description;
+ }
+
+ public String getKey() {
+ return this.key;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public boolean equals(Object obj) {
+ if (! (obj instanceof VehicalType)) {
+ return false;
+ } else {
+ return key.equals(((VehicalType) obj).getKey());
+ }
+ }
+
+ public int hashCode() {
+ return key.hashCode();
+ }
+ }
+
+
+ public static class VehicalSpecific {
+ String key;
+ String description;
+
+ public VehicalSpecific(String key, String description) {
+ this.key = key;
+ this.description = description;
+ }
+
+ public String getKey() {
+ return this.key;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public boolean equals(Object obj) {
+ if (! (obj instanceof VehicalSpecific)) {
+ return false;
+ } else {
+ return key.equals(((VehicalSpecific) obj).getKey());
+ }
+ }
+
+ public int hashCode() {
+ return key.hashCode();
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple-config.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple-config.xml
new file mode 100644
index 0000000..26004c6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple-config.xml
@@ -0,0 +1,37 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <package name="Simple" namespace="/Simple" extends="webwork-default">
+
+ <action name="Open" class="cookbook2.Simple">
+ <result>/pages/Simple/Result.jsp</result>
+ <result name="input">/pages/Simple/Input.jsp</result>
+ </action>
+
+ <action name="View">
+ <result>/pages/Simple/index.jsp</result>
+ </action>
+
+ <action name="View-Input">
+ <result type="plaintext">/pages/Simple/Input.jsp</result>
+ </action>
+
+ <action name="View-Result">
+ <result type="plaintext">/pages/Simple/Result.jsp</result>
+ </action>
+
+ <action name="View-Action">
+ <result type="plaintext">/WEB-INF/src/java/cookbook2/Simple.java</result>
+ </action>
+
+ <action name="View-Config">
+ <result type="plaintext">/WEB-INF/classes/cookbook2/Simple-config.xml</result>
+ </action>
+
+ <action name="View-Validation">
+ <result type="plaintext">/WEB-INF/classes/cookbook2/Simple-validation.xml</result>
+ </action>
+
+ </package>
+</xwork>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple-validation.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple-validation.xml
new file mode 100644
index 0000000..c05fd23
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple-validation.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="name">
+ <field-validator type="requiredstring">
+ <message>You must enter a name</message>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple.java b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple.java
new file mode 100644
index 0000000..0a75e04
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/Simple.java
@@ -0,0 +1,27 @@
+package cookbook2;
+
+import com.opensymphony.xwork.ActionSupport;
+
+public class Simple extends ActionSupport {
+
+ private String name;
+
+ public void setName(String value) {
+ name = value;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+
+ public String execute() {
+
+ if (this.hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/ActionTag-config.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/ActionTag-config.xml
new file mode 100644
index 0000000..40f6c4b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/ActionTag-config.xml
@@ -0,0 +1,59 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <package name="ActionTag" extends="webwork-default" namespace="/ActionTag">
+
+ <action name="Open" class="cookbook2.actiontag.Result">
+ <result>/pages/ActionTag/Result.jsp</result>
+ <result name="input">/pages/ActionTag/Input.jsp</result>
+ </action>
+
+ <action name="View">
+ <result>/pages/ActionTag/index.jsp</result>
+ </action>
+
+ <action name="View-Input">
+ <result type="plaintext">/pages/ActionTag/Input.jsp</result>
+ </action>
+
+ <action name="languages" class="cookbook2.actiontag.Languages">
+ <result>/pages/ActionTag/languages.jsp</result>
+ </action>
+
+ <action name="colors">
+ <result>/pages/ActionTag/colors.jsp</result>
+ </action>
+
+ <action name="View-Result">
+ <result type="plaintext">/pages/ActionTag/Result.jsp</result>
+ </action>
+
+ <action name="View-Colors">
+ <result type="plaintext">/pages/ActionTag/colors.jsp</result>
+ </action>
+
+ <action name="View-Languages">
+ <result type="plaintext">/pages/ActionTag/languages.jsp</result>
+ </action>
+
+ <action name="View-Action">
+ <result type="plaintext">/WEB-INF/src/java/cookbook2/actiontag/Result.java</result>
+ </action>
+
+ <action name="View-Action-Languages">
+ <result type="plaintext">/WEB-INF/src/java/cookbook2/actiontag/Languages.java</result>
+ </action>
+
+ <action name="View-Test-Languages">
+ <result type="plaintext">/WEB-INF/src/test/cookbook2/actiontag/LanguagesTest.java</result>
+ </action>
+
+ <action name="View-Config">
+ <result type="plaintext">/WEB-INF/classes/cookbook2/actiontag/ActionTag-config.xml</result>
+ </action>
+
+ </package>
+
+</xwork>
+
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/Languages.java b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/Languages.java
new file mode 100644
index 0000000..bc97909
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/Languages.java
@@ -0,0 +1,26 @@
+package cookbook2.actiontag;
+
+import com.opensymphony.xwork.ActionSupport;
+import cookbook2.Select;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Languages extends ActionSupport {
+
+ List favoriteLanguages = new ArrayList();
+
+ public List getFavoriteLanguages() {
+ return favoriteLanguages;
+ }
+
+ public String execute() {
+
+ favoriteLanguages.add(new Select.Language("EnglishKey", "English Language"));
+ favoriteLanguages.add(new Select.Language("FrenchKey", "French Language"));
+ favoriteLanguages.add(new Select.Language("SpanishKey", "Spanish Language"));
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/Result.java b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/Result.java
new file mode 100644
index 0000000..0119e49
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/actiontag/Result.java
@@ -0,0 +1,27 @@
+package cookbook2.actiontag;
+
+import com.opensymphony.xwork.ActionSupport;
+
+public class Result extends ActionSupport {
+
+ String favoriteLanguage;
+
+ public void setFavoriteLanguage(String value) {
+ favoriteLanguage = value;
+ }
+
+ public String getFavoriteLanguage() {
+ return favoriteLanguage;
+ }
+
+ String favoriteColor;
+
+ public String getFavoriteColor() {
+ return favoriteColor;
+ }
+
+ public void setFavoriteColor(String value) {
+ favoriteColor = value;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/DirectoryEntry.java b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/DirectoryEntry.java
new file mode 100644
index 0000000..87fada9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/DirectoryEntry.java
@@ -0,0 +1,77 @@
+package cookbook2.pojo;
+
+import java.util.Date;
+
+public class DirectoryEntry {
+
+ private String firstname;
+
+ private String lastname;
+
+ private String extension;
+
+ private String username;
+
+ private Date hired;
+
+ private Integer hours;
+
+ private Boolean editor;
+
+ public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String value) {
+ firstname = value;
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String value) {
+ lastname = value;
+ }
+
+ public String getExtension() {
+ return extension;
+ }
+
+ public void setExtension(String value) {
+ extension = value;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ public Date getHired() {
+ return hired;
+ }
+
+ public void setHired(Date value) {
+ hired = value;
+ }
+
+ public Integer getHours() {
+ return hours;
+ }
+
+ public void setHours(Integer value) {
+ hours = value;
+ }
+
+ public Boolean getEditor() {
+ return editor;
+ }
+
+ public void setEditor(Boolean value) {
+ editor = value;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Pojo-config.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Pojo-config.xml
new file mode 100644
index 0000000..e687e60
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Pojo-config.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <package name="Pojo" namespace="/Pojo" extends="webwork-default">
+
+ <action name="Open" class="cookbook2.pojo.Result">
+ <result>/pages/Pojo/Result.jsp</result>
+ <result name="input">/pages/Pojo/Input.jsp</result>
+ </action>
+
+ <action name="View">
+ <result>/pages/Pojo/index.jsp</result>
+ </action>
+
+ <action name="View-Input">
+ <result type="plaintext">/pages/Pojo/Input.jsp</result>
+ </action>
+
+ <action name="View-Result">
+ <result type="plaintext">/pages/Pojo/Result.jsp</result>
+ </action>
+
+ <action name="View-Action-Entry">
+ <result type="plaintext">/WEB-INF/src/java/cookbook2/pojo/DirectoryEntry.java</result>
+ </action>
+
+ <action name="View-Config">
+ <result type="plaintext">/WEB-INF/classes/cookbook2/pojo/Pojo-config.xml</result>
+ </action>
+
+ </package>
+</xwork>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Result-validation.xml b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Result-validation.xml
new file mode 100644
index 0000000..5ee9b12
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Result-validation.xml
@@ -0,0 +1,49 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="firstname">
+ <field-validator type="requiredstring">
+ <message>You must enter a first name</message>
+ </field-validator>
+ </field>
+
+ <field name="lastname">
+ <field-validator type="requiredstring">
+ <message>You must enter a last name</message>
+ </field-validator>
+ </field>
+
+ <field name="username">
+ <field-validator type="email">
+ <message>You must enter a valid email address</message>
+ </field-validator>
+ </field>
+
+ <field name="extension">
+ <field-validator type="requiredstring">
+ <message>You must enter a telephone extension</message>
+ </field-validator>
+ </field>
+
+ <field name="hired">
+ <field-validator type="date">
+ <param name="min">07/25/2005</param>
+ <message>Hire date must be after 27 Jan 2005</message>
+ </field-validator>
+ </field>
+
+ <field name="hours">
+ <field-validator type="int">
+ <param name="min">1</param>
+ <param name="max">40</param>
+ <message>Hours must between 1 and 40, inclusive></message>
+ </field-validator>
+ </field>
+
+ <field name="editor">
+ <field-validator type="bool">
+ <message>Editor must be TRUE or FALSE</message>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Result.java b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Result.java
new file mode 100644
index 0000000..3e13e21
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/cookbook2/pojo/Result.java
@@ -0,0 +1,14 @@
+package cookbook2.pojo;
+
+import com.opensymphony.xwork.ActionSupport;
+import com.opensymphony.xwork.ModelDriven;
+
+public class Result extends ActionSupport implements ModelDriven {
+
+ private DirectoryEntry directoryEntry = new DirectoryEntry();
+
+ public Object getModel() {
+ return directoryEntry;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/webwork.properties b/struts-sandbox/struts2/apps/cookbook/src/java/webwork.properties
new file mode 100644
index 0000000..391807d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/webwork.properties
@@ -0,0 +1,3 @@
+webwork.objectFactory = spring
+webwork.devMode = true
+webwork.action.extension = do,jspa
diff --git a/struts-sandbox/struts2/apps/cookbook/src/java/xwork.xml b/struts-sandbox/struts2/apps/cookbook/src/java/xwork.xml
new file mode 100644
index 0000000..2353672
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/java/xwork.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
+
+<xwork>
+
+ <include file="webwork-default.xml"/>
+
+ <include file="cookbook2/Home-config.xml"/>
+
+ <include file="cookbook2/Hello-config.xml"/>
+
+ <include file="cookbook2/Simple-config.xml"/>
+
+ <include file="cookbook2/pojo/Pojo-config.xml"/>
+
+ <include file="cookbook2/Select-config.xml"/>
+
+ <include file="cookbook2/actiontag/ActionTag-config.xml"/>
+
+ <include file="cookbook2/Buttons-config.xml"/>
+
+</xwork>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/test/cookbook2/actiontag/LanguagesTest.java b/struts-sandbox/struts2/apps/cookbook/src/test/cookbook2/actiontag/LanguagesTest.java
new file mode 100644
index 0000000..93b7b42
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/test/cookbook2/actiontag/LanguagesTest.java
@@ -0,0 +1,34 @@
+package cookbook2.actiontag;
+
+import cookbook2.Select;
+import junit.framework.TestCase;
+
+import java.util.List;
+
+public class LanguagesTest extends TestCase {
+
+ private Languages action;
+
+ public void setUp() {
+
+ action = new Languages();
+
+ }
+
+ public void testContents() throws Exception {
+
+ List list = action.getFavoriteLanguages();
+ assertNotNull("List is null!", list);
+ assertTrue("List is not empty", list.size() == 0);
+
+ action.execute();
+
+ List list2 = action.getFavoriteLanguages();
+ assertNotNull("List is null!", list2);
+ assertTrue("List is empty!", list.size() > 0);
+ Select.Language entry = (Select.Language) list.get(0);
+ assertNotNull("Entry is null", entry);
+ assertTrue("Entry is empty", entry.getDescription().length() > 0);
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/Home.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/Home.jsp
new file mode 100644
index 0000000..3e6ca51
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/Home.jsp
@@ -0,0 +1,191 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>Struts Action 2 Cookbook</title>
+
+ <link href="<ww:url value="/css/cookbook.css"/>" rel="stylesheet" type="text/css"/>
+</head>
+
+<body>
+<h2>Struts Action 2 Cookbook -- Examples with Code</h2>
+
+<p>
+ This is a collection of working examples which demonstrate how to code
+ some common web application use cases.
+</p>
+
+<p>
+ To navigate your way through the examples, the following icons will help:
+</p>
+<table border="0" cellspacing="5" width="85%">
+ <tr valign="top">
+ <td width="30"><ww:include value="/icon-open.jsp"/></td>
+ <td>Execute the example</td>
+ </tr>
+ <tr valign="top">
+ <td><ww:include value="/icon-view.jsp"/></td>
+ <td>View the source code for the example</td>
+ </tr>
+ <tr valign="top">
+ <td width="30"><ww:include value="/icon-home.jsp"/></td>
+ <td>Return to this screen</td>
+ </tr>
+</table>
+<br/>
+<table width="85%" border="0" cellpadding="2" cellspacing="5">
+
+<tr valign="top">
+ <td>Hello World</td>
+ <td>
+
+ <ww:url id="Hello_Open" action="Open" namespace="/Hello"/>
+ <ww:a href="%{Hello_Open}">
+ <ww:include value="/icon-open.jsp"/>
+ </ww:a>
+ <ww:a href="%{Hello_Open}">Execute</ww:a>
+
+ </td>
+ <td>
+
+ <ww:url id="Hello_View" action="View" namespace="/Hello"/>
+ <ww:a href="%{Hello_View}">
+ <ww:include value="/icon-view.jsp"/>
+ </ww:a>
+ <ww:a href="%{Hello_View}">
+ View Source
+ </ww:a>
+
+ </td>
+</tr>
+
+
+<tr valign="top">
+ <td>Simple Input Form using Action Properties</td>
+ <td>
+
+ <ww:url id="Simple_Open" action="Open!input" namespace="/Simple"/>
+ <ww:a href="%{Simple_Open}">
+ <ww:include value="/icon-open.jsp"/>
+ </ww:a>
+ <ww:a href="%{Simple_Open}">Execute</ww:a>
+
+ </td>
+ <td>
+
+ <ww:url id="Simple_View" action="View" namespace="/Simple"/>
+ <ww:a href="%{Simple_View}">
+ <ww:include value="/icon-view.jsp"/>
+ </ww:a>
+ <ww:a href="%{Simple_View}">
+ View Source
+ </ww:a>
+
+ </td>
+</tr>
+
+
+<tr valign="top">
+ <td>Input Form using a POJO</td>
+ <td>
+
+ <ww:url id="Pojo_Open" action="Open!input" namespace="/Pojo"/>
+ <ww:a href="%{Pojo_Open}">
+ <ww:include value="/icon-open.jsp"/>
+ </ww:a>
+ <ww:a href="%{Pojo_Open}">Execute</ww:a>
+
+ </td>
+ <td>
+
+ <ww:url id="Pojo_View" action="View" namespace="/Pojo"/>
+ <ww:a href="%{Pojo_View}">
+ <ww:include value="/icon-view.jsp"/>
+ </ww:a>
+ <ww:a href="%{Pojo_View}">
+ View Source
+ </ww:a>
+
+ </td>
+</tr>
+
+<tr valign="top">
+ <td>Complex Input Form using Select Controls</td>
+ <td>
+
+ <ww:url id="Select_Open" action="Open!input" namespace="/Select"/>
+ <ww:a href="%{Select_Open}">
+ <ww:include value="/icon-open.jsp"/>
+ </ww:a>
+ <ww:a href="%{Select_Open}">Execute</ww:a>
+
+ </td>
+ <td>
+
+ <ww:url id="Select_View" action="View" namespace="/Select"/>
+ <ww:a href="%{Select_View}">
+ <ww:include value="/icon-view.jsp"/>
+ </ww:a>
+ <ww:a href="%{Select_View}">
+ View Source
+ </ww:a>
+
+ </td>
+</tr>
+
+<tr valign="top">
+ <td>Action as Page Controllers</td>
+ <td>
+
+ <ww:url id="ActionTag_Open" action="Open!input" namespace="/ActionTag"/>
+ <ww:a href="%{ActionTag_Open}">
+ <ww:include value="/icon-open.jsp"/>
+ </ww:a>
+ <ww:a href="%{ActionTag_Open}">Execute</ww:a>
+
+ </td>
+ <td>
+
+ <ww:url id="ActionTag_View" action="View" namespace="/ActionTag"/>
+ <ww:a href="%{ActionTag_View}">
+ <ww:include value="/icon-view.jsp"/>
+ </ww:a>
+ <ww:a href="%{ActionTag_View}">
+ View Source
+ </ww:a>
+
+ </td>
+</tr>
+
+<tr valign="top">
+ <td>Detecting Buttons</td>
+ <td>
+
+ <ww:url id="Buttons_Open" action="Open!input" namespace="/Buttons"/>
+ <ww:a href="%{Buttons_Open}">
+ <ww:include value="/icon-open.jsp"/>
+ </ww:a>
+ <ww:a href="%{Buttons_Open}">Execute</ww:a>
+
+ </td>
+ <td>
+
+ <ww:url id="Buttons_View" action="View" namespace="/Buttons"/>
+ <ww:a href="%{Buttons_View}">
+ <ww:include value="/icon-view.jsp"/>
+ </ww:a>
+ <ww:a href="%{Buttons_View}">
+ View Source
+ </ww:a>
+
+ </td>
+</tr>
+
+
+</table>
+<p><img src="<ww:url value="/images/valid-xhtml10.png"/>" alt="Valid XHTML 1.0!" height="31" width="88"/></p>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/WEB-INF/applicationContext.xml b/struts-sandbox/struts2/apps/cookbook/src/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 0000000..b98e1d8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans default-autowire="autodetect">
+ <!-- add your spring beans here -->
+</beans>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/WEB-INF/web.xml b/struts-sandbox/struts2/apps/cookbook/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..26c373a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Action2 Cookbook</display-name>
+
+ <filter>
+ <filter-name>webwork</filter-name>
+ <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>webwork</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>Home.jsp</welcome-file>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <!--
+ This typically isn't required, as the taglib is included in webwork.jar.
+ If you really need a taglib configuration within web.xml, copy webwork/src/java/META-INF/taglib.tld
+ to the WEB-INF directory as webwork.tld.
+ -->
+ <!--taglib>
+ <taglib-uri>webwork</taglib-uri>
+ <taglib-location>/WEB-INF/webwork.tld</taglib-location>
+ </taglib-->
+</web-app>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/css/cookbook.css b/struts-sandbox/struts2/apps/cookbook/src/webapp/css/cookbook.css
new file mode 100644
index 0000000..b772127
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/css/cookbook.css
@@ -0,0 +1,68 @@
+body {
+ margin: 2% 10%;
+ font: 12px / 1.4 Verdana, Geneva, Arial, Helvetica, sans-serif;
+}
+
+h1 {
+ font-size: 20px;
+}
+
+h2 {
+ font-size: 16px;
+ margin: 3em 0 0.5em;
+}
+
+h3 {
+ font-size: 14px;
+ margin: 2em 0 0.5em;
+}
+
+h4 {
+ font-size: 12px;
+}
+
+h5 {
+ font-size: 11px;
+}
+
+h6 {
+ font-size: 10px;
+}
+
+hr {
+ color: #999999;
+ height: 1px;
+}
+
+img {
+ border: none;
+}
+
+th {
+ text-align: left;
+}
+
+.error {
+ color: #FF0000;
+}
+
+.icon {
+ float: right;
+ margin: 5px;
+}
+
+.intro {
+ font-size: 14px;
+ line-height: 1.6;
+ font-weight: bold;
+}
+
+.label {
+ font-weight: bold;
+ width: 260px;
+}
+
+.result {
+ width: 100%;
+ background: #eef;
+}
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/header-index.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/header-index.jsp
new file mode 100644
index 0000000..4a6913e
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/header-index.jsp
@@ -0,0 +1,12 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<p>
+ <a href="<ww:url action="Home" />">
+ <img src="<ww:url value="/images/return.gif"/>" alt="Home" height="24" width="24" hspace="4" border="0"
+ align="top" class="icon"/>
+ </a>
+ <a href="<ww:url action="Open!input" />">
+ <img src="<ww:url value="/images/execute.gif"/>" alt="Open" height="24" width="24" hspace="4" border="0"
+ align="top" class="icon"/>
+ </a>
+</p>
+
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/header-result.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/header-result.jsp
new file mode 100644
index 0000000..5fdc8bc
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/header-result.jsp
@@ -0,0 +1,12 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<p>
+ <a href="<ww:url action="Home" />">
+ <img src="<ww:url value="/images/return.gif"/>" alt="Home" height="24" width="24" hspace="4" border="0"
+ align="top" class="icon"/>
+ </a>
+ <a href="<ww:url action="View" />">
+ <img src="<ww:url value="/images/code.gif"/>"
+ alt="Open" height="24" width="24" hspace="4"
+ border="0" align="top" class="icon"/>
+ </a>
+</p>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-home.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-home.jsp
new file mode 100644
index 0000000..d74fe18
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-home.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<img src="<ww:url value="/images/return.gif"/>" alt="Home" height="24" width="24" hspace="4" border="0" align="top"
+ class="inline"/>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-open.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-open.jsp
new file mode 100644
index 0000000..20caf66
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-open.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<img src="<ww:url value="/images/execute.gif"/>" alt="Open" height="24" width="24" hspace="4" border="0" align="top"
+ class="inline"/>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-view.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-view.jsp
new file mode 100644
index 0000000..bfbb8a5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/icon-view.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<img src="<ww:url value="/images/code.gif"/>" alt="View" border="0" height="24" width="24" hspace="4" align="top"
+ class="inline"/>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/images/code.gif b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/code.gif
new file mode 100644
index 0000000..93af2cd
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/code.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/images/execute.gif b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/execute.gif
new file mode 100644
index 0000000..f64d70f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/execute.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/images/jsp.gif b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/jsp.gif
new file mode 100644
index 0000000..6f57d52
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/jsp.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/images/return.gif b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/return.gif
new file mode 100644
index 0000000..af4f68f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/return.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/images/valid-xhtml10.png b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/valid-xhtml10.png
new file mode 100644
index 0000000..2275ee6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/images/valid-xhtml10.png
Binary files differ
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/index.html b/struts-sandbox/struts2/apps/cookbook/src/webapp/index.html
new file mode 100644
index 0000000..4b426a2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Home.jsp">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/Input.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/Input.jsp
new file mode 100644
index 0000000..16e3530
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/Input.jsp
@@ -0,0 +1,32 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+
+<html>
+<head>
+ <title>CookBook - Action as Page Controller</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+
+<ww:include value="/header-result.jsp"/>
+
+<h1>Action as Page Controller</h1>
+
+<p>
+ The controls on this page is each populated by its own action
+ and formatted on its own server page fragment.
+ Accordingly, each control could be re-used on any number of pages.
+</p>
+
+<ww:form method="POST">
+
+ <ww:action name="languages" namespace="/ActionTag" executeResult="true"/>
+
+ <ww:action name="colors" namespace="/ActionTag" executeResult="true"/>
+
+ <ww:submit/>
+
+</ww:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/Result.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/Result.jsp
new file mode 100644
index 0000000..bda5ddb
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/Result.jsp
@@ -0,0 +1,19 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Action as Page Controller</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+<ww:include value="/header-result.jsp"/>
+
+<h1>Input Result</h1>
+
+<table>
+ <ww:label label="Favorite Language" name="favoriteLanguage"/>
+ <ww:label label="Favorite Color" name="favoriteColor"/>
+</table>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/colors.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/colors.jsp
new file mode 100644
index 0000000..d1de436
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/colors.jsp
@@ -0,0 +1,10 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<ww:select
+ tooltip="Choose Your Favourite Color"
+ label="Favorite Color"
+ list="{'Red', 'Blue', 'Green'}"
+ name="favoriteColor"
+ emptyOption="true"
+ headerKey="None"
+ headerValue="None"/>
+
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/index.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/index.jsp
new file mode 100644
index 0000000..7fa2ca8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/index.jsp
@@ -0,0 +1,53 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>Source Code for Action as Page Controller</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+
+<ww:include value="/header-index.jsp"/>
+
+<h1>Source Code for Action as Page Controller</h1>
+<hr noshade="noshade"/>
+
+<h2>Server Pages</h2>
+<ul><li>
+ <a href="<ww:url action="View-Input"/>">Input.jsp</a>
+</li><li>
+ <a href="<ww:url action="View-Result"/>">Result.jsp</a>
+</li><li>
+ <a href="<ww:url action="View-Colors"/>">colors.jsp</a>
+</li><li>
+ <a href="<ww:url action="View-Languages"/>">languages.jsp</a>
+</li></ul>
+
+<h2>Actions</h2>
+<ul><li>
+ <a href="<ww:url action="View-Action"/>">Result.java</a>
+</li><li>
+ <a href="<ww:url action="View-Action-Languages"/>">Languages.java</a>
+</li></ul>
+
+
+<h2>Tests</h2>
+<ul><li>
+ <a href="<ww:url action="View-Test-Languages"/>">LanguagesTest.java</a>
+</li></ul>
+
+
+<h2>Configuration files</h2>
+<ul><li>
+ <a href="<ww:url action="View-Config"/>">ActionTag-config.xml</a>
+</li></ul>
+
+<h2>Other source files</h2>
+
+<p>None</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/languages.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/languages.jsp
new file mode 100644
index 0000000..df7d04a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/ActionTag/languages.jsp
@@ -0,0 +1,14 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<ww:select
+ tooltip="Choose Your Favorite Language"
+ label="Favorite Language"
+ list="favoriteLanguages"
+ name="favoriteLanguage"
+ listKey="key"
+ listValue="description"
+ emptyOption="true"
+ headerKey="None"
+ headerValue="None"/>
+
+
+
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/Input.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/Input.jsp
new file mode 100644
index 0000000..f9108a1
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/Input.jsp
@@ -0,0 +1,24 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Detecting Buttons</title>
+ <ww:head/>
+</head>
+
+<body>
+
+<ww:form method="POST">
+
+ <ww:textfield
+ label="Message"
+ name="message"
+ tooltip="Enter your text message here"/>
+
+ <ww:submit name="ford" value="Send Message to Ford"/>
+ <ww:submit name="marvin" value="Send Message to Marvin"/>
+ <ww:submit name="trillian" value="Send Message to Trillian"/>
+
+</ww:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/Result.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/Result.jsp
new file mode 100644
index 0000000..1b2c66d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/Result.jsp
@@ -0,0 +1,17 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Detecting Buttons</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+<ww:include value="/header-result.jsp"/>
+
+<h1>Input Result</h1>
+<table>
+ <ww:label label="Message" name="message"/>
+ <ww:label label="Sent to" name="recipient"/>
+</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/index.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/index.jsp
new file mode 100644
index 0000000..d41756a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Buttons/index.jsp
@@ -0,0 +1,40 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>Source Code for Detecting Buttons</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+
+<ww:include value="/header-index.jsp"/>
+
+<h1>Source Code for Detecting Buttons</h1>
+<hr noshade="noshade"/>
+
+<h2>Server Pages</h2>
+<ul><li>
+ <a href="<ww:url action="View-Input"/>">Input.jsp</a>
+</li><li>
+ <a href="<ww:url action="View-Result"/>">Result.jsp</a>
+</li></ul>
+
+<h2>Actions</h2>
+<ul><li>
+ <a href="<ww:url action="View-Action"/>">Buttons.java</a>
+</li></ul>
+
+<h2>Configuration files</h2>
+<ul><li>
+ <a href="<ww:url action="View-Config"/>">Buttons-config.xml</a>
+</li></ul>
+
+<h2>Other source files</h2>
+
+<p>None</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Hello/Result.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Hello/Result.jsp
new file mode 100644
index 0000000..d1d3f8e
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Hello/Result.jsp
@@ -0,0 +1,14 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<html>
+<head>
+ <title>Cookbook - Hello World</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+<ww:include value="/header-result.jsp"/>
+
+<h1>Don't panic! Struts is mostly harmless ...</h1>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Hello/index.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Hello/index.jsp
new file mode 100644
index 0000000..543a0c2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Hello/index.jsp
@@ -0,0 +1,36 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Source Code for Hello World</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+
+<ww:include value="/header-index.jsp"/>
+
+<h1>Source Code for Hello World</h1>
+<hr noshade="noshade"/>
+
+<h2>Server Pages</h2>
+<ul><li>
+ <a href="<ww:url action="View-Result"/>">Result.jsp</a>
+</li></ul>
+
+<h2>Actions</h2>
+
+<p>None</p>
+
+<h2>Configuration files</h2>
+<ul><li>
+ <a href="<ww:url action="View-Config"/>">Hello-config.xml</a>
+</li></ul>
+
+<h2>Other source files</h2>
+
+<p>None</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/Input.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/Input.jsp
new file mode 100644
index 0000000..6eff05d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/Input.jsp
@@ -0,0 +1,50 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Input Form using a POJO</title>
+ <ww:head/>
+</head>
+
+<body>
+
+<ww:form method="POST">
+ <ww:textfield
+ label="First Name"
+ name="firstname"
+ tooltip="Enter your first name here"/>
+
+ <ww:textfield
+ label="Last Name"
+ name="lastname"
+ tooltip="Enter your last name here"/>
+
+ <ww:textfield
+ label="Telephone"
+ name="extension"
+ tooltip="Enter your office telephone number here"/>
+
+ <ww:textfield
+ label="Email Address"
+ name="username"
+ tooltip="Enter your email address here"/>
+
+ <ww:datepicker
+ tooltip="Select your hire date"
+ label="Hire Date"
+ name="hired"/>
+
+ <ww:textfield
+ label="Hours"
+ name="hours"
+ tooltip="Enter the number of hours you are scheduled to work"/>
+
+ <ww:checkbox
+ label="Editor?"
+ name="editor"
+ tooltip="Are you authorized to edit directory entries?"/>
+
+ <ww:submit/>
+</ww:form>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/Result.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/Result.jsp
new file mode 100644
index 0000000..82951c7
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/Result.jsp
@@ -0,0 +1,22 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Input Form using a POJO</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+<ww:include value="/header-result.jsp"/>
+
+<h1>Input Result</h1>
+<table>
+ <ww:label label="First Name" name="firstname"/>
+ <ww:label label="Last Name" name="lastname"/>
+ <ww:label label="Telephone" name="extension"/>
+ <ww:label label="User Name" name="username"/>
+ <ww:label label="Hired" name="hired"/>
+ <ww:label label="Hours" name="hours"/>
+ <ww:label label="Editor?" name="editor"/>
+</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/index.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/index.jsp
new file mode 100644
index 0000000..2400284
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Pojo/index.jsp
@@ -0,0 +1,40 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>Source Code for Input Form using a POJO</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+
+<ww:include value="/header-index.jsp"/>
+
+<h1>Source Code for Input Form using a POJO</h1>
+<hr noshade="noshade"/>
+
+<h2>Server Pages</h2>
+<ul><li>
+ <a href="<ww:url action="View-Input"/>">Input.jsp</a>
+</li><li>
+ <a href="<ww:url action="View-Result"/>">Result.jsp</a>
+</li></ul>
+
+<h2>Actions</h2>
+<ul><li>
+ <a href="<ww:url action="View-Action-Entry"/>">DirectoryEntry.java</a>
+</li></ul>
+
+<h2>Configuration files</h2>
+<ul><li>
+ <a href="<ww:url action="View-Config"/>">Pojo-config.xml</a>
+</li></ul>
+
+<h2>Other source files</h2>
+
+<p>None</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/Input.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/Input.jsp
new file mode 100644
index 0000000..fa84cab
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/Input.jsp
@@ -0,0 +1,114 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Complex Input Form using Select Controls</title>
+ <ww:head/>
+</head>
+
+<body>
+
+<ww:form method="POST">
+<ww:textfield
+ label="Name"
+ name="name"
+ tooltip="Enter your Name here"/>
+
+<ww:datepicker
+ tooltip="Select Your Birthday"
+ label="Birthday"
+ name="birthday"/>
+
+<ww:textarea
+ tooltip="Enter your Biography"
+ label="Biograph"
+ name="bio"
+ cols="20"
+ rows="3"/>
+
+<ww:select
+ tooltip="Choose Your Favourite Color"
+ label="Favorite Color"
+ list="{'Red', 'Blue', 'Green'}"
+ name="favoriteColor"
+ emptyOption="true"
+ headerKey="None"
+ headerValue="None"/>
+
+<ww:select
+ tooltip="Choose Your Favourite Language"
+ label="Favourite Language"
+ list="favouriteLanguages"
+ name="favouriteLanguage"
+ listKey="key"
+ listValue="description"
+ emptyOption="true"
+ headerKey="None"
+ headerValue="None"/>
+
+<ww:checkboxlist
+ tooltip="Choose your Friends"
+ label="Friends"
+ list="{'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}"
+ name="friends"/>
+
+<ww:checkbox
+ tooltip="Confirmed that your are Over 18"
+ label="Age 18+"
+ name="legalAge"/>
+
+<ww:doubleselect
+ tooltip="Choose Your State"
+ label="State"
+ name="region" list="{'North', 'South'}"
+ value="'South'"
+ doubleValue="'Florida'"
+ doubleList="top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}"
+ doubleName="state"
+ headerKey="-1"
+ headerValue="---------- Please Select ----------"
+ emptyOption="true"/>
+
+<ww:doubleselect
+ tooltip="Choose your Vehicle"
+ label="Favourite Vehical"
+ name="favouriteVehicalType"
+ list="vehicalTypeList"
+ listKey="key"
+ listValue="description"
+ value="'MotorcycleKey'"
+ doubleValue="'YamahaKey'"
+ doubleList="vehicalSpecificList"
+ doubleListKey="key"
+ doubleListValue="description"
+ doubleName="favouriteVehicalSpecific" headerKey="-1"
+ headerValue="---------- Please Select ----------"
+ emptyOption="true"/>
+
+<ww:file
+ tooltip="Upload Your Picture"
+ label="Picture"
+ name="picture"/>
+
+<ww:optiontransferselect
+ tooltip="Select Your Favourite Cartoon Characters"
+ label="Favourite Cartoons Characters"
+ name="leftSideCartoonCharacters"
+ leftTitle="Left Title"
+ rightTitle="Right Title"
+ list="{'Popeye', 'He-Man', 'Spiderman'}"
+ multiple="true"
+ headerKey="headerKey"
+ headerValue="--- Please Select ---"
+ emptyOption="true"
+ doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
+ doubleName="rightSideCartoonCharacters"
+ doubleHeaderKey="doubleHeaderKey"
+ doubleHeaderValue="--- Please Select ---"
+ doubleEmptyOption="true"
+ doubleMultiple="true"/>
+
+<ww:submit onclick="alert('Don't Panic! (Just press OK to continue)');"/>
+</ww:form>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/Result.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/Result.jsp
new file mode 100644
index 0000000..feda391
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/Result.jsp
@@ -0,0 +1,44 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Complex Input Form using Select Controls</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+<ww:include value="/header-result.jsp"/>
+
+<h1>Input Result</h1>
+<table>
+ <ww:label label="Name" name="name"/>
+ <ww:label label="Birthday" name="birthday"/>
+ <ww:label label="Biography" name="bio"/>
+ <ww:label label="Favourite Color" name="favouriteColor"/>
+ <ww:label label="Friends" name="friends"/>
+ <ww:label label="Legal Age" name="legalAge"/>
+ <ww:label label="Region" name="region"/>
+ <ww:label label="State" name="state"/>
+ <ww:label label="Picture" name="picture"/>
+ <ww:label label="Favourite Language" name="favouriteLanguage"/>
+ <ww:label label="Favourite Vehical Type" name="favouriteVehicalType"/>
+ <ww:label label="Favourite Vehical Specific" name="favouriteVehicalSpecific"/>
+ <tr>
+ <td>Favourite Cartoon Characters (Left):</td>
+ <td>
+ <ww:iterator value="leftSideCartoonCharacters" status="stat">
+ <ww:property value="%{#stat.count}"/>.<ww:property value="top"/>
+ </ww:iterator>
+ </td>
+ </tr>
+ <tr>
+ <td>Favourite Cartoon Characters (Right):</td>
+ <td>
+ <ww:iterator value="rightSideCartoonCharacters" status="stat">
+ <ww:property value="%{#stat.count}"/>.<ww:property value="top"/>
+ </ww:iterator>
+ </td>
+ </tr>
+</table>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/index.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/index.jsp
new file mode 100644
index 0000000..37ea06c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Select/index.jsp
@@ -0,0 +1,40 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>Source Code for Complex Input Form using Select Controls</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+
+<ww:include value="/header-index.jsp"/>
+
+<h1>Source Code for Complex Input Form using Select Controls</h1>
+<hr noshade="noshade"/>
+
+<h2>Server Pages</h2>
+<ul><li>
+ <a href="<ww:url action="View-Input"/>">Input.jsp</a>
+</li><li>
+ <a href="<ww:url action="View-Result"/>">Result.jsp</a>
+</li></ul>
+
+<h2>Actions</h2>
+<ul><li>
+ <a href="<ww:url action="View-Action"/>">Select.java</a>
+</li></ul>
+
+<h2>Configuration files</h2>
+<ul><li>
+ <a href="<ww:url action="View-Config"/>">Select-config.xml</a>
+</li></ul>
+
+<h2>Other source files</h2>
+
+<p>None</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/Input.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/Input.jsp
new file mode 100644
index 0000000..54900b8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/Input.jsp
@@ -0,0 +1,14 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Simple Input Form using Action Properties</title>
+ <ww:head/>
+</head>
+
+<body>
+<ww:form method="POST">
+ <ww:textfield label="Please enter your name" name="name"/>
+ <ww:submit/>
+</ww:form>
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/Result.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/Result.jsp
new file mode 100644
index 0000000..ddddce9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/Result.jsp
@@ -0,0 +1,15 @@
+<%@ taglib prefix="ww" uri="/webwork" %>
+<html>
+<head>
+ <title>Cookbook - Simple Input Form using Action Properties</title>
+</head>
+<link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+
+<body>
+<ww:include value="/header-result.jsp"/>
+
+<h1>Don't panic <ww:property value="name"/>!
+ Struts is mostly harmless ...</h1>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/index.jsp b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/index.jsp
new file mode 100644
index 0000000..f6121e1
--- /dev/null
+++ b/struts-sandbox/struts2/apps/cookbook/src/webapp/pages/Simple/index.jsp
@@ -0,0 +1,42 @@
+<%@ taglib uri="/webwork" prefix="ww" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title>Source Code for Simple Input Form using Action Properties</title>
+ <link rel="stylesheet" type="text/css" href="<ww:url value="/css/cookbook.css" />">
+</head>
+
+<body>
+
+<ww:include value="/header-index.jsp"/>
+
+<h1>Source Code for Simple Input Form using Action Properties</h1>
+<hr noshade="noshade"/>
+
+<h2>Server Pages</h2>
+<ul><li>
+ <a href="<ww:url action="View-Input"/>">Input.jsp</a>
+</li><li>
+ <a href="<ww:url action="View-Result"/>">Result.jsp</a>
+</li></ul>
+
+<h2>Actions</h2>
+<ul><li>
+ <a href="<ww:url action="View-Action"/>">Simple.java</a>
+</li></ul>
+
+<h2>Configuration files</h2>
+<ul><li>
+ <a href="<ww:url action="View-Config"/>">Simple-config.xml</a>
+</li><li>
+ <a href="<ww:url action="View-Validation"/>">Simple-validation.xml</a>
+</li></ul>
+
+<h2>Other source files</h2>
+
+<p>None</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/README.txt b/struts-sandbox/struts2/apps/mailreader-bang/README.txt
new file mode 100644
index 0000000..f63bc7c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/README.txt
@@ -0,0 +1,26 @@
+README.txt - mailreader-bang
+
+The MailReader demonstrates a localized application with a master/child
+CRUD workflow.
+
+This rendition also demonstrates switching from the "bang" syntax for
+invoking dynamic methods to a general-purpose wild card approach.
+
+To switch between approaches, edit the struts.xml file to include either
+the struts-bang.xml file OR the struts-wildcard.xml. (But not both.)
+
+When using the -bang application, be sure that the
+struts.enable.DynamicMethodInvocation property is set to "true".
+
+For the -wilcard application. be sure that the
+struts.enable.DynamicMethodInvocation property is set to "false".
+
+See the Sandbox for other MailReader examples using other architectures.
+
+* http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2/apps/
+
+For more about the MailReader applicaton genneraly, visit Struts University.
+
+* http://www.StrutsUniversity.org/
+
+----------------------------------------------------------------------------
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/pom.xml b/struts-sandbox/struts2/apps/mailreader-bang/pom.xml
new file mode 100644
index 0000000..f4915e2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-apps</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-mailreader</artifactId>
+ <packaging>war</packaging>
+ <name>Starter Webapp</name>
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>struts-mailreader-dao</artifactId>
+ <version>1.3.5-SNAPSHOT</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty6-plugin</artifactId>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-j2ee_1.4_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/ApplicationListener.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/ApplicationListener.java
new file mode 100644
index 0000000..c32fb71
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/ApplicationListener.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+package mailreader2;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Subscription information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class ApplicationListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/AuthenticationInterceptor.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/AuthenticationInterceptor.java
new file mode 100644
index 0000000..10cc368
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/AuthenticationInterceptor.java
@@ -0,0 +1,31 @@
+package mailreader2;
+
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.Action;
+import java.util.Map;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class AuthenticationInterceptor implements Interceptor {
+
+ public void destroy () {}
+
+ public void init() {}
+
+ public String intercept(ActionInvocation actionInvocation) throws Exception {
+
+ Map session = actionInvocation.getInvocationContext().getSession();
+
+ User user = (User) session.get(Constants.USER_KEY);
+
+ boolean isAuthenticated = (null!=user) && (null!=user.getDatabase());
+
+ if (!isAuthenticated) {
+ return Action.LOGIN;
+ }
+ else {
+ return actionInvocation.invoke();
+ }
+
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Constants.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Constants.java
new file mode 100644
index 0000000..89d9607
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Constants.java
@@ -0,0 +1,125 @@
+/*
+ * $Id: Constants.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+/**
+ * <p> Manifest constants for the MailReader application. </p>
+ */
+public final class Constants {
+
+ // --- Tokens ----
+
+ /**
+ * <p> The token representing a "cancel" request. </p>
+ */
+ public static final String CANCEL = "cancel";
+
+ /**
+ * <p> The token representing a "create" task. </p>
+ */
+ public static final String CREATE = "Create";
+
+ /**
+ * <p> The application scope attribute under which our user database is
+ * stored. </p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ * <p> The token representing a "edit" task. </p>
+ */
+ public static final String DELETE = "Delete";
+
+ /**
+ * <p> The token representing a "edit" task. </p>
+ */
+ public static final String EDIT = "Edit";
+
+ /**
+ * <p> The package name for this application. </p>
+ */
+ public static final String PACKAGE = "org.apache.struts.apps.mailreader";
+
+ /**
+ * <p> The session scope attribute under which the Subscription object
+ * currently selected by our logged-in User is stored. </p>
+ */
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ /**
+ * <p> The session scope attribute under which the User object for the
+ * currently logged in user is stored. </p>
+ */
+ public static final String USER_KEY = "user";
+
+ /**
+ * <p>The token representing the "Host" property.
+ */
+ public static final String HOST = "host";
+
+
+ // ---- Error Messages ----
+
+ /**
+ * <p>
+ * A static message in case message resource is not loaded.
+ * </p>
+ */
+ public static final String ERROR_MESSAGES_NOT_LOADED =
+ "ERROR: Message resources not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p>
+ * A static message in case database resource is not loaded.
+ * <p>
+ */
+ public static final String ERROR_DATABASE_NOT_LOADED =
+ "ERROR: User database not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p>
+ * A standard key from the message resources file, to test if it is available.
+ * <p>
+ */
+ public static final String ERROR_DATABASE_MISSING = "error.database.missing";
+
+ /**
+ * <P>
+ * A "magic" username to trigger an ExpiredPasswordException for testing.
+ *</p>
+ */
+ public static final String EXPIRED_PASSWORD_EXCEPTION = "ExpiredPasswordException";
+
+ /**
+ * <p>
+ * Name of field to associate with authentification errors.
+ * <p>
+ */
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ // ---- Log Messages ----
+
+ /**
+ * <p> Message to log if saving a user fails. </p>
+ */
+ public static final String LOG_DATABASE_SAVE_ERROR =
+ " Unexpected error when saving User: ";
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logoff.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logoff.java
new file mode 100644
index 0000000..4cbafa5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logoff.java
@@ -0,0 +1,32 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+/**
+ * <p> Log user out of the current session. </p>
+ */
+public class Logoff extends MailreaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logon-validation.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logon-validation.xml
new file mode 100644
index 0000000..4a04c76
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logon-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logon.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logon.java
new file mode 100644
index 0000000..0c8fa73
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Logon.java
@@ -0,0 +1,45 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+
+/**
+ * <p> Validate a user logon. </p>
+ */
+public final class Logon extends MailreaderSupport {
+
+ public String execute() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport.java
new file mode 100644
index 0000000..71e971c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport.java
@@ -0,0 +1,559 @@
+/*
+ * $Id: BaseAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+import com.opensymphony.util.BeanUtils;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUser;
+
+import java.util.Map;
+
+/**
+ * <p> Base Action for MailreaderSupport application. </p>
+ * <p/>
+ * <p> Note that this class does NOT implement model driven because of the way
+ * the pre-existing model is designed. The MailReader DAO includes immutable
+ * fields that can only be set on construction, and some objects do not have a
+ * default construction. One approach would be to mirror all the DAO
+ * properties on the Actions. As an alternative, this implementations uses the
+ * DAO properties where possible, and uses local Action properties only as
+ * needed. To create new objects, a blank temporary object is constructed, and
+ * the page uses a mix of local Action properties and DAO properties. When the
+ * new object is to be saved, the local Action properties are used to create
+ * the object using the DAO factory methods, the input values are copied from
+ * the temporary object, and the new object is saved. It's kludge, but it
+ * avoids creating unnecessary local properties. Pick your poison.</p>
+ */
+public class MailreaderSupport extends ActionSupport
+ implements SessionAware, ApplicationAware {
+
+ /**
+ * Return CANCEL so apropriate result can be selected.
+ * @return "cancel" so apropriate result can be selected.
+ */
+ public String cancel() {
+ return Constants.CANCEL;
+ }
+
+
+ // ---- ApplicationAware ----
+
+ /**
+ * <p>Field to store application context or its proxy.</p>
+ * <p/>
+ * <p>The application context lasts for the life of the application. A
+ * reference to the database is stored in the application context at
+ * startup.</p>
+ */
+ private Map application;
+
+ /**
+ * <p>Store a new application context.</p>
+ *
+ * @param value A Map representing application state
+ */
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ /**
+ * <p>Provide application context.</p>
+ */
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- Task property (utilized by UI) ----
+
+ /**
+ * <p>Field to store workflow task.</p>
+ * <p/>
+ * <p>The Task is used to track the state of the CRUD workflows. It can be
+ * set to Constant.CREATE, Constant.EDIT, or Constant.DELETE as
+ * needed.</p>
+ */
+ private String task = null;
+
+
+ /**
+ * <p>Provide worklow task.</p>
+ *
+ * @return Returns the task.
+ */
+ public String getTask() {
+ return task;
+ }
+
+ /**
+ * <p>Store new workflow task.</p>
+ *
+ * @param value The task to set.
+ */
+ public void setTask(String value) {
+ task = value;
+ }
+
+ // ---- Token property (utilized by UI) ----
+
+ /**
+ * <p>Field to store double-submit guard.</p>
+ */
+ private String token = null;
+
+
+ /**
+ * <p>Provide Token.</p>
+ *
+ * @return Returns the token.
+ */
+ public String getToken() {
+ return token;
+ }
+
+ /**
+ * <p>Store new Token.</p>
+ *
+ * @param value The token to set.
+ */
+ public void setToken(String value) {
+ token = value;
+ }
+
+
+ // ---- Host property ----
+
+ /**
+ * <p>Field to store Subscription host.</p>
+ * <p/>
+ * <p> The host is an immutable property of the Subscrtion DAP object, so
+ * we need to store it locally until we are ready to create the
+ * Subscription. </p>
+ */
+ private String host;
+
+ /**
+ * <p>Provide tSubscription host.</p>
+ *
+ * @return host property
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * <p>Store new Subscription host.</p>
+ *
+ * @param value
+ */
+ public void setHost(String value) {
+ host = value;
+ }
+
+ // ---- Password property ----
+
+ /**
+ * <p>Field to store User password property.</p>
+ * <p/>
+ * <p>The User DAO object password proerty is immutable, so we store it
+ * locally until we are ready to create the object.</p>
+ */
+ private String password = null;
+
+
+ /**
+ * <p>Provide User password</p>
+ *
+ * @return Returns the password.
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * <p>Store new User Password</p>
+ *
+ * @param value The password to set.
+ */
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ // ---- Password2 property (confirmation) ----
+
+ /**
+ * <p>Field to store the User password confirmation.</p>
+ * <p/>
+ * <p>When a User object is created, we ask the client to enter the
+ * password twice, to help ensure the password is being typed
+ * correctly.</p>
+ */
+ private String password2 = null;
+
+
+ /**
+ * <p>Provide the User password confirmation.</p>
+ *
+ * @return Returns the confirmationpassword.
+ */
+ public String getPassword2() {
+ return password2;
+ }
+
+ /**
+ * <p>Store a new User password confirmation.</p>
+ *
+ * @param value The confirmation password to set.
+ */
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ // ---- Username property ----
+
+ /**
+ * <p>Field to store User username.</p>
+ * <p/>
+ * <p>The User DAO object password proerty is immutable, so we store it
+ * locally until we are ready to create the object.</p>
+ */
+ private String username = null;
+
+
+ /**
+ * <p>Provide User username.</p>
+ *
+ * @return Returns the User username.
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * <p>Store new User username</p>
+ *
+ * @param value The username to set.
+ */
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ // ---- Database property ----
+
+ /**
+ * <p>Provide reference to UserDatabase, or null if the database is not
+ * available. </p>
+ *
+ * @return a reference to the UserDatabase or null if the database is not
+ * available
+ */
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(Constants.DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText("error.database.missing"));
+ }
+ return (UserDatabase) db;
+ }
+
+ /**
+ * <p>Store a new reference to UserDatabase</p>
+ *
+ * @param database
+ */
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(Constants.DATABASE_KEY, database);
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(Constants.USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(Constants.USER_KEY, user);
+ }
+
+ /**
+ * <p>Obtain User object from database, or return null if the credentials
+ * are not found or invalid.</p>
+ *
+ * @param username User username
+ * @param password User password
+ * @return User object or null if not found
+ * @throws ExpiredPasswordException
+ */
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+ // FIXME: Stupid testing hack to compensate for inadequate DAO layer
+ if (Constants.EXPIRED_PASSWORD_EXCEPTION.equals(username)) {
+ throw new ExpiredPasswordException(Constants.EXPIRED_PASSWORD_EXCEPTION);
+ }
+
+ User user = getDatabase().findUser(username);
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ this.addFieldError(Constants.PASSWORD_MISMATCH_FIELD,
+ getText("error.password.mismatch"));
+ }
+ return user;
+ }
+
+ /**
+ * <p><code>Log</code> instance for this application. </p>
+ */
+ protected Log log = LogFactory.getLog(Constants.PACKAGE);
+
+ /**
+ * <p> Persist the User object, including subscriptions, to the database.
+ * </p>
+ *
+ * @throws java.lang.Exception on database error
+ */
+ public void saveUser() throws Exception {
+ try {
+ getDatabase().save();
+ } catch (Exception e) {
+ String message = Constants.LOG_DATABASE_SAVE_ERROR + getUser()
+ .getUsername();
+ log.error(message, e);
+ throw new Exception(message, e);
+ }
+ }
+
+ public void createInputUser() {
+ User user = new MemoryUser(null, null);
+ setUser(user);
+ }
+
+ /**
+ * <p> Verify input for creating a new user, create the user, and process
+ * the login. </p>
+ *
+ * @return A new User and empty Errors if create succeeds, or null and
+ * Errors if create fails
+ */
+ public User createUser(String username, String password) {
+
+ UserDatabase database = getDatabase();
+ User user;
+
+ try {
+ user = database.findUser(username);
+ }
+
+ catch (ExpiredPasswordException e) {
+ user = getUser(); // Just so that it is not null
+ }
+
+ if (user != null) {
+ this.addFieldError("username", "error.username.unique");
+ return null;
+ }
+
+ return database.createUser(username);
+ }
+
+ // Since user.username is immutable, we have to use some local properties
+
+ /**
+ * <p>Use the current User object to create a new User object, and make
+ * the new User object the authenticated user.</p>
+ * <p/>
+ * <p>The "current" User object is usually a temporary object being used
+ * to capture input.</p>
+ *
+ * @param _username User username
+ * @param _password User password
+ */
+ public void copyUser(String _username, String _password) {
+ User input = getUser();
+ input.setPassword(_password);
+ User user = createUser(_username, _password);
+ if (null != user) {
+ BeanUtils.setValues(user, input, null);
+ setUser(user);
+ }
+ }
+
+ // ---- Subscription property ----
+
+ /**
+ * <p>Obtain the cached Subscription object, if any. </p>
+ *
+ * @return Cached Subscription object or null
+ */
+ public Subscription getSubscription() {
+ return (Subscription) getSession().get(Constants.SUBSCRIPTION_KEY);
+ }
+
+ /**
+ * <p>Store new User Subscription.</p>
+ *
+ * @param subscription
+ */
+ public void setSubscription(Subscription subscription) {
+ getSession().put(Constants.SUBSCRIPTION_KEY, subscription);
+ }
+
+ /**
+ * <p> Obtain User Subscription object for the given host, or return null
+ * if not found. </p>
+ *
+ * <p>It would be possible for this code to throw a NullPointerException,
+ * but the ExceptionHandler in the xwork.xml will catch that for us.</p>
+ *
+ * @return The matching Subscription or null
+ */
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = getUser().findSubscription(host);
+ return subscription;
+ }
+
+ /**
+ * <p>Obtain uSER Subscription for the local Host property.</p>
+ * <p/>
+ * <p>Usually, the host property will be set from the client request,
+ * because it was embedded in a link to the Subcription action.
+ *
+ * @return Subscription or null if not found
+ */
+ public Subscription findSubscription() {
+ return findSubscription(getHost());
+ }
+
+ /**
+ * <p>Provide a "temporary" User Subscription object that can be used to
+ * capture input values.</p>
+ */
+ public void createInputSubscription() {
+ Subscription sub = new MemorySubscription(getUser(), null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+
+ /**
+ * <p>Provide new User Subscription object for the given host, or null if
+ * the host is not unique.</p>
+ *
+ * @param host
+ * @return New User Subscription object or null
+ */
+ public Subscription createSubscription(String host) {
+
+ Subscription sub;
+
+ sub = findSubscription(host);
+
+ if (null != sub) {
+ // FIXME - localization - "error.host.unique")
+ addFieldError(Constants.HOST,"That hostname is already defined");
+ return null;
+ }
+
+ return getUser().createSubscription(host);
+ }
+
+ /**
+ * <p>Create a new Subscription from the current Subscription object,
+ * making the new Subscription the current Subscription. </p>
+ * <p/>
+ * <p>Usually, the "current" Subscription is a temporary object being used
+ * to capture input values.</p>
+ *
+ * @param host
+ */
+ public void copySubscription(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ BeanUtils.setValues(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }
+
+ /**
+ * <p>Delete the current Subscription object from the database.</p>
+ */
+ public void removeSubscription() {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(Constants.SUBSCRIPTION_KEY);
+ }
+
+ /**
+ * <p>Provide MailServer Host for current User Subscription.</p>
+ *
+ * @return MailServer Host for current User Subscription
+ */
+ public String getSubscriptionHost() {
+ Subscription sub = getSubscription();
+ if (null == sub) {
+ return null;
+ }
+ return sub.getHost();
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport.properties b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport.properties
new file mode 100644
index 0000000..df33d47
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport.properties
@@ -0,0 +1,93 @@
+button.cancel=Cancel
+button.confirm=Confirm
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+button.reset=Reset
+button.save=Save
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+error.database.missing=User database is missing, cannot validate logon credentials
+error.fromAddress.format=Invalid format for From Address
+error.fromAddress.required=From Address is required
+error.fullName.required=Full Name is required
+error.host.required=Mail Server is required
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+error.password.mismatch=Invalid username and/or password, please try again
+error.replyToAddress.format=Invalid format for Reply To Address
+struts.messages.invalid.token=Cannot submit this form out of order
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+error.username.required=Username is required
+error.username.unique=That username is already in use - please select another
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.logon=Log on to the MailReader Demonstration Application
+index.registration=Register with the MailReader Demonstration Application
+index.title=MailReader Demonstration Application
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+logon.title=MailReader Demonstration Application - Logon
+mainMenu.heading=Main Menu Options for
+mainMenu.logoff=Log off MailReader Demonstration Application
+mainMenu.registration=Edit your user registration profile
+mainMenu.title=MailReader Demonstration Application - Main Menu
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+fromAddress=From Address
+fullName=Full Name
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+password=Password
+password2=(Repeat) Password
+replyToAddress=Reply To Address
+username=Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+registration.title.create=Register for the MailReader Demonstration Application
+registration.title.edit=Edit Registration for the MailReader Demonstration Application
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport_ja.properties b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport_ja.properties
new file mode 100644
index 0000000..df4f174
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.logon=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+logon.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+mainMenu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+mainMenu.logoff=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+mainMenu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+mainMenu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport_ru.properties b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport_ru.properties
new file mode 100644
index 0000000..b80ecd5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/MailreaderSupport_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.logon=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+logon.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+mainMenu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+mainMenu.logoff=\u0412\u044b\u0439\u0442\u0438
+mainMenu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration-RegistrationSave-validation.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration-RegistrationSave-validation.xml
new file mode 100644
index 0000000..6896407
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration-RegistrationSave-validation.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="errors.range"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.match"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration-validation.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration-validation.xml
new file mode 100644
index 0000000..44d66bc
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration-validation.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="user.fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="user.fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+ <field name="user.replyToAddress">
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration.java
new file mode 100644
index 0000000..e6764ee
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Registration.java
@@ -0,0 +1,91 @@
+package mailreader2;
+
+import org.apache.struts.apps.mailreader.dao.User;
+
+
+/**
+ * <p>Insert or update a User object to the persistent store. </p>
+ */
+public class Registration extends MailreaderSupport {
+
+ /**
+ * <p>Double check that there is not a valid User logon. </p>
+ *
+ * @return True if there is not a valid User logon
+ */
+ private boolean isCreating() {
+ User user = getUser();
+ return (null == user) || (null == user.getDatabase());
+ }
+
+ /**
+ * <p> Retrieve User object to edit or null if User does not exist. </p>
+ *
+ * @return The "Success" result for this mapping
+ * @throws Exception on any error
+ */
+ public String input() throws Exception {
+
+ if (isCreating()) {
+ createInputUser();
+ setTask(Constants.CREATE);
+ } else {
+ setTask(Constants.EDIT);
+ setUsername(getUser().getUsername());
+ setPassword(getUser().getPassword());
+ setPassword2(getUser().getPassword());
+ }
+
+ return INPUT;
+ }
+
+ /**
+ * <p> Insert or update a User object to the persistent store. </p>
+ * <p/>
+ * <p> If a User is not logged in, then a new User is created and
+ * automatically logged in. Otherwise, the existing User is updated. </p>
+ *
+ * @return The "Success" result for this mapping
+ * @throws Exception on any error
+ */
+ public String execute()
+ throws Exception {
+
+ boolean creating = Constants.CREATE.equals(getTask());
+ creating = creating && isCreating(); // trust but verify
+
+ if (creating) {
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText("error.username.unique"));
+ return INPUT;
+ }
+
+ copyUser(getUsername(), getPassword());
+
+ } else {
+
+ // FIXME: Any way to call the RegisrationSave validators from here?
+ String newPassword = getPassword();
+ if (newPassword != null) {
+ String confirmPassword = getPassword2();
+ boolean matches = ((null != confirmPassword)
+ && (confirmPassword.equals(newPassword)));
+ if (matches) {
+ getUser().setPassword(newPassword);
+ } else {
+ addActionError(getText("error.password.match"));
+ return INPUT;
+ }
+ }
+ }
+
+ saveUser();
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Subscription-validation.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Subscription-validation.xml
new file mode 100644
index 0000000..df903c2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Subscription-validation.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="host">
+ <field-validator type="requiredstring">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Subscription.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Subscription.java
new file mode 100644
index 0000000..a3f32ed
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Subscription.java
@@ -0,0 +1,124 @@
+package mailreader2;
+
+import com.opensymphony.xwork2.Preparable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * <p> Provide an Edit method for retrieving an existing subscription, and a
+ * Save method for updating or inserting a subscription. </p>
+ */
+public class Subscription extends MailreaderSupport
+ implements Preparable {
+
+ /**
+ * <p>Field to store list of MailServer types</p>
+ */
+ private Map types = null;
+
+ /**
+ * <p>Provide the list of MailServer types.</p>
+ *
+ * @return List of MailServer types
+ */
+ public Map getTypes() {
+ return types;
+ }
+
+ /**
+ * <p>Setup the MailerServer types and set the local Host property from
+ * the User Subscription (if any). </p>
+ */
+ public void prepare() {
+
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+
+ setHost(getSubscriptionHost());
+ }
+
+ /**
+ * <p>Setup a temporary User Subscription object to capture input
+ * values.</p>
+ *
+ * @return INPUT
+ */
+ public String input() {
+ createInputSubscription();
+ setTask(Constants.CREATE);
+ return INPUT;
+ }
+
+ /**
+ * <p>Load User Subscription for the local Host property.</p>
+ * <p/>
+ * <p>Usually, the Host is being set from the request by a link to an Edit
+ * or Delete task.</p>
+ *
+ * @return INPUT or Error, if Subscription is not found
+ */
+ public String find() {
+
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+
+ if (sub == null) {
+ return ERROR;
+ }
+
+ setSubscription(sub);
+
+ return INPUT;
+
+ }
+
+ /**
+ * <p>Prepare to present a confirmation page before removing
+ * Subscription.</p>
+ *
+ * @return INPUT or Error, if Subscription is not found
+ */
+ public String delete() {
+
+ setTask(Constants.DELETE);
+ return find();
+ }
+
+ /**
+ * <p>Prepare to edit User Subscription.</p>
+ *
+ * @return INPUT or Error, if Subscription is not found
+ */
+ public String edit() {
+
+ setTask(Constants.EDIT);
+ return find();
+ }
+
+ /**
+ * <p> Examine the Task property and DELETE, CREATE, or save the User
+ * Subscription, as appropriate. </p>
+ *
+ * @return SUCCESS
+ * @throws Exception on a database error
+ */
+ public String save() throws Exception {
+
+ if (Constants.DELETE.equals(getTask())) {
+ removeSubscription();
+ }
+
+ if (Constants.CREATE.equals(getTask())) {
+ copySubscription(getHost());
+ }
+
+ if (hasErrors()) return INPUT;
+
+ saveUser();
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/SubscriptionSave-validation.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/SubscriptionSave-validation.xml
new file mode 100644
index 0000000..9f2f6d7
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/SubscriptionSave-validation.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="subscription.username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.type">
+ <field-validator type="requiredstring">
+ <message key="error.type.invalid"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/SubscriptionSave.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/SubscriptionSave.java
new file mode 100644
index 0000000..7d935c6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/SubscriptionSave.java
@@ -0,0 +1,20 @@
+package mailreader2;
+
+/**
+ * <p> Save a subscriptioin, resetting checkbox in prepare.</p>
+ */
+public final class SubscriptionSave extends Subscription {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ getSubscription().setAutoConnect(false);
+ }
+
+ public String execute() throws Exception {
+ return save();
+ }
+
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Welcome.java b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Welcome.java
new file mode 100644
index 0000000..08ec125
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/mailreader2/Welcome.java
@@ -0,0 +1,28 @@
+package mailreader2;
+
+/**
+ * Verify that essential resources are available.
+ */
+public class Welcome extends MailreaderSupport {
+
+ public String execute() {
+
+ // Confirm message resources loaded
+ String message = getText(Constants.ERROR_DATABASE_MISSING);
+ if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
+ addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);
+ }
+
+ // Confirm database loaded
+ if (null==getDatabase()) {
+ addActionError(Constants.ERROR_DATABASE_NOT_LOADED);
+ }
+
+ if (hasErrors()) {
+ return ERROR;
+ }
+ else {
+ return SUCCESS;
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-bang.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-bang.xml
new file mode 100644
index 0000000..ecaef4f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-bang.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <package name="bang" namespace="/" extends="struts-support">
+
+ <action name="Logon" class="mailreader2.Logon">
+ <result name="input">/pages/Logon.jsp</result>
+ <result name="cancel" type="redirect-action">Welcome</result>
+ <result type="redirect-action">MainMenu</result>
+ <result name="expired" type="chain">ChangePassword</result>
+ <exception-mapping
+ exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
+ result="expired"/>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Registration" class="mailreader2.Registration">
+ <result name="input">/pages/Registration.jsp</result>
+ <result type="redirect-action">MainMenu</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="RegistrationSave" class="mailreader2.Registration">
+ <result name="input">/pages/Registration.jsp</result>
+ <result type="redirect-action">MainMenu</result>
+ <interceptor-ref name="guest-submit" />
+ </action>
+
+ <action name="Subscription" class="mailreader2.Subscription">
+ <result name="input">/pages/Subscription.jsp</result>
+ <result type="redirect-action">Registration!input</result>
+ </action>
+
+ <action name="SubscriptionSave" class="mailreader2.SubscriptionSave">
+ <result name="input">/pages/Subscription.jsp</result>
+ <result type="redirect-action">Registration!input</result>
+ <interceptor-ref name="user-submit" />
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-support.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-support.xml
new file mode 100644
index 0000000..b2893d3
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-support.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+
+ <package name="struts-support" namespace="/" extends="struts-default">
+
+ <interceptors>
+
+ <interceptor name="authentication"
+ class="mailreader2.AuthenticationInterceptor"/>
+
+ <interceptor-stack name="user" >
+ <interceptor-ref name="authentication" />
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="user-submit" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="user"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="guest" >
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+
+ <interceptor-stack name="guest-submit" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="guest"/>
+ </interceptor-stack>
+
+ </interceptors>
+
+ <default-interceptor-ref name="user"/>
+
+ <global-results>
+ <result name="error">/pages/Error.jsp</result>
+ <result name="invalid.token">/pages/Error.jsp</result>
+ <result name="login" type="redirect-action">Logon!input</result>
+ </global-results>
+
+ <global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Throwable"/>
+ </global-exception-mappings>
+
+ <action name="Welcome" class="mailreader2.Welcome">
+ <result>/pages/Welcome.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="ChangePassword" class="mailreader2.MailreaderSupport">
+ <result>/pages/ChangePassword.jsp</result>
+ </action>
+
+ <action name="MainMenu" class="mailreader2.MailreaderSupport">
+ <result>/pages/MainMenu.jsp</result>
+ </action>
+
+ <action name="Logoff" class="mailreader2.Logoff">
+ <result type="redirect-action">Welcome</result>
+ </action>
+
+ <action name="Tour">
+ <result>/pages/tour.html</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ </package>
+
+</struts>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-wildcard.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-wildcard.xml
new file mode 100644
index 0000000..b6c7c06
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts-wildcard.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <package name="wildcard" namespace="/" extends="struts-support">
+
+ <action name="Logon!*" class="mailreader2.Logon" method="{1}">
+ <result name="input">/pages/Logon.jsp</result>
+ <result name="cancel" type="redirect-action">Welcome</result>
+ <result type="redirect-action">MainMenu</result>
+ <result name="expired" type="chain">ChangePassword</result>
+ <exception-mapping
+ exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
+ result="expired"/>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="Registration!*" class="mailreader2.Registration" method="{1}">
+ <result name="input">/pages/Registration.jsp</result>
+ <result type="redirect-action">MainMenu</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ <action name="RegistrationSave" class="mailreader2.Registration">
+ <result name="input">/pages/Registration.jsp</result>
+ <result type="redirect-action">MainMenu</result>
+ <interceptor-ref name="guest-submit" />
+ </action>
+
+ <action name="Subscription!*" class="mailreader2.Subscription" method="{1}">
+ <result name="input">/pages/Subscription.jsp</result>
+ <result type="redirect-action">Registration!input</result>
+ </action>
+
+ <action name="SubscriptionSave" class="mailreader2.SubscriptionSave">
+ <result name="input">/pages/Subscription.jsp</result>
+ <result type="redirect-action">Registration!input</result>
+ <interceptor-ref name="user-submit" />
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts.properties b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts.properties
new file mode 100644
index 0000000..d7bcc1b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts.properties
@@ -0,0 +1,3 @@
+struts.devMode = true
+struts.action.extension = do
+struts.enable.DynamicMethodInvocation = false
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts.xml
new file mode 100644
index 0000000..0aea0c8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/java/struts.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+
+ <include file="struts-default.xml"/>
+
+ <include file="struts-support.xml"/>
+
+ <!--
+ <include file="struts-bang.xml"/>
+ -->
+ <include file="struts-wildcard.xml"/>
+
+</struts>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/alternate.properties b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/alternate.properties
new file mode 100644
index 0000000..45f4dd5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/alternate.properties
@@ -0,0 +1,3 @@
+password=Enter your Password here ==>
+struts.logo.path=/struts-power.gif
+struts.logo.alt=Powered by Struts
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/alternate_ja.properties b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/alternate_ja.properties
new file mode 100644
index 0000000..981adc8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/alternate_ja.properties
@@ -0,0 +1 @@
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b==>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/applicationContext.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..b98e1d8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/applicationContext.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans default-autowire="autodetect">
+ <!-- add your spring beans here -->
+</beans>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/database.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/resources/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/META-INF/context.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/WEB-INF/web.xml b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7257132
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath*:applicationContext*.xml</param-value>
+ </context-param>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ mailreader2.ApplicationListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/css/mailreader.css b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/css/mailreader.css
new file mode 100644
index 0000000..bfc7648
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/css/mailreader.css
@@ -0,0 +1,46 @@
+/**
+* Mailreader stylesheet
+*/
+
+body {
+ background-color: #FFFFFF;
+ color: #000000;
+ link: 000066;
+ visited: #660066;
+ active: #33CCCC;
+}
+
+A:hover {
+ color: #FF0000;
+}
+
+h1 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h5 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h6 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+font.hint {
+ font-style: italic;
+ font-size: 80%;
+ font-family: Arial, Helvetica, sans-serif;
+ text-align: left;
+}
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/index.html b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/index.html
new file mode 100644
index 0000000..1b01b3f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.do">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/ChangePassword.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/ChangePassword.jsp
new file mode 100644
index 0000000..667834d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/ChangePassword.jsp
@@ -0,0 +1,25 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="change.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+
+<p>
+ <s:text name="change.message"/>
+</p>
+
+<p>
+ <a href="<s:url action="Logon!input"/>">
+ <s:text name="change.try"/>
+ </a>
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Error.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Error.jsp
new file mode 100644
index 0000000..05ab5e0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Error.jsp
@@ -0,0 +1,40 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Unexpected Error</title>
+</head>
+
+<body>
+<h2>An unexpected error has occured</h2>
+
+<p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+</p>
+
+<hr/>
+
+<h3>Error Message</h3>
+
+<s:actionerror />
+
+<p>
+ <s:property value="%{exception.message}"/>
+</p>
+
+<hr/>
+
+<h3>Technical Details</h3>
+
+<p>
+ <s:property value="%{exceptionStack}"/>
+</p>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Footer.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Footer.jsp
new file mode 100644
index 0000000..2b3b86c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Footer.jsp
@@ -0,0 +1,6 @@
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<hr/>
+
+<p>
+ <a href="<s:url action="Welcome" />"><s:text name="index.title"/></a>
+</p>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Logon.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Logon.jsp
new file mode 100644
index 0000000..4c8ce0b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Logon.jsp
@@ -0,0 +1,30 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.Logon.username.focus()">
+
+<s:actionerror />
+<s:form action="Logon" validate="true">
+ <s:textfield label="%{getText('username')}" name="username"/>
+
+ <s:password label="%{getText('password')}" name="password" showPassword="true"/>
+
+ <s:submit value="%{getText('button.save')}"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Logon!cancel" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="Footer.jsp"/>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/MainMenu.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/MainMenu.jsp
new file mode 100644
index 0000000..8c4c98a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/MainMenu.jsp
@@ -0,0 +1,25 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="mainMenu.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h3><s:text name="mainMenu.heading"/> <s:property
+ value="user.fullName"/></h3>
+<ul>
+ <li><a href="<s:url action="Registration!input" />">
+ <s:text name="mainMenu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url action="Logoff"/>">
+ <s:text name="mainMenu.logoff"/>
+ </a>
+</ul>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Registration.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Registration.jsp
new file mode 100644
index 0000000..af7f6bd
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Registration.jsp
@@ -0,0 +1,126 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title><s:text name="registration.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="registration.title.edit"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.Registration.username.focus()">
+
+<s:actionerror/>
+<s:form action="RegistrationSave" validate="false">
+ <s:token />
+ <s:hidden name="task"/>
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('username')}" name="username"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('username')}" name="username"/>
+ <s:hidden name="username"/>
+ </s:else>
+
+ <s:password label="%{getText('password')}" name="password"/>
+
+ <s:password label="%{getText('password2')}" name="password2"/>
+
+ <s:textfield label="%{getText('fullName')}"
+ name="user.fullName"/>
+
+ <s:textfield label="%{getText('fromAddress')}"
+ name="user.fromAddress"/>
+
+ <s:textfield label="%{getText('replyToAddress')}"
+ name="user.replyToAddress"/>
+
+ <s:if test="task == 'Create'">
+ <s:submit value="%{getText('button.save')}" action="RegistrationSave"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Welcome" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+ </s:if>
+ <s:else>
+ <s:submit value="%{getText('button.save')}" action="Registration"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="MainMenu" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+ </s:else>
+
+</s:form>
+
+<s:if test="task == 'Edit'">
+ <div align="center">
+ <h3><s:text name="heading.subscriptions"/></h3>
+ </div>
+
+ <table border="1" width="100%">
+
+ <tr>
+ <th align="center" width="30%">
+ <s:text name="heading.host"/>
+ </th>
+ <th align="center" width="25%">
+ <s:text name="heading.user"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.type"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.autoConnect"/>
+ </th>
+ <th align="center" width="15%">
+ <s:text name="heading.action"/>
+ </th>
+ </tr>
+
+ <s:iterator value="user.subscriptions">
+ <tr>
+ <td align="left">
+ <s:property value="host"/>
+ </td>
+ <td align="left">
+ <s:property value="username"/>
+ </td>
+ <td align="center">
+ <s:property value="type"/>
+ </td>
+ <td align="center">
+ <s:property value="autoConnect"/>
+ </td>
+ <td align="center">
+
+ <a href="<s:url action="Subscription!delete"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.deleteSubscription"/>
+ </a>
+
+ <a href="<s:url action="Subscription!edit"><s:param name="host" value="host"/></s:url>">
+ <s:text name="registration.editSubscription"/>
+ </a>
+
+ </td>
+ </tr>
+ </s:iterator>
+
+ </table>
+
+ <a href="<s:url action="Subscription!input"/>"><s:text
+ name="registration.addSubscription"/></a>
+
+</s:if>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Subscription.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Subscription.jsp
new file mode 100644
index 0000000..de6d94c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Subscription.jsp
@@ -0,0 +1,68 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title><s:text name="subscription.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="subscription.title.edit"/></title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title><s:text name="subscription.title.delete"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.Subscription.username.focus()">
+
+<s:actionerror/>
+<s:form action="SubscriptionSave" validate="false">
+ <s:token />
+ <s:hidden name="task"/>
+ <s:label label="%{getText('username')}" name="user.username"/>
+
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('mailHostname')}" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('mailHostname')}" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:label label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:label label="%{getText('mailServerType')}"
+ name="subscription.type"/>
+ <s:label label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.confirm')}"/>
+ </s:if>
+ <s:else>
+ <s:textfield label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:textfield label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:select label="%{getText('mailServerType')}"
+ name="subscription.type" list="types"/>
+ <s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.save')}"/>
+ <s:reset value="%{getText('button.reset')}"/>
+ </s:else>
+
+ <s:submit action="Registration!input"
+ value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Welcome.jsp b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..9b307ea
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/Welcome.jsp
@@ -0,0 +1,56 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><s:text name="index.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h3><s:text name="index.heading"/></h3>
+
+<ul>
+ <li><a href="<s:url action="Registration!input"/>"><s:text
+ name="index.registration"/></a></li>
+ <li><a href="<s:url action="Logon!input"/>"><s:text
+ name="index.logon"/></a></li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li>
+ <s:url id="en" action="Welcome">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="ja" action="Welcome">
+ <s:param name="request_locale">ja</s:param>
+ </s:url>
+ <s:a href="%{ja}">Japanese</s:a>
+ </li>
+ <li>
+ <s:url id="ru" action="Welcome">
+ <s:param name="request_locale">ru</s:param>
+ </s:url>
+ <s:a href="%{ru}">Russian</s:a>
+ </li>
+</ul>
+
+<hr/>
+
+<p><s:i18n name="alternate">
+ <img src="<s:text name="struts.logo.path"/>"
+ alt="<s:text name="struts.logo.alt"/>"/>
+</s:i18n></p>
+
+<p><a href="<s:url action="Tour" />"><s:text name="index.tour"/></a></p>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/tour.html b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/tour.html
new file mode 100644
index 0000000..c27e9e8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/pages/tour.html
@@ -0,0 +1,2423 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"/>
+ <link rel="stylesheet" type="text/css" href="../css/mailreader.css"/>
+
+ <title>A Walking Tour of the Struts 2 MailReader Application</title>
+</head>
+
+<body>
+<blockquote>
+<h2>A Walking Tour of the Struts 2 MailReader Application</h2>
+
+<p>
+ <i>
+ This article is meant to introduce a new user to Apache Struts 2 by
+ "walking through" a simple, but functional, application.
+ The article includes code snippets, but for the best result, you might
+ want to install the MailReader application on your own development
+ workstation and follow along.
+ Of course, the full source code to the MailReader is included in the
+ distribution.
+ </i>
+
+</p>
+
+<p>
+ <i>
+ The tour assumes the reader has a basic understanding of the Java
+ language, JavaBeans, web applications, and JavaServer Pages. For
+ background on these technologies, see the
+ <a href="http://struts.apache.org/primer.html">
+ Key Technologies Primer</a>.
+ </i>
+</p>
+
+<hr/>
+
+<p>Logging In</p>
+
+<ul>
+ <li>
+ <a href="#Welcome">Welcome</a>
+
+ <ul>
+ <li><a href="#web.xml">web.xml and resources.properties</a></li>
+
+ <li><a href="#Welcome.do">Welcome.do</a></li>
+
+ <li><a href="#Welcome.java">Welcome Action</a></li>
+
+ <li><a href="#global-results">Global Results</a></li>
+
+ <li><a href="#ApplicationListener.java">ApplicationListener.java</a></li>
+
+ <li><a href="#resources.properties">Message Resources</a></li>
+
+ <li><a href="#Welcome.jsp">Welcome Page</a></li>
+
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Logon">Logon</a>
+ <ul>
+
+ <li><a href="#Logon.jsp">Logon Page</a></li>
+
+ <li><a href="#Logon-validation.xml">Logon-validation.xml</a></li>
+
+ <li><a href="#Logon.java">Logon.java</a></li>
+
+ <li><a href="#MailreaderSupport.java">MailreaderSupport.java</a></li>
+
+ <li><a href="#Logon.xml">Logon Configuration</a></li>
+
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#MainMenu">MainMenu</a>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Registration.jsp">Registration page</a>
+ <ul>
+ <li><a href="#iterator">iterator</a></li>
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Subscription">Subscription</a>
+
+ <ul>
+ <li><a href="#SubscriptionAction.java">Subscription.java</a>
+ </li>
+ </ul>
+ </li>
+</ul>
+<hr/>
+
+<p>
+ The premise of the MailReader is that it is the first iteration of a
+ portal application.
+ This version allows users to register and maintain a set of
+ accounts with various mail servers.
+ If completed, the application would let users read mail from their
+ accounts.
+</p>
+
+<p>
+ The MailReader application demonstrates registering with an application,
+ logging into an application, maintaining a master record, and maintaining
+ child records.
+ This article overviews the constructs needed to do these things,
+ including the server pages, Java classes, and configuration elements.
+</p>
+
+<p>
+ For more about the MailReader, including alternate implementations and a
+ set of formal Use Cases,
+ please visit the <a href="http://www.StrutsUniversity.org/MailReader">
+ Struts University MailReader site</a>.
+</p>
+
+<hr/>
+<blockquote>
+ <p><font class="hint">
+ <strong>JAAS</strong> -
+ Note that for compatibility and ease of deployment, the MailReader
+ uses "application-based" authorization.
+ However, use of the standard Java Authentication and Authorization
+ Service (JAAS) is recommended for most applications.
+ (See the <a
+ href="http://struts.apache.org/primer.html">
+ Key Technologies Primer</a> for more about
+ authentication technologies.)
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The tour starts with how the initial welcome page is displayed, and
+ then steps through logging into the application and editing a subscription.
+ Please note that this not a quick peek at a "Hello World" application.
+ The tour is a rich trek into a realistic, best practices application.
+ You may need to adjust your chair and get a fresh cup of coffee.
+ Printed, the article is 29 pages long (US).
+</p>
+
+<h3><a name="Welcome" id="Welcome">Welcome Page</a></h3>
+
+<p>
+ A web application, like any other web site, can specify a list of welcome pages.
+ When you open a web application without specifying a particular page, a
+ default "welcome page" is served as the response.
+</p>
+
+<h4><a name="web.xml" id="web.xml">web.xml</a></h4>
+
+<p>
+ When a web application loads,
+ the container reads and parses the "Web Application Deployment
+ Descriptor", or "web.xml" file.
+ The framework plugs into a web application via a servlet filter.
+ Like any filter, the "struts2" filter is deployed via the "web.xml".
+</p>
+
+<hr/>
+<h5>web.xml - The Web Application Deployment Descriptor</h5>
+<pre><code><?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 MailReader</display-name>
+
+ <strong><filter>
+ <filter-name>struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter></strong>
+
+ <filter-mapping>
+ <filter-name><strong>struts2</strong></filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <!-- Application Listener for MailReader database -->
+ <listener>
+ <listener-class>
+ mailreader2.ApplicationListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ </web-app></code></pre>
+<hr/>
+
+<p>
+ Among other things,
+ the web.xml specifies the "Welcome File List" for an application.
+ When a web address refers to a directory rather than an individual file,
+ the container consults the Welcome File List for the name of a page to
+ open by default.
+</p>
+
+<p>
+ However, most Struts applications do not refer to physical pages,
+ but to "virtual resources" called <i>actions</i>.
+ Actions specify code that we want to be run before a page
+ or other resource renders the response.
+ An accepted practice is to never link directly to server pages,
+ but only to logical action mappings.
+ By linking to actions, developers can often "rewire" an application
+ without editing the server pages.
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Link actions not pages."</font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The actions are listed in one or more XML configuration files,
+ the default configuration file being named "struts.xml".
+ When the application loads, the struts.xml, and any other files
+ it includes, are parsed, and the framework creates a set of
+ configuration objects.
+ Among other things, the configuration maps a request for a certain
+ page to a certain action mapping.
+</p>
+
+<p>
+ Sites can list zero or more "Welcome" pages in the web.xml.
+ Unless you are using Java 1.5, actions cannot be specified as a Welcome
+ page.
+ So, in the case of a Welcome page,
+ how do we follow the best practice of navigating through actions
+ rather than pages?
+</p>
+
+<p>
+ One solution is to use a page to "bootstrap" one of our actions.
+ We can register the usual "index.html" as the Welcome page and have it
+ redirect to a "Welcome" action.
+</p>
+
+<hr/>
+<h5>MailReader's index.html</h5>
+<pre><code><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;<strong>URL=Welcome.do</strong>">
+ </head>
+ <body>
+ <p>Loading ...</p>
+</body></html></code></pre>
+<hr/>
+
+<p>
+ As an alternative,
+ we could also have used a JSP page that issued the redirect with a Struts tag,
+ but a plain HTML solution works as well.
+</p>
+
+<h4><a name="Welcome.do" id="Welcome.do">Welcome.do</a></h4>
+
+<p>
+ When the client requests "Welcome.do", the request is passed to the "struts2" FilterDispatcher
+ (that we registered in the web.xml file).
+ The FilterDispatcher retrieves the appropriate action mapping from the
+ configuration.
+ If we just wanted to forward to the Welcome page, we could use a simple
+ configuration element.
+</p>
+<hr/>
+<h5>A simple "forward thru" action element</h5>
+<pre><code><action name="<strong>Welcome</strong>">
+ <result><strong>/pages/Welcome.jsp</strong></result>
+</action></code></pre>
+<hr/>
+
+<p>
+ If a client asks for the Welcome action ("Welcome.do), the "/page/Welcome.jsp"
+ page would be returned in response.
+ The client does not know, or need to know, that the physical resource is located at
+ "/pages/Welcome.jsp".
+ All the client knows is that it requested the resource "Welcome.do".
+</p>
+
+<p>
+ But if we peek at the configuration file for the MailReader,
+ we find a slightly more complicated XML element for the Welcome action.
+</p>
+
+<hr/>
+<h5>The Welcome action element</h5>
+<pre><code><action name="Welcome" <b>class="mailreader2.Welcome"</b>>
+ <result>/pages/Welcome.jsp</result>
+ <strong><interceptor-ref name="guest"/></strong>
+ </action></code></pre>
+<hr/>
+
+<p>
+ Here, the <strong>Welcome</strong> Java class executes whenever
+ someone asks for the Welcome action.
+ As it completes, the Action class can select which "result" is displayed.
+ The default result name is "success".
+ Another available result, defined at a global scope, is "error".
+</p>
+
+<hr/>
+<h5>Key concept:</h5>
+<blockquote>
+ <p>
+ The Action class doesn't need to know what result type is needed
+ for "success" or "error".
+ The Action can just return the logical name for a result,
+ without knowing how the result is implemented.
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ The net effect is that all of the result details,
+ including the paths to server pages,
+ all can be declared <em>once</em> in the configuration.
+ Tightly coupled implementation details are not scattered all over
+ the application.
+</p>
+
+<hr/>
+<h5>Key concept:</h5>
+<blockquote>
+ <p>
+ The Struts configuration lets us separate concerns and "say it once".
+ The configuration helps us "normalize" an application,
+ in much the same way we normalize a database schema.
+ </p>
+</blockquote>
+<hr/>
+
+
+<p>
+ OK ... but why would a Welcome Action want to choose between "success" and
+ "error"?
+</p>
+
+<h4><a name="Welcome.java" id="Welcome.java">Welcome Action</a></h4>
+
+<p>
+ The MailReader application retains a list of users along with their email
+ accounts.
+ The application stores this information in a database.
+ If the application can't connect to the database, the application can't do
+ its job.
+ So before displaying the Welcome <strong>page</strong>, the Welcome
+ <strong>class</strong> checks to see if the database is available.
+</p>
+
+<p>
+ The MailReader is also an internationalized application.
+ So, the Welcome Action class checks to see if the message resources are
+ available too.
+ If both resources are available, the class passes back the "success" token.
+ Otherwise, the class passes back the "error" token,
+ so that the appropriate messages can be displayed.
+</p>
+
+<hr/>
+<h5>The Welcome Action class</h5>
+<pre><code>package mailreader2;
+public class Welcome extends MailreaderSupport {
+
+ public String execute() {
+
+ // Confirm message resources loaded
+ String message = getText(Constants.ERROR_DATABASE_MISSING);
+ if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
+ <strong>addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);</strong>
+ }
+
+ // Confirm database loaded
+ if (null==getDatabase()) {
+ <strong>addActionError(Constants.ERROR_DATABASE_NOT_LOADED);</strong>
+ }
+
+ if (hasErrors()) {
+ <strong>return ERROR;</strong>
+ }
+ else {
+ <strong>return SUCCESS;</strong>
+ }
+ }
+}</code></pre>
+<hr/>
+
+<p>
+ Several common result names are predefined,
+ including ERROR, SUCCESS, LOGIN, NONE, and INPUT,
+ so that these tokens can be used consistently across Struts 2 applications.
+</p>
+
+
+<h4><a name="global-results" id="global-results">Global Results</a></h4>
+
+<p>
+ As mentioned, "error" is defined in a global scope.
+ Other actions may have trouble connecting to the database later,
+ or other unexpected errors may occur.
+ The MailReader defines the "error" result as a Global Result,
+ so that any action can use it.
+</p>
+
+<hr/>
+<h5>MailReader's global-result element</h5>
+<pre><code> <global-results>
+ <result name=<strong>"error"</strong>><strong>/pages/Error.jsp</strong></result>
+ <result name="invalid.token">/pages/Error.jsp</result>
+ <result name="login" type="redirect-action">Logon!input</result>
+</global-results></code></pre>
+<hr/>
+
+<p>
+ Of course, if an individual action mapping defines its own "error" result type,
+ the local result would be used instead.
+</p>
+
+<h4><a name="ApplicationListener.java" id="ApplicationListener.java">ApplicationListener.java</a>
+</h4>
+
+<p>
+ The database is exposed as an object stored in application scope.
+ The database object is based on an interface.
+ Different implementations of the database could be loaded without changing
+ the rest of the application.
+ But how is the database object loaded in the first place?
+</p>
+
+<p>
+ The database is created by a custom Listener that we configured in the "web.xml".
+</p>
+
+<hr/>
+<h5>mailreader2.ApplicationListener</h5>
+<pre><code> <listener>
+ <listener-class>
+ <strong>mailreader2.ApplicationListener</strong>
+ </listener-class>
+</listener></code></pre>
+<hr/>
+
+<p>
+ By default, our ApplicationListener loads a <strong>MemoryDatabase</strong>
+ implementation of the UserDatabase.
+ MemoryDatabase stores the database content as a XML document,
+ which is parsed and loaded as a set of nested hashtables.
+ The outer table is the list of user objects, each of which has its own
+ inner hashtable of subscriptions.
+ When you register, a user object is stored in this hashtable.
+ When you login, the user object is stored within the session context.
+</p>
+
+<p>
+ The database comes seeded with a sample user.
+ If you check the "database.xml" file under "/src/main",
+ you'll see the sample user described in XML.
+</p>
+
+<hr/>
+<h5>The "seed" user element from the MailReader database.xml</h5>
+<pre><code><user username="<strong>user</strong>" fromAddress="John.User@somewhere.com"
+ fullName="<strong>John Q. User</strong>" password="<strong>pass</strong>">
+ <subscription host="<strong>mail.hotmail.com"</strong> autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="<strong>mail.yahoo.com</strong>" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+</user></code></pre>
+<hr/>
+
+<p>
+ The "seed" user element creates a registration record for "John Q. User",
+ with the subscription detail for his hotmail and yahoo accounts.
+</p>
+
+<h4><a name="resources.properties" id="resources.properties">Message Resources</a>
+</h4>
+
+<p>
+ As mentioned, MailReader is an internationalized application.
+ The message resources for the application are loaded through a reference in the
+ "struts.properties" file.
+ Like the database contents, the "struts.properties" file is kept under
+ "/src/main/" in the source tree.
+</p>
+
+<hr/>
+<h5>struts.properties</h5>
+<pre><code>struts.custom.i18n.resources = <strong>resources</strong>
+struts.action.extension = <strong>do</strong></code></pre>
+<hr/>
+
+<p>
+ When we specify "resources" in the properties file,
+ we are telling the framework to scan the classpath
+ for a Resource Bundle named "resources.properties".
+ The bundle might be embedded in a JAR, or found in the "WEB-INF/classes"
+ folder, or anywhere else on the runtime classpath.
+ In the MailReader, we keep the <strong>original</strong> bundle in the
+ source tree under "src/main/". When the application is built, the
+ properties files are <strong>copied</strong> to "WEB-INF/classes", so
+ that they are on the Java classpath.
+</p>
+
+<hr/>
+<h5>Message Resource entries used by the Welcome page</h5>
+<pre><code><strong>index.heading=</strong>MailReader Application Options
+<strong>index.logon=</strong>Log on to the MailReader Application
+<strong>index.registration=</strong>Register with the MailReader Application
+<strong>index.title=</strong>MailReader Demonstration Application
+<strong>index.tour=</strong>A Walking Tour of the MailReader Demonstration Application</code></pre>
+<hr/>
+
+<p>
+ If you change a message in the resource, and then rebuild and reload the
+ application, the change will appear throughout the application.
+ If you provide message resources for additional locales, you can
+ localize your application.
+ The MailReader provides resources for English, Russian, and Japanese.
+</p>
+
+<h4><a name="Welcome.jsp" id="Welcome.jsp">Welcome Page</a></h4>
+
+<p>
+ After confirming that the necessary resources exist, the Welcome action
+ forwards to the Welcome page.
+</p>
+<hr/>
+<h5>Welcome.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+<strong><%@ taglib prefix="s" uri="http://struts.apache.org/tags" %></strong>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><strong><s:text name="index.title"/></strong></title>
+ <link href="<strong><s:url value="/css/mailreader.css"/></strong>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+
+ <body>
+ <h3><s:text name="index.heading"/></h3>
+
+ <ul>
+ <li><a href="<s:url action="Registration!input"/>"><s:text
+ name="index.registration"/></a></li>
+ <li><a href="<s:url action="Logon!input"/>"><s:text
+ name="index.logon"/></a></li>
+ </ul>
+
+ <h3>Language Options</h3>
+ <ul>
+ <li><a href="<s:url action="Welcome?request_locale=en"/>">English</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ja"/>">Japanese</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ru"/>">Russian</a></li>
+ </ul>
+
+ <hr />
+
+ <p><strong><s:i18n name="alternate"></strong>
+ <img src="<s:text name="struts.logo.path"/>"
+ alt="<s:text name="struts.logo.alt"/>"/>
+ <strong></s:i18n></strong></p>
+
+ <p><a href="<s:url action="Tour" />"><s:text name="index.tour"/></a></p>
+
+ </body>
+</html></code></pre>
+<hr/>
+
+<p>
+ At the top of the Welcome page, there are several directives that load the
+ Struts 2 tag libraries.
+ These are just the usual red tape that goes with any JSP file.
+ The rest of the page utilizes three Struts JSP tags:
+ "text", "url", and "i18n".
+</p>
+
+<p>
+ (We use the tag prefix "s:" in the Struts 2 MailReader application,
+ but you can use whatever prefix you like in your applications.)
+</p>
+
+<p>
+ The <strong>text</strong> tag inserts a message from an
+ application's default resource bundle.
+ If the framework's locale setting is changed for a user,
+ the text tag will render messages from the new locale's resource
+ bundle instead.
+</p>
+
+<p>
+ The <strong>url</strong> tag can render a reference to an
+ action or any other web resource,
+ applying "URL encoding" to the hyperlinks as needed.
+ Java's URL encoding feature lets your application maintain client state
+ without requiring cookies.
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p><font class="hint">
+ <strong>Cookies</strong> -
+ If you turn cookies off in your browser, and then reload your browser
+ and this page,
+ you will see the links with the Java session id information attached.
+ (If you are using Internet Explorer and try this,
+ be sure you reset cookies for the appropriate security zone,
+ and that you disallow "per-session" cookies.)
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The <strong>i18n</strong> tag provides access to multiple resource bundles.
+ The MailReader application uses a second set of message resources for
+ non-text elements.
+ When these are needed, we use the "i18n" tag to specify a different bundle.
+</p>
+
+<p>
+ The <strong>alternate</strong> bundle is stored next to the default bundle,
+ so that it ends up under "classes", which is on the application's class path.
+</p>
+
+<p>
+ In the span of a single request for the Welcome page, the framework has done
+ quite a bit already:
+</p>
+
+<ul>
+ <li>
+ Confirmed that required resources were loaded during initialization.
+ </li>
+
+ <li>
+ Written all the page headings and labels from internationalized
+ message resources.
+ </li>
+
+ <li>
+ Automatically URL-encoded paths as needed.
+ </li>
+</ul>
+
+<p>
+ When rendered, the Welcome page lists two menu options:
+ one to register with the application and one to log on (if you have
+ already registered).
+ Let's follow the Logon link first.
+</p>
+
+<h3><a name="Logon" id="Logon">Logon</a></h3>
+
+<p>
+ If you choose the Logon link, and all goes well, the Logon action forwards
+ control to the Logon page.
+</p>
+
+<h4><a name="Logon.jsp" id="Logon.jsp">Logon Page</a></h4>
+
+<p>
+ The Logon page displays a form that accepts a username and password.
+ You can use the default username and password to logon
+ (<strong>user</strong> and <strong>pass</strong>), if
+ you like. Try omitting or misspelling the username and password in
+ various combinations to see how the application reacts.
+ Note that both the username and password are case sensitive.
+</p>
+
+<hr/>
+<h5>Login.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+ <body onLoad="self.focus();document.Logon.username.focus()">
+ <strong><s:actionerror/></strong>
+ <strong><s:form method="POST" validate="true"></strong>
+ <strong><s:textfield label="%{getText('username')}" name="username"/></strong>
+ <strong><s:password label="%{getText('password')}" name="password"/></strong>
+ <strong><s:submit value="%{getText('button.save')}"/></strong>
+ <strong><s:reset value="%{getText('button.reset')}"/></strong>
+ <s:submit <strong>action="Logon!cancel" onclick="form.onsubmit=null"</strong>
+ value="%{getText('button.cancel')}"/>
+ </s:form>
+ <jsp:include page="Footer.jsp"/>
+ </body>
+</html></code></pre>
+<hr/>
+
+<p>
+ We already saw some of the tags used by the Logon page on the Welcome page.
+ Let's focus on the new tags.
+</p>
+
+<p>
+ The first new tag on the Logon page is <strong>actionerrors</strong>.
+ Most of the possible validation errors are related to a single field.
+ If you don't enter a username,
+ the framework can place an error message near the tag prompting you to
+ enter a username.
+ But some messages are not related to a single field.
+ For example, the database might be down.
+ If the action returns an "Action Error", as opposed to a "Field Error",
+ the messages are rendered in place of the "actionerror" tag.
+ The text for the validation errors, whether they are Action Errors or
+ Field Errors, can be specified in the resource bundle,
+ making the messages easy to manage and localize.
+</p>
+
+<p>
+ The second new tag is <strong>form</strong>.
+ This tag renders a HTML form tag.
+ By default, the form will submit back to whatever action invoked the page.
+ The "validate=true" setting enables client-side validation,
+ so that the form can be validated with JavaScript before being sent
+ back to the server.
+ The framework will still validate the form again, just to be sure, but the
+ client-side validation can save a few round-trips to the server.
+ You can use the method attribute to designate "GET" or "POST",
+ just like the HTML form tag.
+</p>
+
+<p>
+ Within the form tag,
+ we see four more new tags: "textfield", "password", "submit",
+ and "reset". We also see a second usage of "submit" that utilizes an
+ "action" attribute.
+</p>
+
+<p>
+ When we place a control on a form, we usually need to code a set of
+ HTML tags to do everything we want to do.
+ Most often, we do not just want a plain "input type=text" tag.
+ We want the input field to have a label too, and maybe even
+ a tooltip. And, of course, a place to print a message
+ should invalid data be entered.
+</p>
+
+<p>
+ The UI Tags support templates and themes so that a set of HTML tags can be
+ rendered from a single UI Tag. For example, the single tag
+</p>
+
+<pre><code>
+ <s:<strong>textfield</strong> label="%{getText('username')}" name="username"/>
+</code></pre>
+
+<p>
+ generates a wad of HTML markup.
+</p>
+
+<hr/>
+<pre><code><tr>
+ <td class="tdLabel">
+ <label for="Logon_username" class="label">Username:</label>
+ </td>
+ <td>
+ <input type="text" name="username" value="" id="Logon_username"/>
+ </td>
+</tr></code></pre>
+<hr/>
+
+<p>
+ If for some reason you don't like the markup generated by a UI Tag,
+ it's each to change.
+ Each tag is driven by a template that can be updated on a tag-by-tag basis.
+ For example,
+ here is the default template that generates the markup for the ActionErrors tag:
+</p>
+
+<hr/>
+<pre><code><#if (actionErrors?exists && actionErrors?size > 0)>
+ <ul>
+ <#list actionErrors as error>
+ <li><span class="errorMessage">${error}</span></li>
+ </#list>
+ </ul>
+</#if></code></pre>
+<hr/>
+
+<p>
+ If you wanted ActionErrors displayed in a table instead of a list,
+ you could edit a copy of this file, save it as a file named "actionerror.ftl",
+ and place this one file somewhere on your classpath.
+</p>
+
+<hr/>
+<pre><code><#if (actionErrors?exists && actionErrors?size > 0)>
+ <strong><table></strong>
+ <#list actionErrors as error>
+ <strong><tr><td></strong><span class="errorMessage">${error}</span><strong></td></tr></strong>
+ </#list>
+ <strong></table></strong>
+</#if></code></pre>
+<hr/>
+
+<p>
+ Under the covers, the framework uses
+ <a href="http://freemarker.sourceforge.net/">Freemarker</a>
+ for its standard templating language.
+ FreeMarker is similar to
+ <a href="http://jakarta.apache.org/velocity/">Velocity</a>,
+ but it offers better error reporting and some additional features.
+ If you prefer, Velocity and JSP templates can also be used to create your own UI Tags.
+</p>
+
+<p>
+ The <strong>password</strong> tag renders a "input type=password"
+ tag, along with the usual template/theme markup.
+ By default, the password tag will not retain input if the submit fails.
+ If the username is wrong,
+ the client will have to enter the password again too.
+ (If you did want to retain the password when validation fails,
+ you can set the tag's "showPassword" property to true.)
+</p>
+
+<p>
+ Unsurprisingly, the <strong>submit</strong> and <strong>reset</strong> tags
+ render buttons of the corresponding types.
+</p>
+
+<p>
+ The second submit button is more interesting.
+</p>
+
+<pre><code> <s:submit <strong>action="Logon!cancel" onclick="form.onsubmit=null"</strong>
+ value="%{getText('button.cancel')}"/>
+</code></pre>
+
+<p>
+ Here we are creating the Cancel button for the form.
+ The button's attribute <em>action="Logon<strong>!</strong>cancel"</em>
+ tells the framework to submit to the Logon's "cancel" method
+ instead of the usual "execute" method.
+ The <em>onclick="form.onsubmit=null"</em> script defeats client-side validation.
+ On the server side, "cancel" is on a special list of methods that bypass validation,
+ so the request will go directly to the Action's <strong>cancel</strong> method.
+ (Other special aliases on the bypass list include "input" and "back".)
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p><font class="hint">
+ The UI tags have options and capabilities beyond what we have shown here.
+ For more see, the <a href="http://confluence.twdata.org/display/WW/Tags">UI Tag documentation.</a>
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ OK, but how do the tags know that both of these fields are required?
+ How do they know what message to display when the fields are empty?
+</p>
+
+<p>
+ For the answers, we need to look at another flavor of configuration file:
+ the "validation" file.
+</p>
+
+<h4><a name="Logon-validation.xml" id="Logon-validation.xml">Logon-validation.xml</a>
+</h4>
+
+<p>
+ While it is not hard to code data-entry validation into an Action class,
+ the framework provides an even easier way to validate input.
+</p>
+
+<p>
+ The validation framework is configured through another XML document, the <strong>
+ Logon-validation.xml</strong>.
+</p>
+
+<hr/>
+<h5>Validation file for Logon Action</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+ <field name="<strong>username</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="<strong>error.username.required</strong>"/>
+ </field-validator>
+ </field>
+ <field name="<strong>password</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="<strong>error.password.required</strong>"/>
+ </field-validator>
+ </field>
+</validators>
+</code></pre>
+<hr/>
+
+<p>
+ You may note that the DTD refers to "XWork".
+ <a href="http://www.opensymphony.com/xwork/">
+ Open Symphony XWork
+ </a> is a generic command-pattern framework that can be used outside of a
+ web environment. In practice, Struts 2 is a web-based extension of the
+ XWork framework.
+</p>
+
+<p>
+ The field elements correspond to the ActionForm properties.
+ The <strong>username</strong> and <strong>password</strong> field elements
+ say that each field depends on the "requiredstring" validator.
+ If the username is blank or absent, validation will fail and an error
+ message is generated.
+ The messages would be based on the "error.username.required" or
+ "error.password.required" message templates, from the resource bundle.
+</p>
+
+<!--
+<p>
+ The <strong>password</strong> field (or property) is also required.
+ In addition, it must also pass the "maxlength" and "minlength"
+ validations.
+ Here, the minimum length is three characters and the maximum length is
+ sixteen.
+ If the length of the password doesn't meet these criteria, a corresponding
+ error message is generated.
+ Of course, the messages are generated from the MessageResource bundles and
+ are easy to localize.
+</p>
+-->
+
+<h4><a name="Logon.java" id="Logon.java">Logon Action</a></h4>
+
+<p>
+ If validation passes, the framework invokes the "execute" method of the Logon Action.
+ The actual Logon Action is brief, since most of the functionality derives
+ from the base class, <strong>MailreaderSupport</strong>.
+</p>
+
+<hr/>
+<h5>Logon.java</h5>
+<pre><code>package mailreader2;
+import org.apache.struts.apps.mailreader.dao.User;
+public final class <strong>Logon</strong> extends MailreaderSupport {
+public String <strong>execute()</strong> throws ExpiredPasswordException {
+ User user = <strong>findUser(getUsername(), getPassword());</strong>
+ if (user != null) {
+ <strong>setUser(user);</strong>
+ }
+ if (<strong>hasErrors()</strong>) {
+ return INPUT;
+ }
+ return SUCCESS;
+ }
+}</code></pre>
+<hr/>
+
+<p>
+ Logon lays out what we do to authenticate a user.
+ We try to find the user using the credentials provided.
+ If the user is found, we cache a reference.
+ If the user is not found, we return "input" so the client can try again.
+ Otherwise, we return "success", so that the client can access the rest of the application.
+</p>
+
+<h4><a name="MailreaderSupport.java" id="MailreaderSupport.java">MailreaderSupport.java</a></h4>
+
+<p>
+ Let's look at the relevant properties and methods from MailreaderSupport
+ and another base class, <strong>ActionSupport</strong>, namely
+ "getUsername", "getPassword", "findUser", "setUser", and "hasErrors".
+</p>
+
+<p>
+ The framework lets you define
+ <a href="http://struts.apache.org/primer.html#javabeans">JavaBean properties</a>
+ directly on the Action.
+ Any JavaBean property can be used, including rich objects.
+ When a request comes in,
+ any public properties on the Action class are matched with the request parameters.
+ When the names match, the request parameter value is set to the JavaBean property.
+ The framework will make its best effort to convert the data,
+ and, if necessary, it will report any conversion errors.
+</p>
+
+<p>
+ The <strong>Username</strong> and <strong>Password</strong> properties are nothing fancy,
+ just standard JavaBean properties.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.getUsername() and getPassword()</h5>
+<pre><code>private String username = null;
+public String <strong>getUsername()</strong> {
+ return this.username;
+}
+public void setUsername(String username) {
+ this.username = username;
+}
+
+private String password = null;
+public String <strong>getPassword()</strong> {
+ return this.password;
+}
+public void setPassword(String password) {
+ this.password = password;
+}</code></pre>
+<hr/>
+
+<p>
+ We use these properties to capture the client's credentials,
+ and pass them to the more interesting <strong>findUser</strong> method.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.findUser</h5>
+<pre><code>public User <strong>findUser</strong>(String username, String password)
+ throws <strong>ExpiredPasswordException</strong> {
+ User user = <strong>getDatabase().findUser(username)</strong>;
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ this.<strong>addFieldError</strong>("password", getText("error.password.mismatch"));
+ }
+ return user;
+}</code></pre>
+<hr/>
+
+<p>
+ The "findUser" method dips into the MailReader Data Access Object layer,
+ which is represented by the <strong>Database</strong> property.
+ The code for the DAO layer is maintained as a separate component.
+ The MailReader application imports the DAO JAR,
+ but it is not responsible for maintaining any of the DAO source.
+ Keeping the data access layer at "arms-length" is a very good habit.
+ It encourages a style of development where the data access layer
+ can be tested and developed independently of a specific end-user application.
+ In fact, there are several renditions of the MailReader application,
+ all which share the same MailReader DAO JAR!
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Strongly separate data access and business logic from the rest of the application."</font>
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ When "findUser" returns,
+ the Logon Action looks to see if a valid (non-null) User object is returned.
+ A valid User is passed to the <strong>User property</strong>.
+ Although it is still a JavaBean property,
+ the User property is not implemented in quite the same way as Username and Password.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.setUser</h5>
+<pre><code>public User getUser() {
+ return (User) <strong>getSession().get(Constants.USER_KEY)</strong>;
+}
+public void setUser(User user) {
+ getSession().put(Constants.USER_KEY, user);
+}</code></pre>
+<hr/>
+
+<p>
+ Instead of using a field to store the property value,
+ "setUser" passes it to a <strong>Session</strong> property.
+</p>
+
+<hr />
+<h5>MailreaderSupport.getSession() and setSession()</h5>
+<pre><code>private Map session;
+public Map <strong>getSession()</strong> {
+ return session;
+
+public void <strong>setSession(Map value)</strong> {
+ session = value;
+}</code></pre>
+<hr />
+
+<p>
+ To look at the MailreaderSupport class, you would think the Session property is a plain-old Map.
+ In fact, the Session property is an adapter that is backed by the servlet session object at runtime.
+ The MailreaderSupport class doesn't need to know that though.
+ It can treat Session like any other Map.
+ We can also test the MailreaderSupport class by passing it some other implementation of Map,
+ running the test,
+ and then looking to see what changes MailreaderSupport made to our "mock" Session object.
+</p>
+
+<p>
+ But, when MailreaderSupport is running inside a web application,
+ how does it acquire a reference to the servlet session?
+</p>
+
+<p>
+ Good question. If you were to look at just the MailreaderSupport class,
+ you would not see a single line of code that sets the session property.
+ But, yet, when we run the class, the session property is not null.
+ Hmmm.
+</p>
+
+<p>
+ The magic that provides the Session property a runtime value is called "dependency injection".
+ The MailreaderSupport class implements a interface called <strong>SessionAware</strong>.
+ SessionAware is bundled with the framework, and it defines a setter for the Session property.
+</p>
+
+<p>
+ <code>public void <strong>setSession</strong>(Map session);</code>
+</p>
+
+<p>
+ Also bundled with the framework is an object called the <strong>ServletConfigInterceptor</strong>.
+ If the ServletConfigInterceptor sees that an Action implements the SessionAware interface,
+ it automatically set the session property.
+</p>
+
+<pre><code>if (action instanceof <code>SessionAware</code>) {
+ ((SessionAware) action).<code>setSession</code>(context.getSession());
+}</code></pre>
+
+<p>
+ The framework uses these "Interceptor" classes to create a <strong>front controller</strong>
+ for each action an application defines.
+ Each Interceptor can peek at the request before an Action class is invoked,
+ and then again after the Action class is invoked.
+ (If you have worked with Servlet
+ <a href="http://struts.apache.org/primer.html#filters">Filters</a>,
+ you will recognize this pattern.
+ But, unlike Filters, Interceptors are not tied to HTTP.
+ Interceptors can be tested and developed outside of a web application.)
+</p>
+
+<p>
+ You can use the same set of Interceptors for all your actions,
+ or define a special set of Interceptors for any given action,
+ or define different sets of Interceptors to use with different types of actions.
+ The framework comes with a default set of Interceptors,
+ that it will use when another set is not specified,
+ but you can designate your own default Interceptor set (or "stack")
+ in the struts.xml configuration file.
+</p>
+
+<p>
+ Many Interceptors provide a utility or helper functions, like setting the session property.
+ Others, like the <strong>ValidationInterceptor</strong>, can change the workflow of an action.
+ Interceptors are key feature of the framework,
+ and we will see a few more on the tour.
+</p>
+
+<p>
+ If a valid User is not found, or the password doesn't match,
+ the "findUser" method invokes the <strong>addFieldError</strong> method to note the problem.
+ When "findUser" returns, the Logon Action checks for errors,
+ and then it returns either INPUT or SUCCESS.
+</p>
+
+<p>
+ The "addFieldError" method is provided by the ActionSupport class,
+ which is bundled with the framework.
+ The constants for INPUT and SUCCESS are also provided by ActionSupport.
+ While the ActionSupport class provides many useful utilities,
+ you are not required to use it as a base class.
+ Any Java class can be used as an Action, if you like.
+</p>
+
+<p>
+ It is a good practice to provide a base class with utilities
+ that can be shared by an application's Action classes.
+ The framework does this with ActionSupport,
+ and the MailReader application does the same with the MailreaderSupport class.
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Use a base class to define common functionality."</font></p>
+</blockquote>
+<hr/>
+
+<p>
+ But, what happens if Logon returns INPUT instead of SUCCESS.
+ How does the framework know what to do next?
+</p>
+
+<p>
+ To answer that question,
+ we need to turn back to the "struts.xml" file and look at how Logon is configured.
+</p>
+
+
+<h4><a name="Logon.xml" id="Logon.xml">Logon Configuration</a></h4>
+
+<p>
+ The Logon action element outlines how the Logon workflow operates,
+ including what to do when the Action returns "input",
+ or the default result name "success".
+</p>
+
+<hr/>
+<h5>struts.xml Logon</h5>
+<pre><code><action name="<strong>Logon</strong>" class="mailreader2.Logon">
+ <result name="<strong>input</strong>">/pages/Logon.jsp</result>
+ <result name="<strong>cancel</strong>" type="redirect-action">Welcome</result>
+ <result type="redirect-action">MainMenu</result>
+ <result name="<strong>expired</strong>" type="chain">ChangePassword</result>
+ <<strong>exception-mapping</strong>
+ exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
+ result="<strong>expired</strong>"/>
+ <interceptor-ref name="<strong>guest</strong>"/>
+</action></code></pre>
+<hr/>
+
+<p>
+ In the Logon action element, the first result element is named "input".
+ If validation or authentification fail,
+ the Action class will return "input" and the framework will transfer control to the
+ "Logon.jsp" page.
+</p>
+
+<p>
+ The second result element is named <strong>cancel</strong>.
+ If someone presses the cancel button on the Logon page,
+ the Action class will return "cancel", this result will be selected,
+ and the framework will issue a redirect to the Welcome action.
+</p>
+
+<p>
+ The third result has no name,
+ so it will be called if the default <strong>success</strong> token is returned.
+ So, if the Logon succeeds,
+ control will transfer to the MainMenu action.
+</p>
+
+<p>
+ The MailReader DAO exposes a "ExpiredPasswordException".
+ If the DAO throws this exception when the User logs in,
+ the framework will process the exception-mapping
+ and transfer control to the "ChangePassword" action.
+</p>
+
+<p>
+ Just in case any other Exceptions are thrown,
+ the MailReader application also defines a global handler.
+</p>
+
+<hr/>
+<h5>struts.xml exception-mapping</h5>
+<pre><code><global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Exception"/>
+</global-exception-mappings></code></pre>
+<hr/>
+
+<p>
+ If an unexpected Exception is thrown,
+ the exception-mapping will transfer control to the action's "error" result,
+ or to a global "error" result.
+ The MailReader defines a global "error" result
+ which transfers control to an "Error.jsp" page
+ that can display the error message.
+</p>
+
+<hr/>
+<h5>Error.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Unexpected Error</title>
+ </head>
+ <body>
+ <h2>An unexpected error has occured</h2>
+ <p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+ </p>
+ <hr />
+ <h3>Error Message</h3>
+ <strong><s:actionerror /></strong>
+ <p>
+ <strong><s:property value="%{exception.message}"/></strong>
+ </p>
+ <hr />
+ <h3>Technical Details</h3>
+ <p>
+ <strong><s:property value="%{exceptionStack}"/></strong>
+ </p>
+ <jsp:include page="Footer.jsp"/>
+ </body>
+</html></code></pre>
+<hr/>
+
+<p>
+ The Error page uses <strong>property</strong> tags to expose
+ the Exception message and the Exception stack.
+</p>
+
+<p>
+ Finally, the Logon action specifies an <strong>InterceptorStack</strong>
+ named <strong>defaultStack.</strong>
+ If you've worked with Struts 2 or WebWork 2 before, that might seem strange,
+ since "defaultStack" is the factory default.
+</p>
+
+<p>
+ In the MailReader application, most of the actions are only available
+ to authenticated users.
+ The exceptions are the Welcome, Logon, and Register actions
+ which are available to everyone.
+ To authenticate clients,
+ the MailReader uses a custom Interceptor and a custom Interceptor stack.
+</p>
+
+<hr/>
+<h5>mailreader2.AuthenticationInterceptor</h5>
+<pre><code>package mailreader2;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.Action;
+import java.util.Map;
+import org.apache.struts.apps.mailreader.dao.User;
+
+public class <strong>AuthenticationInterceptor</strong> implements Interceptor {
+ public void destroy () {}
+ public void init() {}
+ public String <strong>intercept</strong>(ActionInvocation actionInvocation) throws Exception {
+ Map session = actionInvocation.getInvocationContext().getSession();
+ User user = (User) session.get(Constants.USER_KEY);
+ boolean isAuthenticated = (null!=user) && (null!=user.getDatabase());
+ if (<strong>isAuthenticated</strong>) {
+ return actionInvocation.invoke();
+ }
+ else {
+ return Action.LOGIN;
+ }
+ }
+}</code></pre>
+<hr/>
+
+<p>
+ The <strong>AuthenticationInterceptor</strong> looks to see if a User object
+ has been stored in the client's session state.
+ If so, it returns normally, and the next Interceptor in the set would be invoked.
+ If the User object is missing, the Interceptors returns "login".
+ The framework would match "login" to the global result,
+ and transfer control to the Logon action.
+</p>
+
+<p>
+ The MailReader defines four custom Interceptor stacks: "user", "user-submit",
+ "guest", and "guest-submit".
+</p>
+
+<hr/>
+<h5>struts.xml interceptors</h5>
+<pre><code><interceptors>
+ <interceptor name="<strong>authentication</strong>"
+ class="mailreader2.AuthenticationInterceptor"/>
+ <interceptor-stack name="<strong>user</strong>" >
+ <interceptor-ref name="authentication" />
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>user-submit</strong>" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="user"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>guest</strong>" >
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>guest-submit</strong>" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="guest"/>
+ </interceptor-stack>
+</interceptors>
+<<strong>default-interceptor-ref</strong> name="user"/></code></pre>
+<hr/>
+
+<p>
+ The <strong>user</strong> stacks require that the client be authenticated.
+ In other words, that a User object is present in the session.
+ The actions using a <strong>guest</strong> stack can be accessed by any client.
+ The <strong>-submit</strong> versions of each can be used with actions
+ with forms, to guard against double submits.
+</p>
+
+<h5>Double Submits</h5>
+
+<p>
+ A common problem with designing web applications is that users are impatient
+ and response times can vary.
+ Sometimes, people will press a submit button a second time.
+ When this happens, the browser submits the request again,
+ so that we now have two requests for the same thing.
+ In the case of registering a user, if someone does press the submit button
+ again, and their timing is bad,
+ it could result in the system reporting that the username has already been
+ used.
+ (The first time the button was pressed.)
+ In practice, this would probably never happen, but for a longer running
+ process, like checking out a shopping cart,
+ it's easier for a double submit to occur.
+</p>
+
+<p>
+ To forestall double submits, and "back button" resubmits,
+ the framework can generate a token that is embedded in the form
+ and also kept in the session.
+ If the value of the tokens do not compare,
+ then we know that there has been a problem,
+ and that a form has been submitted twice or out of sequence.
+</p>
+
+<p>
+ The Token Session Interceptor will also attempt to provide intelligent
+ fail-over in the event of multiple requests using the same session.
+ That is, it will block subsequent requests until the first request is complete,
+ and then instead of returning the "invalid.token" code,
+ it will attempt to display the same response that the
+ original, valid action invocation would have displayed
+</p>
+
+<p>
+ Because the default interceptor stack will now authenticate the client,
+ we need to specify the standard "defaultStack" for the three
+ "guest actions", Welcome, Logon, and Register.
+ Requiring authentification by default is the better practice, since it
+ means that we won't forget to enable it when creating new actions.
+ Meanwhile, those pesky users will ensure that we don't forget to disable
+ authentification for "guest" services.
+</p>
+
+<h3><a name="MainMenu" id="MainMenu">MainMenu</a></h3>
+
+<p>
+ On a successful logon, the Main Menu page displays.
+ If you logged in using the demo account,
+ the page title should be "Main Menu Options for John Q. User".
+ Below this legend should be two links:
+</p>
+
+<ul>
+ <li>
+ Edit your user registration profile
+ </li>
+ <li>
+ Log off MailReader Demonstration Application
+ </li>
+</ul>
+
+<p>
+ Let's review the source for the "MainMenu" action mapping,
+ and the "MainMenu.jsp".
+</p>
+
+<hr/>
+<h5>Action mapping element for MainMenu</h5>
+<pre><code><action name="MainMenu" class="mailreader2.MailreaderSupport">
+ <result>/pages/MainMenu.jsp</result>
+ </action></code></pre>
+
+<h5>MainMenu.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title><s:text name="mainMenu.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+
+ <body>
+ <h3><s:text name="mainMenu.heading"/> <strong><s:property
+ value="user.fullName"/></strong></h3>
+ <ul>
+ <li><a href="<s:url <strong>action="Registration!input"</strong> />">
+ <s:text name="mainMenu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url <strong>action="Logoff"</strong> />">
+ <s:text name="mainMenu.logoff"/>
+ </a>
+ </ul>
+ </body>
+</html></code></pre>
+<hr/>
+
+<p>
+ The source for "MainMenu.jsp" also contains a new tag, <strong>
+ property</strong>, which we use to customize the page with the
+ "fullName" property of the authenticated user.
+</p>
+
+<p>
+ Displaying the user's full name is the reason the MainMenu action
+ references the MailreaderSupport class.
+ The MailreaderSupport class has a User property that the text tag
+ can access.
+ If we did not utilize MailreaderSupport,
+ the property tag would not be able to find the User object to print
+ the full name.
+</p>
+
+<p>
+ The customized MainMenu page offers two standard links.
+ One is to "Edit your user registration profile".
+ The other is to "Logoff the MailReader Demonstration Application".
+</p>
+
+<h3><a name="Registration.jsp" id="Registration.jsp">Registration page</a>
+</h3>
+
+<p>
+ If you follow the "Edit your user registration profile" link from the Main
+ Menu page,
+ we will finally reach the heart of the MailReader application: the
+ Registration, or "Profile", page.
+ This page displays everything MailReader knows about you
+ (or at least your login),
+ while utilizing several interesting techniques.
+</p>
+
+<p>
+ To do double duty as the "Create" Registration page and the "Edit"
+ Registration page,
+ the "Registration.jsp" makes extensive use of the test tags,
+ to make it appears as though there are two distinct pages.
+</p>
+
+<hr />
+<h5>Registration.jsp - head element</h5>
+<pre><code><head>
+ <s:if test="<strong>task=='Create'</strong>">
+ <title><s:text name="registration.title.create"/></title>
+ </s:if>
+ <s:if test="<strong>task=='Edit'</strong>">
+ <title><s:text name="registration.title.edit"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head></code></pre>
+<hr />
+
+<p>
+ For example, if client is editing the form (task == 'Edit'),
+ the page inserts the username from the User object.
+ For a new Registration (task == 'Create'),
+ the page creates an empty data-entry field.
+</p>
+
+<hr/>
+<h5>Note:</h5>
+<blockquote>
+ <p><font class="hint">
+ <strong>Presention Logic</strong> -
+ The "test" tag is a convenient way to express presentation
+ logic within your pages.
+ Customized pages help to prevent user error,
+ and dynamic customization reduces the number of server pages your
+ application needs to maintain, among other benefits.
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The page also uses logic tags to display a list of subscriptions
+ for the given user.
+ If the RegistrationForm has task set to "Edit",
+ the lower part of the page that lists the subscriptions is exposed.
+</p>
+
+<hr/>
+<h5></h5>
+<pre><code><s:if test=<strong>"task == 'Edit'"</strong>>
+ <div align="center">
+ <h3><s:text name="heading.subscriptions"/></h3>
+ </div>
+ <!-- ... -->
+ </s:if>
+<jsp:include page="Footer.jsp"/>
+</body></html></code></pre>
+<hr/>
+
+<p>
+ Otherwise, the page contains just the top portion --
+ a data-entry form for managing the user's registration.
+</p>
+
+<h4><a name="iterator" id="iterator">iterator</a></h4>
+
+<p>
+ Besides "if" there are several other control tags that you can use
+ to sort, filter, or iterate over data.
+ The Registration page includes a good example of using the <strong>iterator</strong>
+ tag to display the User's Subscriptions.
+</p>
+
+<p>
+ The subscriptions are stored in a hashtable object, which is in turn
+ stored in the user object.
+ So to display each subscription, we have to reach into the user object,
+ and loop through the members of the subscription collection.
+ Using the iterator tag, you can code it the way it sounds.
+ </p>
+
+<hr/>
+<h5>Using iterator to list the Subscriptions</h5>
+<pre><code><s:iterator value="<strong>user.subscriptions</strong>">
+ <tr>
+ <td align="left">
+ <s:property value="<strong>host</strong>"/>
+ </td>
+ <td align="left">
+ <s:property value="<strong>username</strong>"/>
+ </td>
+ <td align="center">
+ <s:property value="<strong>type</strong>"/>
+ </td>
+ <td align="center">
+ <s:property value="<strong>autoConnect</strong>"/>
+ </td>
+ <td align="center">
+ <a href="<s:url action="<strong>Subscription!delete</strong>"><s:param name="<strong>host</strong>" value="host"/></s:url>">
+ <s:text name="registration.deleteSubscription"/>
+ </a>
+ <a href="<s:url action="<strong>Subscription!edit</strong>"><s:param name="<strong>host</strong>" value="host"/></s:url>">
+ <s:text name="registration.editSubscription"/>
+ </a>
+ </td>
+ </tr>
+</s:iterator></code></pre>
+<hr/>
+
+<p>
+ When the iterator renders, it generates a list of Subscriptions for the current User.
+</p>
+
+<hr />
+
+ <div align="center">
+ <h3>Current Subscriptions</h3>
+ </div>
+
+ <table border="1" width="100%">
+ <tr>
+ <th align="center" width="30%">
+ Host Name
+ </th>
+ <th align="center" width="25%">
+ User Name
+ </th>
+
+ <th align="center" width="10%">
+ Server Type
+ </th>
+ <th align="center" width="10%">
+ Auto
+ </th>
+ <th align="center" width="15%">
+ Action
+ </th>
+ </tr>
+ <tr>
+ <td align="left">
+ mail.hotmail.com
+ </td>
+ <td align="left">
+ user1234
+ </td>
+ <td align="center">
+ pop3
+ </td>
+
+ <td align="center">
+ false
+ </td>
+ <td align="center">
+ <a href="/struts2-mailreader/Subscription!delete.do?host=mail.hotmail.com">
+ Delete
+ </a>
+
+ <a href="/struts2-mailreader/Subscription!edit.do?host=mail.hotmail.com">
+ Edit
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ mail.yahoo.com
+ </td>
+ <td align="left">
+ jquser
+ </td>
+ <td align="center">
+ imap
+ </td>
+ <td align="center">
+ false
+ </td>
+ <td align="center">
+ <a href="/struts2-mailreader/Subscription!delete.do?host=mail.yahoo.com">
+ Delete
+ </a>
+
+ <a href="/struts2-mailreader/Subscription!edit.do?host=mail.yahoo.com">
+ Edit
+ </a>
+ </td>
+ </tr>
+ </table>
+ <a href="/struts2-mailreader/Subscription!input.do">Add</a>
+
+<hr />
+
+ <p>
+ Now look back at the code used to generate this block.
+ </p>
+ <p>
+ Notice anything nifty?
+ </p>
+ <p>
+ How about that the markup between the iterator tag is
+ actually <em>simpler</em> than the markup that we would use to render one row of the table?
+ </p>
+ <p>
+ Instead of using a qualified reference like "value=user.subscription[0].host",
+ we use the simplest possible reference: "value=host".
+ We didn't have to define a local variable, and reference that local in the loop code.
+ The reference to each item in the list is automatically resolved, no fuss, no muss.
+ </p>
+ <p>
+ Nice trick!
+ </p>
+
+<p>
+ The secret to this magic is the <strong>value stack</strong>.
+ Next to Interceptors, the value stack is probably the coolest thing there is about the framework.
+ To explain the value stack, let's step back and start from the beginning.
+</p>
+
+<p>
+ Merging dynamic data into static web pages is a primary reason
+ we create web applications.
+ The Java API has a mechanism that allows you to
+ place objects in a servlet scope (page, request, session, or
+ application), and then retrieve them using a JSP scriplet.
+ If the object is placed directly in one of the scopes,
+ a JSP tag or scriptlet can find that object by searching page scope and
+ then request scope, and session scope, and finally application scope.
+</p>
+
+<p>
+ The value stack works much the same way, only better.
+ When you push an object on the value stack,
+ the public properties of that object become first-class properties of the stack.
+ The object's properties become the stack's properties.
+ If another object on the stack has properties of the same name,
+ the last object pushed onto the stack wins. (Last-In, First-Out.)
+</p>
+
+<p>
+ When the iterator tag loops through a collection,
+ it pushes each item in the collection onto the stack.
+ The item's properties become the stack's property.
+ In the case of the Subscriptions,
+ if the Subscription has a public Host property,
+ then during that iteration,
+ the stack can access the same property.
+</p>
+
+<p>
+ Of course, at the end of each iteration, the tag "pops" the item off the stack.
+ If we were to try and access the Host property later in the page,
+ it won't be there.
+</p>
+
+<p>
+ When an Action is invoked, the Action class is pushed onto the value stack.
+ Since the Action is on the value stack,
+ our tags can access any property of the Action as if it were an implicit property of the page.
+ The tags don't access the Action directly.
+ If a textfield tag is told to render the "Username" property,
+ the tag asks the value stack for the value of "Username",
+ and the value stack returns the first property it finds by that name.
+</p>
+
+<p>
+ The Validators also use the stack.
+ When validation fails on a field,
+ the value for the field is pushed onto the value stack.
+ As a result, if the client enters text into an Integer field,
+ the framework can still redisplay whatever was entered.
+ An invalid input value is not stored in the field (even if it could be).
+ The invalid input is pushed onto the stack for the scope of the request.
+</p>
+
+<p>
+ The Subscription list uses another new tag: the <strong>param</strong> tag.
+ As tags go, "param" takes very few parameters of its own: just "name" and "value", and neither is required.
+ Although simple, "param" is one of the most powerful tags the framework provides.
+ Not so much because of what it does, but because of what "param" allows the other tags to do.
+</p>
+
+<p>
+ Essentially, the "param" tag provides parameters to other tags.
+ A tag like "text" might be retrieving a message template with several replaceable parameters.
+ No matter how many parameters are in the template, and no matter what they are named,
+ you can use the "param" tag to pass in whatever you need.
+</p>
+
+<pre><code>pager.legend = Displaying {current} of {count} items matching {criteria}.
+...
+<s:text name="pager.legend">
+ <s:<strong>param</strong> name="current" value="42" />
+ <s:<strong>param</strong> name="count" value="314" />
+ <s:<strong>param</strong> name="criteria" value="Life, the Universe, and Everything" />
+</s:text></code></pre>
+
+<p>
+ In the case of an "url" tag,
+ we can use "param" to create the query string.
+ A statement like this:
+</p>
+
+<pre><code>
+ <s:url action="Subscription!edit"><s:param name="<strong>host" value="host</strong>"/></s:url>">
+</code></pre>
+
+<p>
+ can render a hyperlink like this:
+</p>
+
+<pre><code>
+ <a href="/struts2-mailreader/Subscription!edit.do?<strong>host=mail.yahoo.com</strong>">Edit</a>
+</code></pre>
+
+
+<!--
+<p>
+ At the foot of the Register page is a link for adding a subscription.
+ Let's wind up the tour by following the Add link and then logging off.
+ Like the link for creating a Registration, Add points to an "Edit" action,
+ namely "EditSubscription".
+</p>
+-->
+
+<p>
+ If a hyperlink needs more parameters,
+ you can use "param" to add as many parameters as needed.
+</p>
+
+<h3>
+ <a name="Subscription" id="Subscription">Subscription</a>
+</h3>
+
+<p>
+ If we follow one of the "Edit" subscription links on the Registration page,
+ we come to the Subscriptions page,
+ which displays the details of our description in a data-entry form.
+ Let's have a look a the Subscription configuration in "struts.xml"
+ and follow the bouncing ball from page to action to page.
+</p>
+
+<hr />
+<h5>struts.xml Subscription element</h5>
+<pre><code><action name="Subscription" class="mailreader2.Subscription">
+ <result name="input">/pages/Subscription.jsp</result>
+ <result type="redirect-action">Registration!input</result>
+</action></code></pre>
+<hr />
+
+<p>
+ The Edit link specified the Subscription action,
+ but also includes the qualifier <strong>!edit</strong>.
+ The <strong>!</strong> idiom tells the framework to invoke the
+ "edit" method of the Subscription action,
+ instead of the default "execute" method
+ The "alternate" execute methods are called <strong>alias</strong> methods.
+</p>
+
+<hr />
+<h5>Subscription edit alias</h5>
+<pre><code>public String <strong>edit()</strong> {
+ <strong>setTask(Constants.EDIT);</strong>>
+ return find();
+}
+
+public String find() {
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+ if (sub == null) {
+ return ERROR;
+ }
+ <strong>setSubscription(sub);</strong>
+ return INPUT;
+}</code></pre>
+<hr />
+
+<p>
+ The "edit" alias has two responsibilities.
+ First, it must set the Task property to "Edit".
+ The Subscription page will render itself differently
+ depending on the value of the Task property.
+ Second, "edit" must locate the relevant Subscription
+ and set it to the Subscription property.
+ If all goes well, "edit" returns the INPUT token,
+ so that the "input" result will be invoked.
+</p>
+
+<p>
+ In the normal course, the Subscription should always be found,
+ since we selected the entry from a system-generated list.
+ If the Subscription is not found,
+ it would be because the database disappeared
+ or the request is being spoofed.
+ If the Subscription is not found,
+ edit returns the token for the global "error" result,
+ because this condition is unexpected.
+</p>
+
+<p>
+ The business logic for the "edit" alias is a simple wrapper
+ around the MailReader DAO classes.
+</p>
+
+<hr />
+<h5>MailreaderSupport findSubscription()</h5>
+<pre><code>public Subscription <strong>findSubscription()</strong> {
+ return findSubscription(getHost());
+}
+
+public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = <strong>getUser().findSubscription(host);</strong>
+ return subscription;
+}</code></pre>
+<hr />
+
+<p>
+ This code is very simple
+ and doesn't seem to provide much in the way of error handling.
+ But, that's OK.
+ Since the page is suppose to be entered from a link that we created,
+ we do expect everything to go right here.
+ But, if it doesn't, the global exception handler we defined in "struts.xml"
+ will trap the exception for us.
+</p>
+
+<p>
+ Likewise, the AuthentificationInterceptor will ensure that only clients
+ with a valid User object can try to edit a Subscription.
+ If the session expired, or someone bookmarked the page,
+ the client will be redirected to the Logon page automatically.
+</p>
+
+<p>
+ As a final layer of defense, we also configured a validator for Subscription,
+ to ensure that we are passed a Host parameter.
+</p>
+
+<hr />
+<h5>Subscription-validation.xml</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+ <field name="<strong>host</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+</validators></code></pre>
+<hr />
+
+<p>
+ By keeping routine sety precautions out of the Action class,
+ the all-important Actions becomes smaller and easier to maintain.
+</p>
+
+<p>
+ After setting the relevent Subscription object to the Subscription property,
+ the framework transfers control to the (you guessed it) Subscription page.
+</p>
+
+<hr />
+<h5>Subscription.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <s:if test="task=='Create'">
+ <title><s:text name="subscription.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="subscription.title.edit"/></title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title><s:text name="subscription.title.delete"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+ <body onLoad="self.focus();document.Subscription.username.focus()">
+
+ <s:actionerror/>
+ <s:form method="POST" <strong>action="SubscriptionSave"</strong> validate="false">
+ <strong><s:token /></strong>
+ <strong><s:hidden name="task"/></strong>
+ <strong><s:label label="%{getText('username')}" name="user.username"/></strong>
+
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('mailHostname')}" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('mailHostname')}" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:label label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:label label="%{getText('mailServerType')}"
+ name="subscription.type"/>
+ <s:label label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.confirm')}"/>
+ </s:if>
+ <s:else>
+ <s:textfield label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:textfield label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <strong><s:select label="%{getText('mailServerType')}"
+ name="subscription.type" list="types"/></strong>
+ <strong><s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/></strong>
+ <s:submit value="%{getText('button.save')}"/>
+ <s:reset value="%{getText('button.reset')}"/>
+ </s:else>
+
+ <s:submit action="Registration!input"
+ value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+ </s:form>
+
+ <jsp:include page="Footer.jsp"/>
+ </body>
+</html></code></pre>
+<hr />
+
+<p>
+ As before, we'll discuss the tags and attributes that are new to this page:
+ "token", "hidden", "label", "select", and "checkbox".
+</p>
+
+<p>
+ When we looked at the form tag for the Logon page,
+ it did not specify a target for the submit.
+ Instead, it just posted back to the Logon action.
+ In this <strong>form</strong> tag, we are specifying a different action,
+ <strong>SubscriptionSave</strong>
+ to be the target of the submit,
+</p>
+
+<p>
+ The main reason we use another action is so that we can use a different set of validations.
+ When we retrieve the Subscription for editing, all we need is the Host property.
+ When we save the Subscription, we want to validate additional properties.
+ Since the validation files are coupled to the classes,
+ we created a new Action class for saving a Subscription.
+</p>
+
+<hr />
+<h5>Subscription-validation.xml</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+ <field name="<strong>host</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+</validators></code></pre>
+<hr />
+
+<p>
+ The validators follow the same type of inheritance path as the classes.
+ SubscriptionSave extends Subscription,
+ so when SubscriptionSave is validated,
+ the Host property specified by "Subscription-validation.xml" will also be required.
+</p>
+
+<p>
+ The <strong>token</strong> tag works with the Token Session Interceptor to foil double submits.
+ The tag generates a key that is embedded in the form and cached in the session.
+ Without this tag, the Interceptor can't work it's magic.
+</p>
+
+<p>
+ The <strong>hidden</strong> tag embeds the Task property into the form.
+ When the form is submitted,
+ the SubscriptionSave action wil use the Task property to decide
+ whether to insert or update the form.
+</p>
+
+<p>
+ The <strong>label</strong> renders a "read only" version of a property,
+ suitable for placement in the form.
+ In Edit or Delete mode, we want the Host property to be immutable,
+ since it is used as a key. (As unwise as that might sound.)
+ In Delete mode, all of the properties are immutable,
+ since we are simply confirming the delete operation.
+</p>
+
+<p>
+ Saving the best for last, the Subscription utilizes two more interesting
+ tags, "select" and "checkbox".
+</p>
+
+<p>
+ Unsurprisingly, the <strong>select</strong> tag renders a select control,
+ but the tag does so without requiring a lot of markup or redtape.
+</p>
+
+<pre><code><s:select label="%{getText('mailServerType')}"
+ name="subscription.type" <strong>list="types"</strong> />
+</code></pre>
+
+<p>
+ The interesting attribute of the "select" tag is "list",
+ which, in our case, specifies a value of "types".
+ If we take another look at the Subscription action,
+ we can see that it implements an interface named Preparable
+ and populates a Types property in a method named "prepare".
+</p>
+
+<hr />
+<h5>Subscription-validation.xml</h5>
+<pre><code>public class <strong>Subscription</strong> extends MailreaderSupport
+ <strong>implements Preparable</strong> {
+
+ private Map types = null;
+ public Map <strong>getTypes()</strong> {
+ return types;
+ }
+
+ public void <strong>prepare()</strong> {
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+ setHost(getSubscriptionHost());
+ }
+
+ // ... </code></pre>
+<hr />
+
+<p>
+ The default Interceptor stack includes the <strong>PrepareInterceptor</strong>,
+ which observes the Preparable interface.
+</p>
+
+<hr />
+<h5>PrepareInterceptor</h5>
+<pre><code>public class <strong>PrepareInterceptor</strong> extends AroundInterceptor {
+
+ protected void after(ActionInvocation dispatcher, String result) throws Exception {
+ }
+
+ protected void before(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+ <strong>if (action instanceof Preparable) {
+ ((Preparable) action).prepare();</strong>
+ }
+ }
+}</code></pre>
+
+<p>
+ The PrepareInterceptor ensures that the "prepare" method will always be called
+ before "execute" or an alias method is invoked.
+ We use "prepare" to setup the list of items for the select list to display.
+ We also transfer the Host property from our Subscription object
+ to a local property, where it is easier to manage.
+</p>
+
+
+<h4>
+ <a name="SubscriptionAction.java" id="SubscriptionAction.java">SubscriptionAction.java</a>
+</h4>
+
+<p>
+ Like many applications, the MailReader uses mainly String properties.
+ One exception is the AutoConnect property of the Subscription object.
+ On the HTML form, the AutoConnect property is represented by a checkbox,
+ and checkboxes need to be handled differently that other controls.
+</p>
+
+<p>
+ The <strong>checkbox</strong> starts out as a simple enough control.
+</p>
+
+<pre><code> <s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/></code></pre>
+
+<p>
+ The Subscription object has a boolean AutoConnect property,
+ and the checkbox simply has to represent its state.
+ The problem is, if you clear a checkbox, the browser client will not submit <em>anything</em>.
+ Nada. Zip.
+ It is as if the checkbox control never existed.
+ The HTTP protocol has no way to affirm "false".
+ If the control is missing, we need to figure out it's been unclicked.
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p class="hint">
+ <strong>Checkboxes</strong> -
+ The HTML checkbox is a tricky control.
+ The problem is that, according to the W3C specification, a value is
+ only guaranteed to be sent
+ if the control is checked.
+ If the control is not checked, then the control may be omitted from
+ the request, as if it was on the page.
+ This can cause a problem with session-scope checkboxes.
+ Once you set the checkbox to true, the control can't set it to false
+ again,
+ because if you uncheck the box, nothing is sent, and so the control
+ stays checked.
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ The simplest solution is to employ our old friend Preparable again.
+ In the "prepare" method for SubscriptionSave,
+ we can set the property represented by the checkbox to false.
+ If the control is not submitted, then the property remains false.
+ If the control is submitted, then the property is set to true.
+</p>
+
+<hr />
+<h5>SubscriptionSave</h5>
+<pre><code>public final class SubscriptionSave extends Subscription {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ <strong>getSubscription().setAutoConnect(false);</strong>
+ }
+
+ public String execute() throws Exception {
+ return save();
+ }
+}</code></pre>
+<hr />
+
+
+<p>
+ If we press the SAVE button,
+ the form will be submitted to the SubscriptionSave action.
+ If the validation succeeds, as we've seen,
+ SubscriptionSave will invoke the Subscription.save method.
+</p>
+
+<hr />
+<h5>Subscription save method</h5>
+<pre><code>public String <strong>save</strong>() throws Exception {
+
+ if (Constants.DELETE.equals(getTask())) {
+ <strong>removeSubscription</strong>();
+ }
+
+ if (Constants.CREATE.equals(getTask())) {
+ <strong>copySubscription(</strong>getHost());
+ }
+
+ saveUser();
+ return SUCCESS;
+}</code></pre>
+<hr />
+
+<p>
+ The <strong>save</strong> method uses the Task property to handle
+ the special cases of deleting and creating,
+ and then updates the state of the User object.
+</p>
+
+<p>
+ The <strong>removeSubscription</strong> method calls the DAO facade,
+ and then updates the application state.
+</p>
+
+<hr />
+<h5>removeSubscription</h5>
+<pre><code>public void <strong>removeSubscription</strong>() throws Exception {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(Constants.SUBSCRIPTION_KEY);
+}</code></pre>
+<hr />
+
+<p>
+ The <strong>copySubscription</strong> method is a bit more interesting.
+ The MailReader DAO layer API includes some immutable fields
+ that can't be set once the object is created.
+ Because key fields are immutable,
+ we can't just create a Subscription, let the framework populate all the fields,
+ and then save it when we are done -- because some fields can't be populated,
+ except at construction.
+</p>
+
+<p>
+ One workaround would be to declare properties on the Action
+ for all the properties we need to pass to the Subscription or User objects.
+ When we are ready to create the object,
+ we could pass the new object values from the Action properties.
+</p>
+
+<p>
+ Another workaround is to declare only the immutable properties on the Action,
+ and then use what we can from the domain object.
+</p>
+
+<p>
+ This implementation of the MailReader utilizes the second alternative.
+ We define User and Subscription objects on our base Action,
+ and add other properties only as needed.
+</p>
+
+<p>
+ To add a new Subscription or User,
+ we create a blank object to capture whatever fields we can.
+ When this "input" object returns, we create a new object,
+ setting the immutable fields to appropriate values,
+ and copy over the rest of the properties.
+</p>
+
+<hr />
+<h5>copySubscription</h5>
+<pre><code>public void <strong>copySubscription</strong>(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ <strong>BeanUtils.setValues</strong>(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+}</code></pre>
+
+<p>
+ Of course, this is not a preferred solution,
+ but merely a way to work around an issue in the MailReader DAO API
+ that would not be easy for us change.
+</p>
+
+<h3>Summary</h3>
+<p>
+ At this point, we've booted the application, logged on,
+ reviewed a Registration record, and edited a Subscription.
+ Of course, there's more, but from here on, it is mostly more of the same.
+ The full source code for MailReader is
+ <a href="http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/struts2/apps/mailreader/">available online</a>
+ and in the distribution.
+</p>
+
+<p>
+ Enjoy!
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/struts-power.gif b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/struts-power.gif
new file mode 100644
index 0000000..5f4e9d4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-bang/src/main/webapp/struts-power.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/README.txt b/struts-sandbox/struts2/apps/mailreader-ibatis/README.txt
new file mode 100644
index 0000000..a32d28c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/README.txt
@@ -0,0 +1,18 @@
+README.txt - mailreader-ibatis
+
+The MailReader demonstrates a localized application with a master/child
+CRUD workflow.
+
+This rendition also demonstrates using iBATIS SQL Maps and a streamlined
+data access layer for database access.
+
+See the Sandbox for other MailReader examples using other architectures.
+
+* http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2/apps/
+
+For more about the MailReader applicaton genneraly, visit Struts University.
+
+* http://www.StrutsUniversity.org/
+
+
+----------------------------------------------------------------------------
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/pom.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/pom.xml
new file mode 100644
index 0000000..cf23ee6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-apps</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-mailreader</artifactId>
+ <packaging>war</packaging>
+ <name>MailReader Example Application</name>
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>1.8.0.4</version>
+ </dependency>
+ <dependency>
+ <groupId>com.ibatis</groupId>
+ <artifactId>ibatis2-sqlmap</artifactId>
+ <version>2.1.7.597</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>struts-mailreader-dao</artifactId>
+ <version>1.3.5</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty6-plugin</artifactId>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-j2ee_1.4_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/ApplicationListener.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/ApplicationListener.java
new file mode 100644
index 0000000..c7a269c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/ApplicationListener.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+package mailreader2;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Support information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class ApplicationListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/AuthenticationInterceptor.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/AuthenticationInterceptor.java
new file mode 100644
index 0000000..627c456
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/AuthenticationInterceptor.java
@@ -0,0 +1,33 @@
+package mailreader2;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.Map;
+
+public class AuthenticationInterceptor implements Interceptor {
+
+ public void destroy() {
+ }
+
+ public void init() {
+ }
+
+ public String intercept(ActionInvocation actionInvocation) throws Exception {
+
+ Map session = actionInvocation.getInvocationContext().getSession();
+
+ User user = (User) session.get(Constants.USER_KEY);
+
+ boolean isAuthenticated = (null != user) && (null != user.getDatabase());
+
+ if (!isAuthenticated) {
+ return Action.LOGIN;
+ } else {
+ return actionInvocation.invoke();
+ }
+
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/ChangePassword.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/ChangePassword.java
new file mode 100644
index 0000000..9bd958b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/ChangePassword.java
@@ -0,0 +1,10 @@
+package mailreader2;
+
+/**
+ * <p>
+ * When implemented, allow guest to change password,
+ * given correct credentials.
+ * </p>
+ */
+public class ChangePassword extends MailreaderSupport {
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Constants.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Constants.java
new file mode 100644
index 0000000..45afd48
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Constants.java
@@ -0,0 +1,150 @@
+/*
+ * $Id: Constants.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+/**
+ * <p> Manifest constants for the MailReader application. </p>
+ */
+public final class Constants {
+
+ // -- Statements --
+
+ public static final Integer DB_FALSE = 0;
+ public static final Integer DB_TRUE = 1;
+
+ public static final String LOCALE_LIST = "LOCALE_LIST";
+ public static final String REGISTRATION_INSERT_ASSERT = "REGISTRATION_INSERT_ASSERT";
+ public static final String REGISTRATION_INSERT = "REGISTRATION_INSERT";
+ public static final String REGISTRATION_PASSWORD = "REGISTRATION_PASSWORD";
+ public static final String REGISTRATION_FULLNAME = "REGISTRATION_FULLNAME";
+ public static final String REGISTRATION_EDIT = "REGISTRATION_EDIT";
+ public static final String REGISTRATION_UPDATE = "REGISTRATION_UPDATE";
+ public static final String SUBSCRIPTION_INSERT_ASSERT = "SUBSCRIPTION_INSERT_ASSERT";
+ public static final String SUBSCRIPTION_INSERT = "SUBSCRIPTION_INSERT";
+ public static final String SUBSCRIPTION_LIST = "SUBSCRIPTION_LIST";
+ public static final String SUBSCRIPTION_EDIT = "SUBSCRIPTION_EDIT";
+ public static final String SUBSCRIPTION_UPDATE = "SUBSCRIPTION_UPDATE";
+
+ // -- Tokens --
+
+ /**
+ * <p> The token representing a "cancel" request. </p>
+ */
+ public static final String CANCEL = "cancel";
+
+ /**
+ * <p> The token representing a "create" task. </p>
+ */
+ public static final String CREATE = "Create";
+
+ /**
+ * <p> The application scope attribute under which our user database is
+ * stored. </p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ * <p> The token representing a "edit" task. </p>
+ */
+ public static final String DELETE = "Delete";
+
+ /**
+ * <p> The token representing a "edit" task. </p>
+ */
+ public static final String EDIT = "Edit";
+
+ /**
+ * <p> The package name for this application. </p>
+ */
+ public static final String PACKAGE = "org.apache.struts.apps.mailreader";
+
+ /**
+ * <p> The session scope attribute under which the Support object
+ * currently selected by our logged-in User is stored. </p>
+ */
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ /**
+ * <p> The session scope attribute under which the User object for the
+ * currently logged in user is stored. </p>
+ */
+ public static final String USER_KEY = "user";
+
+ /**
+ * <p>The token representing the "Host" property.
+ */
+ public static final String HOST = "host";
+
+ // ---- Error Messages ----
+
+ /**
+ * <p/>
+ * A static message in case message resource is not loaded.
+ * </p>
+ */
+ public static final String ERROR_MESSAGES_NOT_LOADED =
+ "ERROR: Message resources not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p/>
+ * A static message in case database resource is not loaded.
+ * <p/>
+ */
+ public static final String ERROR_DATABASE_NOT_LOADED =
+ "ERROR: User database not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p/>
+ * A standard key from the message resources file, to test if it is available.
+ * <p/>
+ */
+ public static final String ERROR_DATABASE_MISSING = "error.database.missing";
+
+ /**
+ * <p/>
+ * A "magic" username to trigger an ExpiredPasswordException for testing.
+ * </p>
+ */
+ public static final String EXPIRED_PASSWORD_EXCEPTION = "ExpiredPasswordException";
+
+ /**
+ * <p/>
+ * Name of field to associate with authentification errors.
+ * <p/>
+ */
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ /**
+ * <p/>
+ * A static message in case message resource is not loaded.
+ * </p>
+ */
+ public static final String ERROR_INVALID_WORKFLOW =
+ "ERROR: Action is being executed out of sequence!";
+
+ // ---- Log Messages ----
+
+ /**
+ * <p> Message to log if saving a user fails. </p>
+ */
+ public static final String LOG_DATABASE_SAVE_ERROR =
+ " Unexpected error when saving User: ";
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Logoff.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Logoff.java
new file mode 100644
index 0000000..4d88393
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Logoff.java
@@ -0,0 +1,30 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+/**
+ * <p> Log user out of the current session. </p>
+ */
+public class Logoff extends MailreaderSupport {
+
+ public String execute() {
+ setUser(null);
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/MailreaderSupport.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/MailreaderSupport.java
new file mode 100644
index 0000000..1f4b648
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/MailreaderSupport.java
@@ -0,0 +1,558 @@
+/*
+ * $Id: BaseAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.ModelDriven;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUser;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+/**
+ * <p> Base Action for MailreaderSupport application. </p>
+ * <p/>
+ * <p> Note that this class does NOT implement model driven because of the way
+ * the pre-existing model is designed. The MailReader DAO includes immutable
+ * fields that can only be set on construction, and some objects do not have a
+ * default construction. One approach would be to mirror all the DAO
+ * properties on the Actions. As an alternative, this implementations uses the
+ * DAO properties where possible, and uses local Action properties only as
+ * needed. To create new objects, a blank temporary object is constructed, and
+ * the page uses a mix of local Action properties and DAO properties. When the
+ * new object is to be saved, the local Action properties are used to create
+ * the object using the DAO factory methods, the input values are copied from
+ * the temporary object, and the new object is saved. It's kludge, but it
+ * avoids creating unnecessary local properties. Pick your poison.</p>
+ */
+public class MailreaderSupport extends ActionSupport
+ implements SessionAware, ApplicationAware {
+
+ /**
+ * Return CANCEL so apropriate result can be selected.
+ *
+ * @return "cancel" so apropriate result can be selected.
+ */
+ public String cancel() {
+ return Constants.CANCEL;
+ }
+
+ // ---- ApplicationAware ----
+
+ /**
+ * <p>Field to store application context or its proxy.</p>
+ * <p/>
+ * <p>The application context lasts for the life of the application. A
+ * reference to the database is stored in the application context at
+ * startup.</p>
+ */
+ private Map application;
+
+ /**
+ * <p>Store a new application context.</p>
+ *
+ * @param value A Map representing application state
+ */
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ /**
+ * <p>Provide application context.</p>
+ */
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- Task property (utilized by UI) ----
+
+ /**
+ * <p>Field to store workflow task.</p>
+ * <p/>
+ * <p>The Task is used to track the state of the CRUD workflows. It can be
+ * set to Constant.CREATE, Constant.EDIT, or Constant.DELETE as
+ * needed.</p>
+ */
+ private String task = null;
+
+
+ /**
+ * <p>Provide worklow task.</p>
+ *
+ * @return Returns the task.
+ */
+ public String getTask() {
+ return task;
+ }
+
+ /**
+ * <p>Store new workflow task.</p>
+ *
+ * @param value The task to set.
+ */
+ public void setTask(String value) {
+ task = value;
+ }
+
+ // ---- Token property (utilized by UI) ----
+
+ /**
+ * <p>Field to store double-submit guard.</p>
+ */
+ private String token = null;
+
+
+ /**
+ * <p>Provide Token.</p>
+ *
+ * @return Returns the token.
+ */
+ public String getToken() {
+ return token;
+ }
+
+ /**
+ * <p>Store new Token.</p>
+ *
+ * @param value The token to set.
+ */
+ public void setToken(String value) {
+ token = value;
+ }
+
+ // ---- Host property ----
+
+ /**
+ * <p>Field to store Support host.</p>
+ * <p/>
+ * <p> The host is an immutable property of the Subscrtion DAP object, so
+ * we need to store it locally until we are ready to create the
+ * Support. </p>
+ */
+ private String host;
+
+ /**
+ * <p>Provide tSubscription host.</p>
+ *
+ * @return host property
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * <p>Store new Support host.</p>
+ *
+ * @param value
+ */
+ public void setHost(String value) {
+ host = value;
+ }
+
+ // ---- Password property ----
+
+ /**
+ * <p>Field to store User password property.</p>
+ * <p/>
+ * <p>The User DAO object password proerty is immutable, so we store it
+ * locally until we are ready to create the object.</p>
+ */
+ private String password = null;
+
+
+ /**
+ * <p>Provide User password</p>
+ *
+ * @return Returns the password.
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * <p>Store new User Password</p>
+ *
+ * @param value The password to set.
+ */
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ // ---- Password2 property (confirmation) ----
+
+ /**
+ * <p>Field to store the User password confirmation.</p>
+ * <p/>
+ * <p>When a User object is created, we ask the client to enter the
+ * password twice, to help ensure the password is being typed
+ * correctly.</p>
+ */
+ private String password2 = null;
+
+
+ /**
+ * <p>Provide the User password confirmation.</p>
+ *
+ * @return Returns the confirmationpassword.
+ */
+ public String getPassword2() {
+ return password2;
+ }
+
+ /**
+ * <p>Store a new User password confirmation.</p>
+ *
+ * @param value The confirmation password to set.
+ */
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ // ---- Username property ----
+
+ /**
+ * <p>Field to store User username.</p>
+ * <p/>
+ * <p>The User DAO object password proerty is immutable, so we store it
+ * locally until we are ready to create the object.</p>
+ */
+ private String username = null;
+
+
+ /**
+ * <p>Provide User username.</p>
+ *
+ * @return Returns the User username.
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * <p>Store new User username</p>
+ *
+ * @param value The username to set.
+ */
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ // ---- Database property ----
+
+ /**
+ * <p>Provide reference to UserDatabase, or null if the database is not
+ * available. </p>
+ *
+ * @return a reference to the UserDatabase or null if the database is not
+ * available
+ */
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(Constants.DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText("error.database.missing"));
+ }
+ return (UserDatabase) db;
+ }
+
+ /**
+ * <p>Store a new reference to UserDatabase</p>
+ *
+ * @param database
+ */
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(Constants.DATABASE_KEY, database);
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(Constants.USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(Constants.USER_KEY, user);
+ }
+
+ /**
+ * <p>Obtain User object from database, or return null if the credentials
+ * are not found or invalid.</p>
+ *
+ * @param username User username
+ * @param password User password
+ * @return User object or null if not found
+ * @throws ExpiredPasswordException
+ */
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+ // FIXME: Stupid testing hack to compensate for inadequate DAO layer
+ if (Constants.EXPIRED_PASSWORD_EXCEPTION.equals(username)) {
+ throw new ExpiredPasswordException(Constants.EXPIRED_PASSWORD_EXCEPTION);
+ }
+
+ User user = getDatabase().findUser(username);
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ this.addFieldError(Constants.PASSWORD_MISMATCH_FIELD,
+ getText("error.password.mismatch"));
+ }
+ return user;
+ }
+
+ /**
+ * <p><code>Log</code> instance for this application. </p>
+ */
+ protected Log log = LogFactory.getLog(Constants.PACKAGE);
+
+ /**
+ * <p> Persist the User object, including subscriptions, to the database.
+ * </p>
+ *
+ * @throws java.lang.Exception on database error
+ */
+ public void saveUser() throws Exception {
+ try {
+ getDatabase().save();
+ } catch (Exception e) {
+ String message = Constants.LOG_DATABASE_SAVE_ERROR + getUser()
+ .getUsername();
+ log.error(message, e);
+ throw new Exception(message, e);
+ }
+ }
+
+ public void createInputUser() {
+ User user = new MemoryUser(null, null);
+ setUser(user);
+ }
+
+ /**
+ * <p> Verify input for creating a new user, create the user, and process
+ * the login. </p>
+ *
+ * @return A new User and empty Errors if create succeeds, or null and
+ * Errors if create fails
+ */
+ public User createUser(String username, String password) {
+
+ UserDatabase database = getDatabase();
+ User user;
+
+ try {
+ user = database.findUser(username);
+ }
+
+ catch (ExpiredPasswordException e) {
+ user = getUser(); // Just so that it is not null
+ }
+
+ if (user != null) {
+ this.addFieldError("username", "error.username.unique");
+ return null;
+ }
+
+ return database.createUser(username);
+ }
+
+ // Since user.username is immutable, we have to use some local properties
+
+ /**
+ * <p>Use the current User object to create a new User object, and make
+ * the new User object the authenticated user.</p>
+ * <p/>
+ * <p>The "current" User object is usually a temporary object being used
+ * to capture input.</p>
+ *
+ * @param _username User username
+ * @param _password User password
+ */
+ public void copyUser(String _username, String _password) {
+ User input = getUser();
+ input.setPassword(_password);
+ User user = createUser(_username, _password);
+ if (null != user) {
+ BeanUtils.setValues(user, input, null);
+ setUser(user);
+ }
+ }
+
+ // ---- Support property ----
+
+ /**
+ * <p>Obtain the cached Support object, if any. </p>
+ *
+ * @return Cached Support object or null
+ */
+ public Subscription getSubscription() {
+ return (Subscription) getSession().get(Constants.SUBSCRIPTION_KEY);
+ }
+
+ /**
+ * <p>Store new User Support.</p>
+ *
+ * @param subscription
+ */
+ public void setSubscription(Subscription subscription) {
+ getSession().put(Constants.SUBSCRIPTION_KEY, subscription);
+ }
+
+ /**
+ * <p> Obtain User Support object for the given host, or return null
+ * if not found. </p>
+ * <p/>
+ * <p>It would be possible for this code to throw a NullPointerException,
+ * but the ExceptionHandler in the xwork.xml will catch that for us.</p>
+ *
+ * @return The matching Support or null
+ */
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = getUser().findSubscription(host);
+ return subscription;
+ }
+
+ /**
+ * <p>Obtain uSER Support for the local Host property.</p>
+ * <p/>
+ * <p>Usually, the host property will be set from the client request,
+ * because it was embedded in a link to the Subcription action.
+ *
+ * @return Support or null if not found
+ */
+ public Subscription findSubscription() {
+ return findSubscription(getHost());
+ }
+
+ /**
+ * <p>Provide a "temporary" User Support object that can be used to
+ * capture input values.</p>
+ */
+ public void createInputSubscription() {
+ Subscription sub = new MemorySubscription(getUser(), null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+
+ /**
+ * <p>Provide new User Support object for the given host, or null if
+ * the host is not unique.</p>
+ *
+ * @param host
+ * @return New User Support object or null
+ */
+ public Subscription createSubscription(String host) {
+
+ Subscription sub;
+
+ sub = findSubscription(host);
+
+ if (null != sub) {
+ // FIXME - localization - "error.host.unique")
+ addFieldError(Constants.HOST, "That hostname is already defined");
+ return null;
+ }
+
+ return getUser().createSubscription(host);
+ }
+
+ /**
+ * <p>Create a new Support from the current Support object,
+ * making the new Support the current Support. </p>
+ * <p/>
+ * <p>Usually, the "current" Support is a temporary object being used
+ * to capture input values.</p>
+ *
+ * @param host
+ */
+ public void copySubscription(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ BeanUtils.setValues(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }
+
+ /**
+ * <p>Delete the current Support object from the database.</p>
+ */
+ public void removeSubscription() {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(Constants.SUBSCRIPTION_KEY);
+ }
+
+ /**
+ * <p>Provide MailServer Host for current User Support.</p>
+ *
+ * @return MailServer Host for current User Support
+ */
+ public String getSubscriptionHost() {
+ Subscription sub = getSubscription();
+ if (null == sub) {
+ return null;
+ }
+ return sub.getHost();
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/MainMenu.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/MainMenu.java
new file mode 100644
index 0000000..dfa5e6c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/MainMenu.java
@@ -0,0 +1,9 @@
+package mailreader2;
+
+/**
+ * <p>
+ * Provide access to MailreaderSupport properties.
+ * </p>
+ */
+public class MainMenu extends MailreaderSupport {
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Welcome-action.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Welcome-action.xml
new file mode 100644
index 0000000..8577d07
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Welcome-action.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <package name="Welcome" namespace="/" extends="MailreaderSupport">
+
+ <action name="Welcome" class="mailreader2.Welcome">
+ <result>/pages/Welcome.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Welcome.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Welcome.java
new file mode 100644
index 0000000..ce54263
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/Welcome.java
@@ -0,0 +1,31 @@
+package mailreader2;
+
+import com.opensymphony.xwork2.Preparable;
+import com.opensymphony.xwork2.ModelDriven;
+import java.util.List;
+
+/**
+ * Verify that essential resources are available.
+ */
+public class Welcome extends MailreaderSupport {
+
+ public String execute() {
+
+ // Confirm message resources loaded
+ String message = getText(Constants.ERROR_DATABASE_MISSING);
+ if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
+ addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);
+ }
+
+ // Confirm database loaded
+ if (null == getDatabase()) {
+ addActionError(Constants.ERROR_DATABASE_NOT_LOADED);
+ }
+
+ if (hasErrors()) {
+ return ERROR;
+ } else {
+ return SUCCESS;
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Input.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Input.java
new file mode 100644
index 0000000..597bfaa
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Input.java
@@ -0,0 +1,9 @@
+package mailreader2.logon;
+
+import mailreader2.MailreaderSupport;
+
+/**
+ * <p>Stub class for login/Input.</p>
+ */
+public class Input extends MailreaderSupport {
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Retrieve-validation.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Retrieve-validation.xml
new file mode 100644
index 0000000..4a04c76
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Retrieve-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Retrieve.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Retrieve.java
new file mode 100644
index 0000000..b8d78ec
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/logon/Retrieve.java
@@ -0,0 +1,46 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2.logon;
+
+import mailreader2.MailreaderSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+/**
+ * <p> Validate a user logon. </p>
+ */
+public final class Retrieve extends MailreaderSupport {
+
+ public String execute() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Create-validation.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Create-validation.xml
new file mode 100644
index 0000000..ccf277b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Create-validation.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="errors.range"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.match"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Create.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Create.java
new file mode 100644
index 0000000..53fdad9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Create.java
@@ -0,0 +1,37 @@
+package mailreader2.registration;
+
+import mailreader2.Constants;
+import org.apache.struts.apps.mailreader.dao.User;
+
+/**
+ * <p>Insert new user, providing extra validation.</p>
+ * <p/>
+ * <p>(On an update, the password change is optional.)</p>
+ */
+public final class Create extends Update {
+
+ public String execute()
+ throws Exception {
+
+ // trust but verify
+ boolean creating = Constants.CREATE.equals(getTask());
+ creating = creating && isCreating();
+ if (!creating) {
+ addActionError("registration/Create: ");
+ addActionError(Constants.ERROR_INVALID_WORKFLOW);
+ return ERROR;
+ }
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText("error.username.unique"));
+ return INPUT;
+ }
+
+ copyUser(getUsername(), getPassword());
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Input.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Input.java
new file mode 100644
index 0000000..a034366
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Input.java
@@ -0,0 +1,31 @@
+package mailreader2.registration;
+
+import mailreader2.Constants;
+
+/**
+ * <p> Retrieve User object to edit or null if User does not exist. </p>
+ */
+public class Input extends Support {
+
+ /**
+ * <p> Retrieve User object to edit or null if User does not exist. </p>
+ *
+ * @return The "Success" result for this mapping
+ * @throws Exception on any error
+ */
+ public String execute() throws Exception {
+
+ if (isCreating()) {
+ createInputUser();
+ setTask(Constants.CREATE);
+ } else {
+ setTask(Constants.EDIT);
+ setUsername(getUser().getUsername());
+ setPassword(getUser().getPassword());
+ setPassword2(getUser().getPassword());
+ }
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Support.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Support.java
new file mode 100644
index 0000000..0316314
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Support.java
@@ -0,0 +1,20 @@
+package mailreader2.registration;
+
+import mailreader2.MailreaderSupport;
+import org.apache.struts.apps.mailreader.dao.User;
+
+/**
+ * <p>Base class to store shared methods.</p>
+ */
+public class Support extends MailreaderSupport {
+
+ /**
+ * <p>Double check that there is not a valid User logon. </p>
+ *
+ * @return True if there is not a valid User logon
+ */
+ protected boolean isCreating() {
+ User user = getUser();
+ return (null == user) || (null == user.getDatabase());
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Update-validation.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Update-validation.xml
new file mode 100644
index 0000000..44d66bc
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Update-validation.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="user.fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="user.fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+ <field name="user.replyToAddress">
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Update.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Update.java
new file mode 100644
index 0000000..77c19b2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/registration/Update.java
@@ -0,0 +1,48 @@
+package mailreader2.registration;
+
+import mailreader2.Constants;
+
+/**
+ * <p> Update a User object to the persistent store. </p>
+ */
+public class Update extends Support {
+
+
+
+
+ private String fixNull(String value) {
+ if (value == null) return null;
+ String buffer = value.trim();
+ if (buffer.length() == 0) return null;
+ return buffer;
+ }
+
+ public String execute()
+ throws Exception {
+
+ boolean creating = Constants.CREATE.equals(getTask());
+ creating = creating && isCreating(); // trust but verify
+ if (creating) {
+ addActionError("registration/Update: ");
+ addActionError(Constants.ERROR_INVALID_WORKFLOW);
+ return ERROR;
+ }
+ // FIXME: Any way to call the RegisrationSave validators from here?
+ String newPassword = fixNull(getPassword());
+ String confirmPassword = fixNull(getPassword2());
+ if (newPassword != null) {
+ boolean matches = ((confirmPassword != null)
+ && (confirmPassword.equals(newPassword)));
+ if (matches) {
+ getUser().setPassword(newPassword);
+ } else {
+ addActionError(getText("error.password.match"));
+ return INPUT;
+ }
+ }
+
+ saveUser();
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Delete.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Delete.java
new file mode 100644
index 0000000..893916f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Delete.java
@@ -0,0 +1,15 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p>Prepare to present a confirmation page before removing
+ * subscription.</p>
+ */
+public class Delete extends Edit {
+
+ public String execute() throws Exception {
+ setTask(Constants.DELETE);
+ return find();
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Edit-validation.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Edit-validation.xml
new file mode 100644
index 0000000..df903c2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Edit-validation.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="host">
+ <field-validator type="requiredstring">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Edit.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Edit.java
new file mode 100644
index 0000000..1baf3f9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Edit.java
@@ -0,0 +1,16 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p>Prepare to edit User Support.</p>
+ */
+public class Edit extends Support {
+
+ public String execute() throws Exception {
+ setTask(Constants.EDIT);
+ return find();
+ }
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Input.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Input.java
new file mode 100644
index 0000000..2053dd6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Input.java
@@ -0,0 +1,17 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p>Setup a temporary User Support object to capture input
+ * values.</p>
+ */
+public class Input extends Support {
+
+ public String execute() {
+ createInputSubscription();
+ setTask(Constants.CREATE);
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Save-validation.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Save-validation.xml
new file mode 100644
index 0000000..9f2f6d7
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Save-validation.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="subscription.username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.type">
+ <field-validator type="requiredstring">
+ <message key="error.type.invalid"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Save.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Save.java
new file mode 100644
index 0000000..e24e530
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Save.java
@@ -0,0 +1,38 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p> Workaround class. Submitting to an alias doesn't seem to work. </p>
+ */
+public final class Save extends Edit {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ getSubscription().setAutoConnect(false);
+ }
+
+ /**
+ * <p> Examine the Task property and DELETE, CREATE, or save the User
+ * Support, as appropriate. </p>
+ *
+ * @return SUCCESS
+ * @throws Exception on a database error
+ */
+ public String execute() throws Exception {
+
+ if (Constants.DELETE.equals(getTask())) {
+ removeSubscription();
+ }
+
+ if (Constants.CREATE.equals(getTask())) {
+ copySubscription(getHost());
+ }
+
+ if (hasErrors()) return INPUT;
+
+ saveUser();
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Support.java b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Support.java
new file mode 100644
index 0000000..172f264
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/java/mailreader2/subscription/Support.java
@@ -0,0 +1,69 @@
+package mailreader2.subscription;
+
+import com.opensymphony.xwork2.Preparable;
+import mailreader2.MailreaderSupport;
+import mailreader2.Constants;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * <p> Provide an Edit method for retrieving an existing subscription, and a
+ * Save method for updating or inserting a subscription. </p>
+ */
+public class Support extends MailreaderSupport
+ implements Preparable {
+
+ /**
+ * <p>Field to store list of MailServer types</p>
+ */
+ private Map types = null;
+
+ /**
+ * <p>Provide the list of MailServer types.</p>
+ *
+ * @return List of MailServer types
+ */
+ public Map getTypes() {
+ return types;
+ }
+
+ /**
+ * <p>Setup the MailerServer types and set the local Host property from
+ * the User Support (if any). </p>
+ */
+ public void prepare() {
+
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+
+ setHost(getSubscriptionHost());
+
+ }
+
+ /**
+ * <p>Load User Support for the local Host property.</p>
+ * <p/>
+ * <p>Usually, the Host is being set from the request by a link to an Edit
+ * or Delete task.</p>
+ *
+ * @return INPUT or Error, if Support is not found
+ */
+ public String find() {
+
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+
+ if (sub == null) {
+ addActionError("find (Subscription): ");
+ addActionError(Constants.ERROR_INVALID_WORKFLOW);
+ return ERROR;
+ }
+
+ setSubscription(sub);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/alternate.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/alternate.properties
new file mode 100644
index 0000000..45f4dd5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/alternate.properties
@@ -0,0 +1,3 @@
+password=Enter your Password here ==>
+struts.logo.path=/struts-power.gif
+struts.logo.alt=Powered by Struts
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/alternate_ja.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/alternate_ja.properties
new file mode 100644
index 0000000..981adc8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/alternate_ja.properties
@@ -0,0 +1 @@
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b==>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/applicationContext.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..b98e1d8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/applicationContext.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans default-autowire="autodetect">
+ <!-- add your spring beans here -->
+</beans>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/database.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources.properties
new file mode 100644
index 0000000..dbfae81
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources.properties
@@ -0,0 +1,93 @@
+button.cancel=Cancel
+button.confirm=Confirm
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+button.reset=Reset
+button.save=Save
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+error.database.missing=User database is missing, cannot validate logon credentials
+error.fromAddress.format=Invalid format for From Address
+error.fromAddress.required=From Address is required
+error.fullName.required=Full Name is required
+error.host.required=Mail Server is required
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+error.password.mismatch=Invalid username and/or password, please try again
+error.replyToAddress.format=Invalid format for Reply To Address
+struts.messages.invalid.token=Cannot submit this form out of order
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+error.username.required=Username is required
+error.username.unique=That username is already in use - please select another
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.logon=Log on to the MailReader Demonstration Application
+index.registration=Register with the MailReader Demonstration Application
+index.title=MailReader Demonstration Application
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+logon.title=MailReader Demonstration Application - Logon
+mainMenu.heading=Main Menu Options for
+mainMenu.logoff=Log off MailReader Demonstration Application
+mainMenu.registration=Edit your user registration profile
+mainMenu.title=MailReader Demonstration Application - Main Menu
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+fromAddress=From Address
+fullName=Full Name
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+password=Password
+password2=(Repeat) Password
+replyToAddress=Reply To Address
+username=Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+registration.title.create=Register for the MailReader Demonstration Application
+registration.title.edit=Edit Registration for the MailReader Demonstration Application
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources_ja.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources_ja.properties
new file mode 100644
index 0000000..dc0ca7d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.logon=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+logon.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+mainMenu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+mainMenu.logoff=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+mainMenu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+mainMenu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources_ru.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources_ru.properties
new file mode 100644
index 0000000..ef8c820
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/resources_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.logon=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+logon.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+mainMenu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+mainMenu.logoff=\u0412\u044b\u0439\u0442\u0438
+mainMenu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql-map-config.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql-map-config.xml
new file mode 100644
index 0000000..3944151
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql-map-config.xml
@@ -0,0 +1,25 @@
+<!DOCTYPE sqlMapConfig PUBLIC
+ "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
+ "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
+
+<sqlMapConfig>
+
+ <properties resource="sql/sql-map-config-hsql.properties"/>
+
+ <settings cacheModelsEnabled="true" enhancementEnabled="false"
+ maxSessions="64" maxTransactions="8" maxRequests="128"/>
+
+ <transactionManager type="JDBC">
+ <dataSource type="SIMPLE">
+ <property value="${driver}" name="JDBC.Driver"/>
+ <property value="${url}" name="JDBC.ConnectionURL"/>
+ <property value="${username}" name="JDBC.Username"/>
+ <property value="${password}" name="JDBC.Password"/>
+ <property value="15" name="Pool.MaximumActiveConnections"/>
+ <property value="15" name="Pool.MaximumIdleConnections"/>
+ <property value="1000" name="Pool.MaximumWait"/>
+ </dataSource>
+ </transactionManager>
+
+ <sqlMap resource="sql/sql-map.xml"/>
+</sqlMapConfig>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/mailreader-schema.sql b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/mailreader-schema.sql
new file mode 100644
index 0000000..9b86c86
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/mailreader-schema.sql
@@ -0,0 +1,35 @@
+CREATE TABLE locale
+(
+ pk_locale char(36),
+ locale_code char(9),
+ locale_name char(36)
+);
+
+CREATE TABLE registration
+(
+ pk_registration char(36),
+ fk_locale char(36),
+ username char(18),
+ password char(18),
+ fullname varchar(36),
+ email_from varchar(72),
+ email_replyto varchar(72)
+);
+
+CREATE TABLE protocol
+(
+ pk_protocol char(36),
+ protocol_code char(9),
+ protocol_name char(36)
+);
+
+CREATE TABLE subscription
+(
+ pk_subscription char(36),
+ fk_registration char(36),
+ fk_protocol char(36),
+ subscription_host char(36),
+ host_user char(18),
+ host_pass char(18),
+ host_auto int
+);
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map-config-derby.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map-config-derby.properties
new file mode 100644
index 0000000..7ef45fa
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map-config-derby.properties
@@ -0,0 +1,12 @@
+##############################################################
+# Database Connectivity Properties
+# (derby - http://db.apache.org/derby/)
+##############################################################
+
+driver=org.apache.derby.jdbc.EmbeddedDriver
+url=jdbc:derby:mailreader;create=true
+username=
+password=
+SqlMapPath=mailreader2
+dataSourceType=SIMPLE
+
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map-config-hsql.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map-config-hsql.properties
new file mode 100644
index 0000000..2f0d141
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map-config-hsql.properties
@@ -0,0 +1,9 @@
+##############################################################
+# Database Connectivity Properties
+# (HSQL - http://hsql.org/)
+##############################################################
+
+driver=org.hsqldb.jdbcDriver
+url=jdbc:hsqldb:mem:mailreader
+username=sa
+password=
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map.xml
new file mode 100644
index 0000000..a821d4d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/sql/sql-map.xml
@@ -0,0 +1,89 @@
+<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
+ "http://ibatis.apache.org/dtd/sql-map-2.dtd">
+
+<sqlMap namespace="mailreader">
+
+ <typeAlias alias="data"
+ type="mailreader2.AppData"/>
+
+ <select id="LOCALE_LIST" resultClass="data">
+ SELECT pk_locale AS locale_key, locale_code, locale_name
+ FROM locale;
+ </select>
+
+ <select id="REGISTRATION_INSERT_ASSERT" parameterClass="data" resultClass="long">
+ SELECT COUNT(*)
+ FROM registration
+ WHERE username=#username#;
+ </select>
+
+ <insert id="REGISTRATION_INSERT" parameterClass="data">
+ INSERT INTO registration
+ (pk_registration, fk_locale, username, password, fullname, email_from, email_replyto)
+ VALUES (#registration_key#, #locale_key#, #username#, #password#, #fullname#, #email_from#, #email_replyto#);
+ </insert>
+
+ <select id="REGISTRATION_PASSWORD" parameterClass="data" resultClass="data">
+ SELECT username, password
+ FROM registration
+ WHERE username=#username#;
+ </select>
+
+ <select id="REGISTRATION_FULLNAME" parameterClass="data" resultClass="data">
+ SELECT username, fullname
+ FROM registration
+ WHERE username=#username#;
+ </select>
+
+ <select id="REGISTRATION_EDIT" parameterClass="data" resultClass="data">
+ SELECT pk_registration AS registration_key, fk_locale AS locale_key,
+ username, password, fullname, email_from, email_replyto
+ FROM registration
+ WHERE pk_registration=#registration_key#;
+ </select>
+
+ <update id="REGISTRATION_UPDATE" parameterClass="data">
+ UPDATE registration
+ SET fk_locale=#locale_key#, username=#username#, password=#password#, fullname=#fullname#,
+ email_from=#email_from#, email_replyto=#email_replyto#
+ WHERE pk_registration=#registration_key#;
+ </update>
+
+ <select id="SUBSCRIPTION_INSERT_ASSERT" parameterClass="data" resultClass="long">
+ SELECT COUNT(*)
+ FROM subscription
+ WHERE fk_registration=#registration_key#
+ AND subscription_host=#subscription_host#;
+ </select>
+
+ <insert id="SUBSCRIPTION_INSERT" parameterClass="data">
+ INSERT INTO subscription
+ (pk_subscription, fk_registration, fk_protocol, subscription_host, host_user, host_pass, host_auto)
+ VALUES (#subscription_key#, #registration_key#, #protocol_key#, #subscription_host#,
+ #host_user#, #host_pass#, #host_auto#);
+ </insert>
+
+ <select id="SUBSCRIPTION_LIST" parameterClass="data" resultClass="data">
+ SELECT pk_subscription AS subscription_key,
+ subscription_host, host_user, host_pass, host_auto, protocol_name
+ FROM subscription
+ JOIN protocol ON pk_protocol=fk_protocol
+ WHERE fk_registration=#registration_key#;
+ </select>
+
+ <select id="SUBSCRIPTION_EDIT" parameterClass="data" resultClass="data">
+ SELECT pk_subscription AS subscription_key, fk_protocol AS protocol_key,
+ subscription_host, host_user, host_pass, host_auto, protocol_name
+ FROM subscription
+ JOIN protocol ON pk_protocol=fk_protocol
+ WHERE pk_subscription=#subscription_key#;
+ </select>
+
+ <update id="SUBSCRIPTION_UPDATE" parameterClass="data">
+ UPDATE subscription
+ SET fk_registration=#registration_key#, fk_protocol=#protocol_key#,
+ subscription_host=#subscription_host#, host_user=#host_user#, host_pass=#host_pass#, host_auto=#host_auto#
+ WHERE pk_subscription=#subscription_key#;
+ </update>
+
+</sqlMap>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/struts.properties b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/struts.properties
new file mode 100644
index 0000000..b041cee
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/struts.properties
@@ -0,0 +1,4 @@
+struts.objectFactory = spring
+struts.devMode = true
+struts.custom.i18n.resources = resources
+struts.enable.DynamicMethodInvocation = false
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/struts.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/struts.xml
new file mode 100644
index 0000000..89e3753
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/resources/struts.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <include file="struts-default.xml"/>
+
+ <package name="default" namespace="" extends="struts-default">
+
+ <global-results>
+ <result name="error">/pages/Error.jsp</result>
+ <result name="invalid.token">/pages/Error.jsp</result>
+ <result name="success" type="redirect-action">MainMenu</result>
+ <result name="expired" type="chain">ChangePassword</result>
+ </global-results>
+
+ <global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Throwable"/>
+ <exception-mapping
+ exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
+ result="expired"/>
+ </global-exception-mappings>
+
+ <!-- goto actions: Exit to another workflow -->
+
+ <action name="subscription/Save" class="mailreader2.subscription.Save">
+ <result name="input">/pages/subscription.jsp</result>
+ <result type="redirect-action">registration/vInput</result>
+ </action>
+
+ <!-- prepare actions: Confirm/Delete, Edit, Input -->
+ <!-- A "!" might be a better convention,
+ but that doesn't seem to work with a button -->
+
+ <action name="*/v*" class="mailreader2.{1}.{2}">
+ <result>/pages/{1}.jsp</result>
+ </action>
+
+ <!-- execute actions: Create, Retrieve, Update, Save -->
+
+ <action name="*/*" class="mailreader2.{1}.{2}">
+ <result name="input">/pages/{1}.jsp</result>
+ </action>
+
+ <!-- Why doen't these match * -->
+ <!-- It seems to be concaternating a period to the token -->
+ <!-- Unable to instantiate Action, mailreader2.Welcome.,
+ defined for 'Welcome' in namespace '/'mailreader2.Welcome. -->
+ <action name="Logoff" class="mailreader2.Logoff">
+ <result>/pages/Logoff.jsp</result>
+ </action>
+
+ <action name="MainMenu" class="mailreader2.MainMenu">
+ <result>/pages/MainMenu.jsp</result>
+ </action>
+
+ <action name="Welcome" class="mailreader2.Welcome">
+ <result>/pages/Welcome.jsp</result>
+ </action>
+
+ <!-- display actions: Welcome, Logoff, MainMenu -->
+
+ <action name="*" class="mailreader2.{1}">
+ <result>/pages/{1}.jsp</result>
+ </action>
+
+ </package>
+
+</struts>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/META-INF/context.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/WEB-INF/web.xml b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..758310a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath*:applicationContext*.xml</param-value>
+ </context-param>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ mailreader2.ApplicationListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/css/mailreader.css b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/css/mailreader.css
new file mode 100644
index 0000000..bfc7648
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/css/mailreader.css
@@ -0,0 +1,46 @@
+/**
+* Mailreader stylesheet
+*/
+
+body {
+ background-color: #FFFFFF;
+ color: #000000;
+ link: 000066;
+ visited: #660066;
+ active: #33CCCC;
+}
+
+A:hover {
+ color: #FF0000;
+}
+
+h1 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h5 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h6 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+font.hint {
+ font-style: italic;
+ font-size: 80%;
+ font-family: Arial, Helvetica, sans-serif;
+ text-align: left;
+}
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/index.html b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/ChangePassword.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/ChangePassword.jsp
new file mode 100644
index 0000000..37d85be
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/ChangePassword.jsp
@@ -0,0 +1,25 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="change.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+
+<p>
+ <s:text name="change.message"/>
+</p>
+
+<p>
+ <a href="<s:url action="Logon"/>">
+ <s:text name="change.try"/>
+ </a>
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Error.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Error.jsp
new file mode 100644
index 0000000..481eddb
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Error.jsp
@@ -0,0 +1,40 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Unexpected Error</title>
+</head>
+
+<body>
+<h2>An unexpected error has occured</h2>
+
+<p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+</p>
+
+<hr/>
+
+<h3>Error Message</h3>
+
+<s:actionerror/>
+
+<p>
+ <s:property value="%{exception.message}"/>
+</p>
+
+<hr/>
+
+<h3>Technical Details</h3>
+
+<p>
+ <s:property value="%{exceptionStack}"/>
+</p>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Footer.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Footer.jsp
new file mode 100644
index 0000000..b2eae1e
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Footer.jsp
@@ -0,0 +1,6 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<hr/>
+
+<p>
+ <a href="<s:url action="Welcome" />"><s:text name="index.title"/></a>
+</p>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Logoff.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Logoff.jsp
new file mode 100644
index 0000000..8928aea
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Logoff.jsp
@@ -0,0 +1 @@
+<% response.sendRedirect("Welcome.action"); %>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/MainMenu.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/MainMenu.jsp
new file mode 100644
index 0000000..0cd89e5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/MainMenu.jsp
@@ -0,0 +1,33 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="mainMenu.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h3><s:text name="mainMenu.heading"/> <s:property
+ value="user.fullName"/></h3>
+<ul>
+ <li>
+ <s:url id="Input" action="registration/vInput" />
+ <s:a href="%{Input}">
+ <s:text name="mainMenu.registration"/>
+ </s:a>
+ </li>
+ <li>
+ <s:url id="Logoff" action="Logoff"/>
+ <s:a href="%{Logoff}">
+ <s:text name="mainMenu.logoff"/>
+ </s:a>
+ </li>
+</ul>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Welcome.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..89347df
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/Welcome.jsp
@@ -0,0 +1,64 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><s:text name="index.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h3><s:text name="index.heading"/></h3>
+
+<ul>
+ <li>
+ <s:url id="registration" action="registration/vInput" />
+ <s:a href="%{registration}"><s:text name="index.registration"/></s:a>
+ </li>
+ <li>
+ <s:url id="logon" action="logon/vInput"/>
+ <s:a href="%{logon}"><s:text name="index.logon"/></s:a>
+ </li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li>
+ <s:url id="en" action="Welcome">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="ja" action="Welcome">
+ <s:param name="request_locale">ja</s:param>
+ </s:url>
+ <s:a href="%{ja}">Japanese</s:a>
+ </li>
+ <li>
+ <s:url id="ru" action="Welcome">
+ <s:param name="request_locale">ru</s:param>
+ </s:url>
+ <s:a href="%{ru}">Russian</s:a>
+ </li>
+</ul>
+
+<hr/>
+
+<p>
+ <s:i18n name="alternate">
+ <img src="<s:text name="struts.logo.path"/>"
+ alt="<s:text name="struts.logo.alt"/>"/>
+ </s:i18n>
+</p>
+
+<p>
+ <s:url id="Tour" action="Tour"/><s:a href="%{Tour}"><s:text name="index.tour"/></s:a>
+</p>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/logon.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/logon.jsp
new file mode 100644
index 0000000..92bbae4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/logon.jsp
@@ -0,0 +1,30 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.Retrieve.username.focus()">
+
+<s:actionerror/>
+<s:form id="Retrieve" action="logon/Retrieve" validate="true">
+ <s:textfield label="%{getText('username')}" name="username"/>
+
+ <s:password label="%{getText('password')}" name="password" showPassword="true"/>
+
+ <s:submit value="%{getText('button.save')}"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Welcome" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="Footer.jsp"/>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/registration.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/registration.jsp
new file mode 100644
index 0000000..79c2c16
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/registration.jsp
@@ -0,0 +1,130 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title><s:text name="registration.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="registration.title.edit"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.form1.username.focus()">
+
+<s:actionerror/>
+<s:form id="form1" action="registration/Update" validate="true">
+ <s:token/>
+ <s:hidden name="task"/>
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('username')}" name="username"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('username')}" name="username"/>
+ <s:hidden name="username"/>
+ </s:else>
+
+ <s:password label="%{getText('password')}" name="password"/>
+
+ <s:password label="%{getText('password2')}" name="password2"/>
+
+ <s:textfield label="%{getText('fullName')}"
+ name="user.fullName"/>
+
+ <s:textfield label="%{getText('fromAddress')}"
+ name="user.fromAddress"/>
+
+ <s:textfield label="%{getText('replyToAddress')}"
+ name="user.replyToAddress"/>
+
+ <s:if test="task == 'Create'">
+ <s:submit value="%{getText('button.save')}" action="registration/Create"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Welcome" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+ </s:if>
+ <s:else>
+ <s:submit value="%{getText('button.save')}"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit value="%{getText('button.cancel')}"
+ action="MainMenu" onclick="form.onsubmit=null"/>
+ </s:else>
+
+</s:form>
+
+<s:if test="task == 'Edit'">
+ <div align="center">
+ <h3><s:text name="heading.subscriptions"/></h3>
+ </div>
+
+ <table border="1" width="100%">
+
+ <tr>
+ <th align="center" width="30%">
+ <s:text name="heading.host"/>
+ </th>
+ <th align="center" width="25%">
+ <s:text name="heading.user"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.type"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.autoConnect"/>
+ </th>
+ <th align="center" width="15%">
+ <s:text name="heading.action"/>
+ </th>
+ </tr>
+
+ <s:iterator value="user.subscriptions">
+ <tr>
+ <td align="left">
+ <s:property value="host"/>
+ </td>
+ <td align="left">
+ <s:property value="username"/>
+ </td>
+ <td align="center">
+ <s:property value="type"/>
+ </td>
+ <td align="center">
+ <s:property value="autoConnect"/>
+ </td>
+ <td align="center">
+ <s:url id="Delete" action="subscription/vDelete" >
+ <s:param name="host" value="host"/>
+ </s:url>
+ <s:a href="%{Delete}">
+ <s:text name="registration.deleteSubscription"/>
+ </s:a>
+
+ <s:url id="Edit" action="subscription/vEdit">
+ <s:param name="host" value="host"/>
+ </s:url>
+ <s:a href="%{Edit}">
+ <s:text name="registration.editSubscription"/>
+ </s:a>
+ </td>
+ </tr>
+ </s:iterator>
+
+ </table>
+
+ <s:url id="Input" action="subscription/vInput" />
+ <s:a href="%{Input}"><s:text name="registration.addSubscription"/></s:a>
+
+</s:if>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/registration/Retrieve.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/registration/Retrieve.jsp
new file mode 100644
index 0000000..6595226
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/registration/Retrieve.jsp
@@ -0,0 +1,31 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.registration/Retrieve.username.focus()">
+
+<s:actionerror/>
+<s:url id="Retrieve" action="registration/Retrieve" />
+<s:form action="registration/Retrieve" validate="true">
+ <s:textfield label="%{getText('username')}" name="username"/>
+
+ <s:password label="%{getText('password')}" name="password" showPassword="true"/>
+
+ <s:submit value="%{getText('button.save')}"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Welcome" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="../Footer.jsp"/>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/subscription.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/subscription.jsp
new file mode 100644
index 0000000..bf4c9a4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/subscription.jsp
@@ -0,0 +1,68 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title><s:text name="subscription.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="subscription.title.edit"/></title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title><s:text name="subscription.title.delete"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.form1.username.focus()">
+
+<s:actionerror/>
+<s:form id="form1" action="subscription/Save" validate="true">
+ <s:token/>
+ <s:hidden name="task"/>
+ <s:label label="%{getText('username')}" name="user.username"/>
+
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('mailHostname')}" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('mailHostname')}" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:label label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:label label="%{getText('mailServerType')}"
+ name="subscription.type"/>
+ <s:label label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.confirm')}"/>
+ </s:if>
+ <s:else>
+ <s:textfield label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:textfield label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:select label="%{getText('mailServerType')}"
+ name="subscription.type" list="types"/>
+ <s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.save')}"/>
+ <s:reset value="%{getText('button.reset')}"/>
+ </s:else>
+
+ <s:submit action="registration/vInput"
+ value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/tour.jsp b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/tour.jsp
new file mode 100644
index 0000000..a6ceb46
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/pages/tour.jsp
@@ -0,0 +1,2431 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"/>
+ <link rel="stylesheet" type="text/css" href="../css/mailreader.css"/>
+
+ <title>A Walking Tour of the Struts 2 MailReader Application</title>
+</head>
+
+<body>
+<blockquote>
+<h2>A Walking Tour of the Struts 2 MailReader Application</h2>
+
+<p>
+ <i>
+ This article is meant to introduce a new user to Apache Struts 2 by
+ "walking through" a simple, but functional, application.
+ The article includes code snippets, but for the best result, you might
+ want to install the MailReader application on your own development
+ workstation and follow along.
+ Of course, the full source code to the MailReader is included in the
+ distribution.
+ </i>
+
+</p>
+
+<p>
+ <i>
+ The tour assumes the reader has a basic understanding of the Java
+ language, JavaBeans, web applications, and JavaServer Pages. For
+ background on these technologies, see the
+ <a href="http://struts.apache.org/primer.html">
+ Key Technologies Primer</a>.
+ </i>
+</p>
+
+<hr/>
+
+<p>Logging In</p>
+
+<ul>
+ <li>
+ <a href="#Welcome">Welcome</a>
+
+ <ul>
+ <li><a href="#web.xml">web.xml and resources.properties</a></li>
+
+ <li><a href="#Welcome.do">Welcome.do</a></li>
+
+ <li><a href="#Welcome.java">Welcome Action</a></li>
+
+ <li><a href="#global-results">Global Results</a></li>
+
+ <li><a href="#ApplicationListener.java">ApplicationListener.java</a></li>
+
+ <li><a href="#resources.properties">Message Resources</a></li>
+
+ <li><a href="#Welcome.jsp">Welcome Page</a></li>
+
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Logon">Logon</a>
+ <ul>
+
+ <li><a href="#Logon.jsp">Logon Page</a></li>
+
+ <li><a href="#Logon-validation.xml">Logon-validation.xml</a></li>
+
+ <li><a href="#Logon.java">Logon.java</a></li>
+
+ <li><a href="#MailreaderSupport.java">MailreaderSupport.java</a></li>
+
+ <li><a href="#Logon.xml">Logon Configuration</a></li>
+
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#MainMenu">MainMenu</a>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Registration.jsp">Registration page</a>
+ <ul>
+ <li><a href="#iterator">iterator</a></li>
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Subscription">Subscription</a>
+
+ <ul>
+ <li><a href="#SubscriptionAction.java">Subscription.java</a>
+ </li>
+ </ul>
+ </li>
+</ul>
+<hr/>
+
+<p>
+ The premise of the MailReader is that it is the first iteration of a
+ portal application.
+ This version allows users to register and maintain a set of
+ accounts with various mail servers.
+ If completed, the application would let users read mail from their
+ accounts.
+</p>
+
+<p>
+ The MailReader application demonstrates registering with an application,
+ logging into an application, maintaining a master record, and maintaining
+ child records.
+ This article overviews the constructs needed to do these things,
+ including the server pages, Java classes, and configuration elements.
+</p>
+
+<p>
+ For more about the MailReader, including alternate implementations and a
+ set of formal Use Cases,
+ please visit the <a href="http://www.StrutsUniversity.org/MailReader">
+ Struts University MailReader site</a>.
+</p>
+
+<hr/>
+<blockquote>
+ <p><font class="hint">
+ <strong>JAAS</strong> -
+ Note that for compatibility and ease of deployment, the MailReader
+ uses "application-based" authorization.
+ However, use of the standard Java Authentication and Authorization
+ Service (JAAS) is recommended for most applications.
+ (See the <a
+ href="http://struts.apache.org/primer.html">
+ Key Technologies Primer</a> for more about
+ authentication technologies.)
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The tour starts with how the initial welcome page is displayed, and
+ then steps through logging into the application and editing a subscription.
+ Please note that this not a quick peek at a "Hello World" application.
+ The tour is a rich trek into a realistic, best practices application.
+ You may need to adjust your chair and get a fresh cup of coffee.
+ Printed, the article is 29 pages long (US).
+</p>
+
+<h3><a name="Welcome" id="Welcome">Welcome Page</a></h3>
+
+<p>
+ A web application, like any other web site, can specify a list of welcome pages.
+ When you open a web application without specifying a particular page, a
+ default "welcome page" is served as the response.
+</p>
+
+<h4><a name="web.xml" id="web.xml">web.xml</a></h4>
+
+<p>
+ When a web application loads,
+ the container reads and parses the "Web Application Deployment
+ Descriptor", or "web.xml" file.
+ The framework plugs into a web application via a servlet filter.
+ Like any filter, the "struts2" filter is deployed via the "web.xml".
+</p>
+
+<hr/>
+<h5>web.xml - The Web Application Deployment Descriptor</h5>
+<pre><code><?xml version="1.0" encoding="ISO-8859-1"?>
+ <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+ <web-app>
+
+ <display-name>Struts 2 MailReader</display-name>
+
+ <strong><filter>
+ <filter-name>struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter></strong>
+
+ <filter-mapping>
+ <filter-name><strong>struts2</strong></filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <!-- Application Listener for MailReader database -->
+ <listener>
+ <listener-class>
+ mailreader2.ApplicationListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ </web-app></code></pre>
+<hr/>
+
+<p>
+ Among other things,
+ the web.xml specifies the "Welcome File List" for an application.
+ When a web address refers to a directory rather than an individual file,
+ the container consults the Welcome File List for the name of a page to
+ open by default.
+</p>
+
+<p>
+ However, most Struts applications do not refer to physical pages,
+ but to "virtual resources" called <i>actions</i>.
+ Actions specify code that we want to be run before a page
+ or other resource renders the response.
+ An accepted practice is to never link directly to server pages,
+ but only to logical action mappings.
+ By linking to actions, developers can often "rewire" an application
+ without editing the server pages.
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Link actions not pages."</font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The actions are listed in one or more XML configuration files,
+ the default configuration file being named "struts.xml".
+ When the application loads, the struts.xml, and any other files
+ it includes, are parsed, and the framework creates a set of
+ configuration objects.
+ Among other things, the configuration maps a request for a certain
+ page to a certain action mapping.
+</p>
+
+<p>
+ Sites can list zero or more "Welcome" pages in the web.xml.
+ Unless you are using Java 1.5, actions cannot be specified as a Welcome
+ page.
+ So, in the case of a Welcome page,
+ how do we follow the best practice of navigating through actions
+ rather than pages?
+</p>
+
+<p>
+ One solution is to use a page to "bootstrap" one of our actions.
+ We can register the usual "index.html" as the Welcome page and have it
+ redirect to a "Welcome" action.
+</p>
+
+<hr/>
+<h5>MailReader's index.html</h5>
+<pre><code><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+ <html><head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;<strong>URL=Welcome.do</strong>">
+ </head>
+ <body>
+ <p>Loading ...</p>
+ </body></html></code></pre>
+<hr/>
+
+<p>
+ As an alternative,
+ we could also have used a JSP page that issued the redirect with a Struts tag,
+ but a plain HTML solution works as well.
+</p>
+
+<h4><a name="Welcome.do" id="Welcome.do">Welcome.do</a></h4>
+
+<p>
+ When the client requests "Welcome.do", the request is passed to the "struts2" FilterDispatcher
+ (that we registered in the web.xml file).
+ The FilterDispatcher retrieves the appropriate action mapping from the
+ configuration.
+ If we just wanted to forward to the Welcome page, we could use a simple
+ configuration element.
+</p>
+<hr/>
+<h5>A simple "forward thru" action element</h5>
+<pre><code><action name="<strong>Welcome</strong>">
+ <result><strong>/pages/Welcome.jsp</strong></result>
+ </action></code></pre>
+<hr/>
+
+<p>
+ If a client asks for the Welcome action ("Welcome.do), the "/page/Welcome.jsp"
+ page would be returned in response.
+ The client does not know, or need to know, that the physical resource is located at
+ "/pages/Welcome.jsp".
+ All the client knows is that it requested the resource "Welcome.do".
+</p>
+
+<p>
+ But if we peek at the configuration file for the MailReader,
+ we find a slightly more complicated XML element for the Welcome action.
+</p>
+
+<hr/>
+<h5>The Welcome action element</h5>
+<pre><code><action name="Welcome" <b>class="mailreader2.Welcome"</b>>
+ <result>/pages/Welcome.jsp</result>
+ <strong><interceptor-ref name="guest"/></strong>
+ </action></code></pre>
+<hr/>
+
+<p>
+ Here, the <strong>Welcome</strong> Java class executes whenever
+ someone asks for the Welcome action.
+ As it completes, the Action class can select which "result" is displayed.
+ The default result name is "success".
+ Another available result, defined at a global scope, is "error".
+</p>
+
+<hr/>
+<h5>Key concept:</h5>
+<blockquote>
+ <p>
+ The Action class doesn't need to know what result type is needed
+ for "success" or "error".
+ The Action can just return the logical name for a result,
+ without knowing how the result is implemented.
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ The net effect is that all of the result details,
+ including the paths to server pages,
+ all can be declared <em>once</em> in the configuration.
+ Tightly coupled implementation details are not scattered all over
+ the application.
+</p>
+
+<hr/>
+<h5>Key concept:</h5>
+<blockquote>
+ <p>
+ The Struts configuration lets us separate concerns and "say it once".
+ The configuration helps us "normalize" an application,
+ in much the same way we normalize a database schema.
+ </p>
+</blockquote>
+<hr/>
+
+
+<p>
+ OK ... but why would a Welcome Action want to choose between "success" and
+ "error"?
+</p>
+
+<h4><a name="Welcome.java" id="Welcome.java">Welcome Action</a></h4>
+
+<p>
+ The MailReader application retains a list of users along with their email
+ accounts.
+ The application stores this information in a database.
+ If the application can't connect to the database, the application can't do
+ its job.
+ So before displaying the Welcome <strong>page</strong>, the Welcome
+ <strong>class</strong> checks to see if the database is available.
+</p>
+
+<p>
+ The MailReader is also an internationalized application.
+ So, the Welcome Action class checks to see if the message resources are
+ available too.
+ If both resources are available, the class passes back the "success" token.
+ Otherwise, the class passes back the "error" token,
+ so that the appropriate messages can be displayed.
+</p>
+
+<hr/>
+<h5>The Welcome Action class</h5>
+<pre><code>package mailreader2;
+ public class Welcome extends MailreaderSupport {
+
+ public String execute() {
+
+ // Confirm message resources loaded
+ String message = getText(Constants.ERROR_DATABASE_MISSING);
+ if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
+ <strong>addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);</strong>
+ }
+
+ // Confirm database loaded
+ if (null==getDatabase()) {
+ <strong>addActionError(Constants.ERROR_DATABASE_NOT_LOADED);</strong>
+ }
+
+ if (hasErrors()) {
+ <strong>return ERROR;</strong>
+ }
+ else {
+ <strong>return SUCCESS;</strong>
+ }
+ }
+ }</code></pre>
+<hr/>
+
+<p>
+ Several common result names are predefined,
+ including ERROR, SUCCESS, LOGIN, NONE, and INPUT,
+ so that these tokens can be used consistently across Struts 2 applications.
+</p>
+
+
+<h4><a name="global-results" id="global-results">Global Results</a></h4>
+
+<p>
+ As mentioned, "error" is defined in a global scope.
+ Other actions may have trouble connecting to the database later,
+ or other unexpected errors may occur.
+ The MailReader defines the "error" result as a Global Result,
+ so that any action can use it.
+</p>
+
+<hr/>
+<h5>MailReader's global-result element</h5>
+<pre><code> <global-results>
+ <result name=<strong>"error"</strong>><strong>/pages/Error.jsp</strong></result>
+ <result name="invalid.token">/pages/Error.jsp</result>
+ <result name="login" type="redirect-action">Logon!input</result>
+ </global-results></code></pre>
+<hr/>
+
+<p>
+ Of course, if an individual action mapping defines its own "error" result type,
+ the local result would be used instead.
+</p>
+
+<h4><a name="ApplicationListener.java" id="ApplicationListener.java">ApplicationListener.java</a>
+</h4>
+
+<p>
+ The database is exposed as an object stored in application scope.
+ The database object is based on an interface.
+ Different implementations of the database could be loaded without changing
+ the rest of the application.
+ But how is the database object loaded in the first place?
+</p>
+
+<p>
+ The database is created by a custom Listener that we configured in the "web.xml".
+</p>
+
+<hr/>
+<h5>mailreader2.ApplicationListener</h5>
+<pre><code> <listener>
+ <listener-class>
+ <strong>mailreader2.ApplicationListener</strong>
+ </listener-class>
+ </listener></code></pre>
+<hr/>
+
+<p>
+ By default, our ApplicationListener loads a <strong>MemoryDatabase</strong>
+ implementation of the UserDatabase.
+ MemoryDatabase stores the database content as a XML document,
+ which is parsed and loaded as a set of nested hashtables.
+ The outer table is the list of user objects, each of which has its own
+ inner hashtable of subscriptions.
+ When you register, a user object is stored in this hashtable.
+ When you login, the user object is stored within the session context.
+</p>
+
+<p>
+ The database comes seeded with a sample user.
+ If you check the "database.xml" file under "/src/main",
+ you'll see the sample user described in XML.
+</p>
+
+<hr/>
+<h5>The "seed" user element from the MailReader database.xml</h5>
+<pre><code><user username="<strong>user</strong>" fromAddress="John.User@somewhere.com"
+ fullName="<strong>John Q. User</strong>" password="<strong>pass</strong>">
+ <subscription host="<strong>mail.hotmail.com"</strong> autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="<strong>mail.yahoo.com</strong>" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user></code></pre>
+<hr/>
+
+<p>
+ The "seed" user element creates a registration record for "John Q. User",
+ with the subscription detail for his hotmail and yahoo accounts.
+</p>
+
+<h4><a name="resources.properties" id="resources.properties">Message Resources</a>
+</h4>
+
+<p>
+ As mentioned, MailReader is an internationalized application.
+ The message resources for the application are loaded through a reference in the
+ "struts.properties" file.
+ Like the database contents, the "struts.properties" file is kept under
+ "/src/main/" in the source tree.
+</p>
+
+<hr/>
+<h5>struts.properties</h5>
+<pre><code>struts.custom.i18n.resources = <strong>resources</strong>
+ struts.action.extension = <strong>do</strong></code></pre>
+<hr/>
+
+<p>
+ When we specify "resources" in the properties file,
+ we are telling the framework to scan the classpath
+ for a Resource Bundle named "resources.properties".
+ The bundle might be embedded in a JAR, or found in the "WEB-INF/classes"
+ folder, or anywhere else on the runtime classpath.
+ In the MailReader, we keep the <strong>original</strong> bundle in the
+ source tree under "src/main/". When the application is built, the
+ properties files are <strong>copied</strong> to "WEB-INF/classes", so
+ that they are on the Java classpath.
+</p>
+
+<hr/>
+<h5>Message Resource entries used by the Welcome page</h5>
+<pre><code><strong>index.heading=</strong>MailReader Application Options
+ <strong>index.logon=</strong>Log on to the MailReader Application
+ <strong>index.registration=</strong>Register with the MailReader Application
+ <strong>index.title=</strong>MailReader Demonstration Application
+ <strong>index.tour=</strong>A Walking Tour of the MailReader Demonstration Application</code></pre>
+<hr/>
+
+<p>
+ If you change a message in the resource, and then rebuild and reload the
+ application, the change will appear throughout the application.
+ If you provide message resources for additional locales, you can
+ localize your application.
+ The MailReader provides resources for English, Russian, and Japanese.
+</p>
+
+<h4><a name="Welcome.jsp" id="Welcome.jsp">Welcome Page</a></h4>
+
+<p>
+ After confirming that the necessary resources exist, the Welcome action
+ forwards to the Welcome page.
+</p>
+<hr/>
+<h5>Welcome.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <strong><%@ taglib prefix="s" uri="http://struts.apache.org/tags" %></strong>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><strong><s:text name="index.title"/></strong></title>
+ <link href="<strong><s:url value="/css/mailreader.css"/></strong>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+
+ <body>
+ <h3><s:text name="index.heading"/></h3>
+
+ <ul>
+ <li><a href="<s:url action="Registration!input"/>"><s:text
+ name="index.registration"/></a></li>
+ <li><a href="<s:url action="Logon!input"/>"><s:text
+ name="index.logon"/></a></li>
+ </ul>
+
+ <h3>Language Options</h3>
+ <ul>
+ <li><a href="<s:url action="Welcome?request_locale=en"/>">English</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ja"/>">Japanese</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ru"/>">Russian</a></li>
+ </ul>
+
+ <hr />
+
+ <p><strong><s:i18n name="alternate"></strong>
+ <img src="<s:text name="struts.logo.path"/>"
+ alt="<s:text name="struts.logo.alt"/>"/>
+ <strong></s:i18n></strong></p>
+
+ <p><a href="<s:url action="Tour" />"><s:text name="index.tour"/></a></p>
+
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ At the top of the Welcome page, there are several directives that load the
+ Struts 2 tag libraries.
+ These are just the usual red tape that goes with any JSP file.
+ The rest of the page utilizes three Struts JSP tags:
+ "text", "url", and "i18n".
+</p>
+
+<p>
+ (We use the tag prefix "s:" in the Struts 2 MailReader application,
+ but you can use whatever prefix you like in your applications.)
+</p>
+
+<p>
+ The <strong>text</strong> tag inserts a message from an
+ application's default resource bundle.
+ If the framework's locale setting is changed for a user,
+ the text tag will render messages from the new locale's resource
+ bundle instead.
+</p>
+
+<p>
+ The <strong>url</strong> tag can render a reference to an
+ action or any other web resource,
+ applying "URL encoding" to the hyperlinks as needed.
+ Java's URL encoding feature lets your application maintain client state
+ without requiring cookies.
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p><font class="hint">
+ <strong>Cookies</strong> -
+ If you turn cookies off in your browser, and then reload your browser
+ and this page,
+ you will see the links with the Java session id information attached.
+ (If you are using Internet Explorer and try this,
+ be sure you reset cookies for the appropriate security zone,
+ and that you disallow "per-session" cookies.)
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The <strong>i18n</strong> tag provides access to multiple resource bundles.
+ The MailReader application uses a second set of message resources for
+ non-text elements.
+ When these are needed, we use the "i18n" tag to specify a different bundle.
+</p>
+
+<p>
+ The <strong>alternate</strong> bundle is stored next to the default bundle,
+ so that it ends up under "classes", which is on the application's class path.
+</p>
+
+<p>
+ In the span of a single request for the Welcome page, the framework has done
+ quite a bit already:
+</p>
+
+<ul>
+ <li>
+ Confirmed that required resources were loaded during initialization.
+ </li>
+
+ <li>
+ Written all the page headings and labels from internationalized
+ message resources.
+ </li>
+
+ <li>
+ Automatically URL-encoded paths as needed.
+ </li>
+</ul>
+
+<p>
+ When rendered, the Welcome page lists two menu options:
+ one to register with the application and one to log on (if you have
+ already registered).
+ Let's follow the Logon link first.
+</p>
+
+<h3><a name="Logon" id="Logon">Logon</a></h3>
+
+<p>
+ If you choose the Logon link, and all goes well, the Logon action forwards
+ control to the Logon page.
+</p>
+
+<h4><a name="Logon.jsp" id="Logon.jsp">Logon Page</a></h4>
+
+<p>
+ The Logon page displays a form that accepts a username and password.
+ You can use the default username and password to logon
+ (<strong>user</strong> and <strong>pass</strong>), if
+ you like. Try omitting or misspelling the username and password in
+ various combinations to see how the application reacts.
+ Note that both the username and password are case sensitive.
+</p>
+
+<hr/>
+<h5>Login.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+ <body onLoad="self.focus();document.Logon.username.focus()">
+ <strong><s:actionerror/></strong>
+ <strong><s:form method="POST" validate="true"></strong>
+ <strong><s:textfield label="%{getText('username')}" name="username"/></strong>
+ <strong><s:password label="%{getText('password')}" name="password"/></strong>
+ <strong><s:submit value="%{getText('button.save')}"/></strong>
+ <strong><s:reset value="%{getText('button.reset')}"/></strong>
+ <s:submit <strong>action="Logon!cancel" onclick="form.onsubmit=null"</strong>
+ value="%{getText('button.cancel')}"/>
+ </s:form>
+ <jsp:include page="Footer.jsp"/>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ We already saw some of the tags used by the Logon page on the Welcome page.
+ Let's focus on the new tags.
+</p>
+
+<p>
+ The first new tag on the Logon page is <strong>actionerrors</strong>.
+ Most of the possible validation errors are related to a single field.
+ If you don't enter a username,
+ the framework can place an error message near the tag prompting you to
+ enter a username.
+ But some messages are not related to a single field.
+ For example, the database might be down.
+ If the action returns an "Action Error", as opposed to a "Field Error",
+ the messages are rendered in place of the "actionerror" tag.
+ The text for the validation errors, whether they are Action Errors or
+ Field Errors, can be specified in the resource bundle,
+ making the messages easy to manage and localize.
+</p>
+
+<p>
+ The second new tag is <strong>form</strong>.
+ This tag renders a HTML form tag.
+ By default, the form will submit back to whatever action invoked the page.
+ The "validate=true" setting enables client-side validation,
+ so that the form can be validated with JavaScript before being sent
+ back to the server.
+ The framework will still validate the form again, just to be sure, but the
+ client-side validation can save a few round-trips to the server.
+ You can use the method attribute to designate "GET" or "POST",
+ just like the HTML form tag.
+</p>
+
+<p>
+ Within the form tag,
+ we see four more new tags: "textfield", "password", "submit",
+ and "reset". We also see a second usage of "submit" that utilizes an
+ "action" attribute.
+</p>
+
+<p>
+ When we place a control on a form, we usually need to code a set of
+ HTML tags to do everything we want to do.
+ Most often, we do not just want a plain "input type=text" tag.
+ We want the input field to have a label too, and maybe even
+ a tooltip. And, of course, a place to print a message
+ should invalid data be entered.
+</p>
+
+<p>
+ The UI Tags support templates and themes so that a set of HTML tags can be
+ rendered from a single UI Tag. For example, the single tag
+</p>
+
+<pre><code>
+ <s:<strong>textfield</strong> label="%{getText('username')}" name="username"/>
+</code></pre>
+
+<p>
+ generates a wad of HTML markup.
+</p>
+
+<hr/>
+<pre><code><tr>
+ <td class="tdLabel">
+ <label for="Logon_username" class="label">Username:</label>
+ </td>
+ <td>
+ <input type="text" name="username" value="" id="Logon_username"/>
+ </td>
+ </tr></code></pre>
+<hr/>
+
+<p>
+ If for some reason you don't like the markup generated by a UI Tag,
+ it's each to change.
+ Each tag is driven by a template that can be updated on a tag-by-tag basis.
+ For example,
+ here is the default template that generates the markup for the ActionErrors tag:
+</p>
+
+<hr/>
+<pre><code><#if (actionErrors?exists && actionErrors?size > 0)>
+ <ul>
+ <#list actionErrors as error>
+ <li><span class="errorMessage">${error}</span></li>
+ </#list>
+ </ul>
+ </#if></code></pre>
+<hr/>
+
+<p>
+ If you wanted ActionErrors displayed in a table instead of a list,
+ you could edit a copy of this file, save it as a file named "actionerror.ftl",
+ and place this one file somewhere on your classpath.
+</p>
+
+<hr/>
+<pre><code><#if (actionErrors?exists && actionErrors?size > 0)>
+ <strong><table></strong>
+ <#list actionErrors as error>
+ <strong><tr><td></strong><span class="errorMessage">${error}</span><strong></td></tr></strong>
+ </#list>
+ <strong></table></strong>
+ </#if></code></pre>
+<hr/>
+
+<p>
+ Under the covers, the framework uses
+ <a href="http://freemarker.sourceforge.net/">Freemarker</a>
+ for its standard templating language.
+ FreeMarker is similar to
+ <a href="http://jakarta.apache.org/velocity/">Velocity</a>,
+ but it offers better error reporting and some additional features.
+ If you prefer, Velocity and JSP templates can also be used to create your own UI Tags.
+</p>
+
+<p>
+ The <strong>password</strong> tag renders a "input type=password"
+ tag, along with the usual template/theme markup.
+ By default, the password tag will not retain input if the submit fails.
+ If the username is wrong,
+ the client will have to enter the password again too.
+ (If you did want to retain the password when validation fails,
+ you can set the tag's "showPassword" property to true.)
+</p>
+
+<p>
+ Unsurprisingly, the <strong>submit</strong> and <strong>reset</strong> tags
+ render buttons of the corresponding types.
+</p>
+
+<p>
+ The second submit button is more interesting.
+</p>
+
+<pre><code> <s:submit <strong>action="Logon!cancel" onclick="form.onsubmit=null"</strong>
+ value="%{getText('button.cancel')}"/>
+</code></pre>
+
+<p>
+ Here we are creating the Cancel button for the form.
+ The button's attribute <em>action="Logon<strong>!</strong>cancel"</em>
+ tells the framework to submit to the Logon's "cancel" method
+ instead of the usual "execute" method.
+ The <em>onclick="form.onsubmit=null"</em> script defeats client-side validation.
+ On the server side, "cancel" is on a special list of methods that bypass validation,
+ so the request will go directly to the Action's <strong>cancel</strong> method.
+ (Other special aliases on the bypass list include "input" and "back".)
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p><font class="hint">
+ The UI tags have options and capabilities beyond what we have shown here.
+ For more see, the <a href="http://confluence.twdata.org/display/WW/Tags">UI Tag documentation.</a>
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ OK, but how do the tags know that both of these fields are required?
+ How do they know what message to display when the fields are empty?
+</p>
+
+<p>
+ For the answers, we need to look at another flavor of configuration file:
+ the "validation" file.
+</p>
+
+<h4><a name="Logon-validation.xml" id="Logon-validation.xml">Logon-validation.xml</a>
+</h4>
+
+<p>
+ While it is not hard to code data-entry validation into an Action class,
+ the framework provides an even easier way to validate input.
+</p>
+
+<p>
+ The validation framework is configured through another XML document, the <strong>
+ Logon-validation.xml</strong>.
+</p>
+
+<hr/>
+<h5>Validation file for Logon Action</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+ <validators>
+ <field name="<strong>username</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="<strong>error.username.required</strong>"/>
+ </field-validator>
+ </field>
+ <field name="<strong>password</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="<strong>error.password.required</strong>"/>
+ </field-validator>
+ </field>
+ </validators>
+</code></pre>
+<hr/>
+
+<p>
+ You may note that the DTD refers to "XWork".
+ <a href="http://www.opensymphony.com/xwork/">
+ Open Symphony XWork
+ </a> is a generic command-pattern framework that can be used outside of a
+ web environment. In practice, Struts 2 is a web-based extension of the
+ XWork framework.
+</p>
+
+<p>
+ The field elements correspond to the ActionForm properties.
+ The <strong>username</strong> and <strong>password</strong> field elements
+ say that each field depends on the "requiredstring" validator.
+ If the username is blank or absent, validation will fail and an error
+ message is generated.
+ The messages would be based on the "error.username.required" or
+ "error.password.required" message templates, from the resource bundle.
+</p>
+
+<!--
+<p>
+ The <strong>password</strong> field (or property) is also required.
+ In addition, it must also pass the "maxlength" and "minlength"
+ validations.
+ Here, the minimum length is three characters and the maximum length is
+ sixteen.
+ If the length of the password doesn't meet these criteria, a corresponding
+ error message is generated.
+ Of course, the messages are generated from the MessageResource bundles and
+ are easy to localize.
+</p>
+-->
+
+<h4><a name="Logon.java" id="Logon.java">Logon Action</a></h4>
+
+<p>
+ If validation passes, the framework invokes the "execute" method of the Logon Action.
+ The actual Logon Action is brief, since most of the functionality derives
+ from the base class, <strong>MailreaderSupport</strong>.
+</p>
+
+<hr/>
+<h5>Logon.java</h5>
+<pre><code>package mailreader2;
+ import org.apache.struts.apps.mailreader.dao.User;
+ public final class <strong>Logon</strong> extends MailreaderSupport {
+ public String <strong>execute()</strong> throws ExpiredPasswordException {
+ User user = <strong>findUser(getUsername(), getPassword());</strong>
+ if (user != null) {
+ <strong>setUser(user);</strong>
+ }
+ if (<strong>hasErrors()</strong>) {
+ return INPUT;
+ }
+ return SUCCESS;
+ }
+ }</code></pre>
+<hr/>
+
+<p>
+ Logon lays out what we do to authenticate a user.
+ We try to find the user using the credentials provided.
+ If the user is found, we cache a reference.
+ If the user is not found, we return "input" so the client can try again.
+ Otherwise, we return "success", so that the client can access the rest of the application.
+</p>
+
+<h4><a name="MailreaderSupport.java" id="MailreaderSupport.java">MailreaderSupport.java</a></h4>
+
+<p>
+ Let's look at the relevant properties and methods from MailreaderSupport
+ and another base class, <strong>ActionSupport</strong>, namely
+ "getUsername", "getPassword", "findUser", "setUser", and "hasErrors".
+</p>
+
+<p>
+ The framework lets you define
+ <a href="http://struts.apache.org/primer.html#javabeans">JavaBean properties</a>
+ directly on the Action.
+ Any JavaBean property can be used, including rich objects.
+ When a request comes in,
+ any public properties on the Action class are matched with the request parameters.
+ When the names match, the request parameter value is set to the JavaBean property.
+ The framework will make its best effort to convert the data,
+ and, if necessary, it will report any conversion errors.
+</p>
+
+<p>
+ The <strong>Username</strong> and <strong>Password</strong> properties are nothing fancy,
+ just standard JavaBean properties.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.getUsername() and getPassword()</h5>
+<pre><code>private String username = null;
+ public String <strong>getUsername()</strong> {
+ return this.username;
+ }
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ private String password = null;
+ public String <strong>getPassword()</strong> {
+ return this.password;
+ }
+ public void setPassword(String password) {
+ this.password = password;
+ }</code></pre>
+<hr/>
+
+<p>
+ We use these properties to capture the client's credentials,
+ and pass them to the more interesting <strong>findUser</strong> method.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.findUser</h5>
+<pre><code>public User <strong>findUser</strong>(String username, String password)
+ throws <strong>ExpiredPasswordException</strong> {
+ User user = <strong>getDatabase().findUser(username)</strong>;
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ this.<strong>addFieldError</strong>("password", getText("error.password.mismatch"));
+ }
+ return user;
+ }</code></pre>
+<hr/>
+
+<p>
+ The "findUser" method dips into the MailReader Data Access Object layer,
+ which is represented by the <strong>Database</strong> property.
+ The code for the DAO layer is maintained as a separate component.
+ The MailReader application imports the DAO JAR,
+ but it is not responsible for maintaining any of the DAO source.
+ Keeping the data access layer at "arms-length" is a very good habit.
+ It encourages a style of development where the data access layer
+ can be tested and developed independently of a specific end-user application.
+ In fact, there are several renditions of the MailReader application,
+ all which share the same MailReader DAO JAR!
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Strongly separate data access and business logic from the rest of the application."</font>
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ When "findUser" returns,
+ the Logon Action looks to see if a valid (non-null) User object is returned.
+ A valid User is passed to the <strong>User property</strong>.
+ Although it is still a JavaBean property,
+ the User property is not implemented in quite the same way as Username and Password.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.setUser</h5>
+<pre><code>public User getUser() {
+ return (User) <strong>getSession().get(Constants.USER_KEY)</strong>;
+ }
+ public void setUser(User user) {
+ getSession().put(Constants.USER_KEY, user);
+ }</code></pre>
+<hr/>
+
+<p>
+ Instead of using a field to store the property value,
+ "setUser" passes it to a <strong>Session</strong> property.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.getSession() and setSession()</h5>
+<pre><code>private Map session;
+ public Map <strong>getSession()</strong> {
+ return session;
+
+ public void <strong>setSession(Map value)</strong> {
+ session = value;
+ }</code></pre>
+<hr/>
+
+<p>
+ To look at the MailreaderSupport class, you would think the Session property is a plain-old Map.
+ In fact, the Session property is an adapter that is backed by the servlet session object at runtime.
+ The MailreaderSupport class doesn't need to know that though.
+ It can treat Session like any other Map.
+ We can also test the MailreaderSupport class by passing it some other implementation of Map,
+ running the test,
+ and then looking to see what changes MailreaderSupport made to our "mock" Session object.
+</p>
+
+<p>
+ But, when MailreaderSupport is running inside a web application,
+ how does it acquire a reference to the servlet session?
+</p>
+
+<p>
+ Good question. If you were to look at just the MailreaderSupport class,
+ you would not see a single line of code that sets the session property.
+ But, yet, when we run the class, the session property is not null.
+ Hmmm.
+</p>
+
+<p>
+ The magic that provides the Session property a runtime value is called "dependency injection".
+ The MailreaderSupport class implements a interface called <strong>SessionAware</strong>.
+ SessionAware is bundled with the framework, and it defines a setter for the Session property.
+</p>
+
+<p>
+ <code>public void <strong>setSession</strong>(Map session);</code>
+</p>
+
+<p>
+ Also bundled with the framework is an object called the <strong>ServletConfigInterceptor</strong>.
+ If the ServletConfigInterceptor sees that an Action implements the SessionAware interface,
+ it automatically set the session property.
+</p>
+
+<pre><code>if (action instanceof <code>SessionAware</code>) {
+ ((SessionAware) action).<code>setSession</code>(context.getSession());
+ }</code></pre>
+
+<p>
+ The framework uses these "Interceptor" classes to create a <strong>front controller</strong>
+ for each action an application defines.
+ Each Interceptor can peek at the request before an Action class is invoked,
+ and then again after the Action class is invoked.
+ (If you have worked with Servlet
+ <a href="http://struts.apache.org/primer.html#filters">Filters</a>,
+ you will recognize this pattern.
+ But, unlike Filters, Interceptors are not tied to HTTP.
+ Interceptors can be tested and developed outside of a web application.)
+</p>
+
+<p>
+ You can use the same set of Interceptors for all your actions,
+ or define a special set of Interceptors for any given action,
+ or define different sets of Interceptors to use with different types of actions.
+ The framework comes with a default set of Interceptors,
+ that it will use when another set is not specified,
+ but you can designate your own default Interceptor set (or "stack")
+ in the struts.xml configuration file.
+</p>
+
+<p>
+ Many Interceptors provide a utility or helper functions, like setting the session property.
+ Others, like the <strong>ValidationInterceptor</strong>, can change the workflow of an action.
+ Interceptors are key feature of the framework,
+ and we will see a few more on the tour.
+</p>
+
+<p>
+ If a valid User is not found, or the password doesn't match,
+ the "findUser" method invokes the <strong>addFieldError</strong> method to note the problem.
+ When "findUser" returns, the Logon Action checks for errors,
+ and then it returns either INPUT or SUCCESS.
+</p>
+
+<p>
+ The "addFieldError" method is provided by the ActionSupport class,
+ which is bundled with the framework.
+ The constants for INPUT and SUCCESS are also provided by ActionSupport.
+ While the ActionSupport class provides many useful utilities,
+ you are not required to use it as a base class.
+ Any Java class can be used as an Action, if you like.
+</p>
+
+<p>
+ It is a good practice to provide a base class with utilities
+ that can be shared by an application's Action classes.
+ The framework does this with ActionSupport,
+ and the MailReader application does the same with the MailreaderSupport class.
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Use a base class to define common functionality."</font></p>
+</blockquote>
+<hr/>
+
+<p>
+ But, what happens if Logon returns INPUT instead of SUCCESS.
+ How does the framework know what to do next?
+</p>
+
+<p>
+ To answer that question,
+ we need to turn back to the "struts.xml" file and look at how Logon is configured.
+</p>
+
+
+<h4><a name="Logon.xml" id="Logon.xml">Logon Configuration</a></h4>
+
+<p>
+ The Logon action element outlines how the Logon workflow operates,
+ including what to do when the Action returns "input",
+ or the default result name "success".
+</p>
+
+<hr/>
+<h5>struts.xml Logon</h5>
+<pre><code><action name="<strong>Logon</strong>" class="mailreader2.registration.Retrieve">
+ <result name="<strong>input</strong>">/pages/Logon.jsp</result>
+ <result name="<strong>cancel</strong>" type="redirect-action">Welcome</result>
+ <result type="redirect-action">MainMenu</result>
+ <result name="<strong>expired</strong>" type="chain">ChangePassword</result>
+ <<strong>exception-mapping</strong>
+ exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
+ result="<strong>expired</strong>"/>
+ <interceptor-ref name="<strong>guest</strong>"/>
+ </action></code></pre>
+<hr/>
+
+<p>
+ In the Logon action element, the first result element is named "input".
+ If validation or authentification fail,
+ the Action class will return "input" and the framework will transfer control to the
+ "Logon.jsp" page.
+</p>
+
+<p>
+ The second result element is named <strong>cancel</strong>.
+ If someone presses the cancel button on the Logon page,
+ the Action class will return "cancel", this result will be selected,
+ and the framework will issue a redirect to the Welcome action.
+</p>
+
+<p>
+ The third result has no name,
+ so it will be called if the default <strong>success</strong> token is returned.
+ So, if the Logon succeeds,
+ control will transfer to the MainMenu action.
+</p>
+
+<p>
+ The MailReader DAO exposes a "ExpiredPasswordException".
+ If the DAO throws this exception when the User logs in,
+ the framework will process the exception-mapping
+ and transfer control to the "ChangePassword" action.
+</p>
+
+<p>
+ Just in case any other Exceptions are thrown,
+ the MailReader application also defines a global handler.
+</p>
+
+<hr/>
+<h5>struts.xml exception-mapping</h5>
+<pre><code><global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Exception"/>
+ </global-exception-mappings></code></pre>
+<hr/>
+
+<p>
+ If an unexpected Exception is thrown,
+ the exception-mapping will transfer control to the action's "error" result,
+ or to a global "error" result.
+ The MailReader defines a global "error" result
+ which transfers control to an "Error.jsp" page
+ that can display the error message.
+</p>
+
+<hr/>
+<h5>Error.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Unexpected Error</title>
+ </head>
+ <body>
+ <h2>An unexpected error has occured</h2>
+ <p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+ </p>
+ <hr />
+ <h3>Error Message</h3>
+ <strong><s:actionerror /></strong>
+ <p>
+ <strong><s:property value="%{exception.message}"/></strong>
+ </p>
+ <hr />
+ <h3>Technical Details</h3>
+ <p>
+ <strong><s:property value="%{exceptionStack}"/></strong>
+ </p>
+ <jsp:include page="Footer.jsp"/>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ The Error page uses <strong>property</strong> tags to expose
+ the Exception message and the Exception stack.
+</p>
+
+<p>
+ Finally, the Logon action specifies an <strong>InterceptorStack</strong>
+ named <strong>defaultStack.</strong>
+ If you've worked with Struts 2 or WebWork 2 before, that might seem strange,
+ since "defaultStack" is the factory default.
+</p>
+
+<p>
+ In the MailReader application, most of the actions are only available
+ to authenticated users.
+ The exceptions are the Welcome, Logon, and Register actions
+ which are available to everyone.
+ To authenticate clients,
+ the MailReader uses a custom Interceptor and a custom Interceptor stack.
+</p>
+
+<hr/>
+<h5>mailreader2.AuthenticationInterceptor</h5>
+<pre><code>package mailreader2;
+ import com.opensymphony.xwork2.interceptor.Interceptor;
+ import com.opensymphony.xwork2.ActionInvocation;
+ import com.opensymphony.xwork2.Action;
+ import java.util.Map;
+ import org.apache.struts.apps.mailreader.dao.User;
+
+ public class <strong>AuthenticationInterceptor</strong> implements Interceptor {
+ public void destroy () {}
+ public void init() {}
+ public String <strong>intercept</strong>(ActionInvocation actionInvocation) throws Exception {
+ Map session = actionInvocation.getInvocationContext().getSession();
+ User user = (User) session.get(Constants.USER_KEY);
+ boolean isAuthenticated = (null!=user) && (null!=user.getDatabase());
+ if (<strong>isAuthenticated</strong>) {
+ return actionInvocation.invoke();
+ }
+ else {
+ return Action.LOGIN;
+ }
+ }
+ }</code></pre>
+<hr/>
+
+<p>
+ The <strong>AuthenticationInterceptor</strong> looks to see if a User object
+ has been stored in the client's session state.
+ If so, it returns normally, and the next Interceptor in the set would be invoked.
+ If the User object is missing, the Interceptors returns "login".
+ The framework would match "login" to the global result,
+ and transfer control to the Logon action.
+</p>
+
+<p>
+ The MailReader defines four custom Interceptor stacks: "user", "user-submit",
+ "guest", and "guest-submit".
+</p>
+
+<hr/>
+<h5>struts.xml interceptors</h5>
+<pre><code><interceptors>
+ <interceptor name="<strong>authentication</strong>"
+ class="mailreader2.AuthenticationInterceptor"/>
+ <interceptor-stack name="<strong>user</strong>" >
+ <interceptor-ref name="authentication" />
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>user-submit</strong>" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="user"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>guest</strong>" >
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>guest-submit</strong>" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="guest"/>
+ </interceptor-stack>
+ </interceptors>
+ <<strong>default-interceptor-ref</strong> name="user"/></code></pre>
+<hr/>
+
+<p>
+ The <strong>user</strong> stacks require that the client be authenticated.
+ In other words, that a User object is present in the session.
+ The actions using a <strong>guest</strong> stack can be accessed by any client.
+ The <strong>-submit</strong> versions of each can be used with actions
+ with forms, to guard against double submits.
+</p>
+
+<h5>Double Submits</h5>
+
+<p>
+ A common problem with designing web applications is that users are impatient
+ and response times can vary.
+ Sometimes, people will press a submit button a second time.
+ When this happens, the browser submits the request again,
+ so that we now have two requests for the same thing.
+ In the case of registering a user, if someone does press the submit button
+ again, and their timing is bad,
+ it could result in the system reporting that the username has already been
+ used.
+ (The first time the button was pressed.)
+ In practice, this would probably never happen, but for a longer running
+ process, like checking out a shopping cart,
+ it's easier for a double submit to occur.
+</p>
+
+<p>
+ To forestall double submits, and "back button" resubmits,
+ the framework can generate a token that is embedded in the form
+ and also kept in the session.
+ If the value of the tokens do not compare,
+ then we know that there has been a problem,
+ and that a form has been submitted twice or out of sequence.
+</p>
+
+<p>
+ The Token Session Interceptor will also attempt to provide intelligent
+ fail-over in the event of multiple requests using the same session.
+ That is, it will block subsequent requests until the first request is complete,
+ and then instead of returning the "invalid.token" code,
+ it will attempt to display the same response that the
+ original, valid action invocation would have displayed
+</p>
+
+<p>
+ Because the default interceptor stack will now authenticate the client,
+ we need to specify the standard "defaultStack" for the three
+ "guest actions", Welcome, Logon, and Register.
+ Requiring authentification by default is the better practice, since it
+ means that we won't forget to enable it when creating new actions.
+ Meanwhile, those pesky users will ensure that we don't forget to disable
+ authentification for "guest" services.
+</p>
+
+<h3><a name="MainMenu" id="MainMenu">MainMenu</a></h3>
+
+<p>
+ On a successful logon, the Main Menu page displays.
+ If you logged in using the demo account,
+ the page title should be "Main Menu Options for John Q. User".
+ Below this legend should be two links:
+</p>
+
+<ul>
+ <li>
+ Edit your user registration profile
+ </li>
+ <li>
+ Log off MailReader Demonstration Application
+ </li>
+</ul>
+
+<p>
+ Let's review the source for the "MainMenu" action mapping,
+ and the "MainMenu.jsp".
+</p>
+
+<hr/>
+<h5>Action mapping element for MainMenu</h5>
+<pre><code><action name="MainMenu" class="mailreader2.MailreaderSupport">
+ <result>/pages/MainMenu.jsp</result>
+ </action></code></pre>
+
+<h5>MainMenu.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title><s:text name="mainMenu.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+
+ <body>
+ <h3><s:text name="mainMenu.heading"/> <strong><s:property
+ value="user.fullName"/></strong></h3>
+ <ul>
+ <li><a href="<s:url <strong>action="Registration!input"</strong> />">
+ <s:text name="mainMenu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url <strong>action="Logoff"</strong> />">
+ <s:text name="mainMenu.logoff"/>
+ </a>
+ </ul>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ The source for "MainMenu.jsp" also contains a new tag, <strong>
+ property</strong>, which we use to customize the page with the
+ "fullName" property of the authenticated user.
+</p>
+
+<p>
+ Displaying the user's full name is the reason the MainMenu action
+ references the MailreaderSupport class.
+ The MailreaderSupport class has a User property that the text tag
+ can access.
+ If we did not utilize MailreaderSupport,
+ the property tag would not be able to find the User object to print
+ the full name.
+</p>
+
+<p>
+ The customized MainMenu page offers two standard links.
+ One is to "Edit your user registration profile".
+ The other is to "Logoff the MailReader Demonstration Application".
+</p>
+
+<h3><a name="Registration.jsp" id="Registration.jsp">Registration page</a>
+</h3>
+
+<p>
+ If you follow the "Edit your user registration profile" link from the Main
+ Menu page,
+ we will finally reach the heart of the MailReader application: the
+ Registration, or "Profile", page.
+ This page displays everything MailReader knows about you
+ (or at least your login),
+ while utilizing several interesting techniques.
+</p>
+
+<p>
+ To do double duty as the "Create" Registration page and the "Edit"
+ Registration page,
+ the "Registration.jsp" makes extensive use of the test tags,
+ to make it appears as though there are two distinct pages.
+</p>
+
+<hr/>
+<h5>Registration.jsp - head element</h5>
+<pre><code><head>
+ <s:if test="<strong>task=='Create'</strong>">
+ <title><s:text name="registration.title.create"/></title>
+ </s:if>
+ <s:if test="<strong>task=='Edit'</strong>">
+ <title><s:text name="registration.title.edit"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head></code></pre>
+<hr/>
+
+<p>
+ For example, if client is editing the form (task == 'Edit'),
+ the page inserts the username from the User object.
+ For a new Registration (task == 'Create'),
+ the page creates an empty data-entry field.
+</p>
+
+<hr/>
+<h5>Note:</h5>
+<blockquote>
+ <p><font class="hint">
+ <strong>Presention Logic</strong> -
+ The "test" tag is a convenient way to express presentation
+ logic within your pages.
+ Customized pages help to prevent user error,
+ and dynamic customization reduces the number of server pages your
+ application needs to maintain, among other benefits.
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The page also uses logic tags to display a list of subscriptions
+ for the given user.
+ If the RegistrationForm has task set to "Edit",
+ the lower part of the page that lists the subscriptions is exposed.
+</p>
+
+<hr/>
+<h5></h5>
+<pre><code><s:if test=<strong>"task == 'Edit'"</strong>>
+ <div align="center">
+ <h3><s:text name="heading.subscriptions"/></h3>
+ </div>
+ <!-- ... -->
+ </s:if>
+ <jsp:include page="Footer.jsp"/>
+ </body></html></code></pre>
+<hr/>
+
+<p>
+ Otherwise, the page contains just the top portion --
+ a data-entry form for managing the user's registration.
+</p>
+
+<h4><a name="iterator" id="iterator">iterator</a></h4>
+
+<p>
+ Besides "if" there are several other control tags that you can use
+ to sort, filter, or iterate over data.
+ The Registration page includes a good example of using the <strong>iterator</strong>
+ tag to display the User's Subscriptions.
+</p>
+
+<p>
+ The subscriptions are stored in a hashtable object, which is in turn
+ stored in the user object.
+ So to display each subscription, we have to reach into the user object,
+ and loop through the members of the subscription collection.
+ Using the iterator tag, you can code it the way it sounds.
+</p>
+
+<hr/>
+<h5>Using iterator to list the Subscriptions</h5>
+<pre><code><s:iterator value="<strong>user.subscriptions</strong>">
+ <tr>
+ <td align="left">
+ <s:property value="<strong>host</strong>"/>
+ </td>
+ <td align="left">
+ <s:property value="<strong>username</strong>"/>
+ </td>
+ <td align="center">
+ <s:property value="<strong>type</strong>"/>
+ </td>
+ <td align="center">
+ <s:property value="<strong>autoConnect</strong>"/>
+ </td>
+ <td align="center">
+ <a href="<s:url action="<strong>Subscription!delete</strong>"><s:param name="<strong>host</strong>"
+ value="host"/></s:url>">
+ <s:text name="registration.deleteSubscription"/>
+ </a>
+ <a href="<s:url action="<strong>Subscription!edit</strong>"><s:param name="<strong>host</strong>"
+ value="host"/></s:url>">
+ <s:text name="registration.editSubscription"/>
+ </a>
+ </td>
+ </tr>
+ </s:iterator></code></pre>
+<hr/>
+
+<p>
+ When the iterator renders, it generates a list of Subscriptions for the current User.
+</p>
+
+<hr/>
+
+<div align="center">
+ <h3>Current Subscriptions</h3>
+</div>
+
+<table border="1" width="100%">
+ <tr>
+ <th align="center" width="30%">
+ Host Name
+ </th>
+ <th align="center" width="25%">
+ User Name
+ </th>
+
+ <th align="center" width="10%">
+ Server Type
+ </th>
+ <th align="center" width="10%">
+ Auto
+ </th>
+ <th align="center" width="15%">
+ Action
+ </th>
+ </tr>
+ <tr>
+ <td align="left">
+ mail.hotmail.com
+ </td>
+ <td align="left">
+ user1234
+ </td>
+ <td align="center">
+ pop3
+ </td>
+
+ <td align="center">
+ false
+ </td>
+ <td align="center">
+ <a href="/struts2-mailreader/Subscription!delete.do?host=mail.hotmail.com">
+ Delete
+ </a>
+
+ <a href="/struts2-mailreader/Subscription!edit.do?host=mail.hotmail.com">
+ Edit
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ mail.yahoo.com
+ </td>
+ <td align="left">
+ jquser
+ </td>
+ <td align="center">
+ imap
+ </td>
+ <td align="center">
+ false
+ </td>
+ <td align="center">
+ <a href="/struts2-mailreader/Subscription!delete.do?host=mail.yahoo.com">
+ Delete
+ </a>
+
+ <a href="/struts2-mailreader/Subscription!edit.do?host=mail.yahoo.com">
+ Edit
+ </a>
+ </td>
+ </tr>
+</table>
+<a href="/struts2-mailreader/Subscription!input.do">Add</a>
+
+<hr/>
+
+<p>
+ Now look back at the code used to generate this block.
+</p>
+
+<p>
+ Notice anything nifty?
+</p>
+
+<p>
+ How about that the markup between the iterator tag is
+ actually <em>simpler</em> than the markup that we would use to render one row of the table?
+</p>
+
+<p>
+ Instead of using a qualified reference like "value=user.subscription[0].host",
+ we use the simplest possible reference: "value=host".
+ We didn't have to define a local variable, and reference that local in the loop code.
+ The reference to each item in the list is automatically resolved, no fuss, no muss.
+</p>
+
+<p>
+ Nice trick!
+</p>
+
+<p>
+ The secret to this magic is the <strong>value stack</strong>.
+ Next to Interceptors, the value stack is probably the coolest thing there is about the framework.
+ To explain the value stack, let's step back and start from the beginning.
+</p>
+
+<p>
+ Merging dynamic data into static web pages is a primary reason
+ we create web applications.
+ The Java API has a mechanism that allows you to
+ place objects in a servlet scope (page, request, session, or
+ application), and then retrieve them using a JSP scriplet.
+ If the object is placed directly in one of the scopes,
+ a JSP tag or scriptlet can find that object by searching page scope and
+ then request scope, and session scope, and finally application scope.
+</p>
+
+<p>
+ The value stack works much the same way, only better.
+ When you push an object on the value stack,
+ the public properties of that object become first-class properties of the stack.
+ The object's properties become the stack's properties.
+ If another object on the stack has properties of the same name,
+ the last object pushed onto the stack wins. (Last-In, First-Out.)
+</p>
+
+<p>
+ When the iterator tag loops through a collection,
+ it pushes each item in the collection onto the stack.
+ The item's properties become the stack's property.
+ In the case of the Subscriptions,
+ if the Subscription has a public Host property,
+ then during that iteration,
+ the stack can access the same property.
+</p>
+
+<p>
+ Of course, at the end of each iteration, the tag "pops" the item off the stack.
+ If we were to try and access the Host property later in the page,
+ it won't be there.
+</p>
+
+<p>
+ When an Action is invoked, the Action class is pushed onto the value stack.
+ Since the Action is on the value stack,
+ our tags can access any property of the Action as if it were an implicit property of the page.
+ The tags don't access the Action directly.
+ If a textfield tag is told to render the "Username" property,
+ the tag asks the value stack for the value of "Username",
+ and the value stack returns the first property it finds by that name.
+</p>
+
+<p>
+ The Validators also use the stack.
+ When validation fails on a field,
+ the value for the field is pushed onto the value stack.
+ As a result, if the client enters text into an Integer field,
+ the framework can still redisplay whatever was entered.
+ An invalid input value is not stored in the field (even if it could be).
+ The invalid input is pushed onto the stack for the scope of the request.
+</p>
+
+<p>
+ The Subscription list uses another new tag: the <strong>param</strong> tag.
+ As tags go, "param" takes very few parameters of its own: just "name" and "value", and neither is required.
+ Although simple, "param" is one of the most powerful tags the framework provides.
+ Not so much because of what it does, but because of what "param" allows the other tags to do.
+</p>
+
+<p>
+ Essentially, the "param" tag provides parameters to other tags.
+ A tag like "text" might be retrieving a message template with several replaceable parameters.
+ No matter how many parameters are in the template, and no matter what they are named,
+ you can use the "param" tag to pass in whatever you need.
+</p>
+
+<pre><code>pager.legend = Displaying {current} of {count} items matching {criteria}.
+ ...
+ <s:text name="pager.legend">
+ <s:<strong>param</strong> name="current" value="42" />
+ <s:<strong>param</strong> name="count" value="314" />
+ <s:<strong>param</strong> name="criteria" value="Life, the Universe, and Everything" />
+ </s:text></code></pre>
+
+<p>
+ In the case of an "url" tag,
+ we can use "param" to create the query string.
+ A statement like this:
+</p>
+
+<pre><code>
+ <s:url action="Subscription!edit"><s:param name="<strong>host" value="host</strong>"/></s:url>">
+</code></pre>
+
+<p>
+ can render a hyperlink like this:
+</p>
+
+<pre><code>
+ <a href="/struts2-mailreader/Subscription!edit.do?<strong>host=mail.yahoo.com</strong>">Edit</a>
+</code></pre>
+
+
+<!--
+<p>
+ At the foot of the Register page is a link for adding a subscription.
+ Let's wind up the tour by following the Add link and then logging off.
+ Like the link for creating a Support, Add points to an "Edit" action,
+ namely "EditSubscription".
+</p>
+-->
+
+<p>
+ If a hyperlink needs more parameters,
+ you can use "param" to add as many parameters as needed.
+</p>
+
+<h3>
+ <a name="Subscription" id="Subscription">Subscription</a>
+</h3>
+
+<p>
+ If we follow one of the "Edit" subscription links on the Registration page,
+ we come to the Subscriptions page,
+ which displays the details of our description in a data-entry form.
+ Let's have a look a the Subscription configuration in "struts.xml"
+ and follow the bouncing ball from page to action to page.
+</p>
+
+<hr/>
+<h5>struts.xml Subscription element</h5>
+<pre><code><action name="Subscription" class="mailreader2.SubscriptionSupport">
+ <result name="input">/pages/Subscription.jsp</result>
+ <result type="redirect-action">Registration!input</result>
+ </action></code></pre>
+<hr/>
+
+<p>
+ The Edit link specified the Subscription action,
+ but also includes the qualifier <strong>!edit</strong>.
+ The <strong>!</strong> idiom tells the framework to invoke the
+ "edit" method of the Subscription action,
+ instead of the default "execute" method
+ The "alternate" execute methods are called <strong>alias</strong> methods.
+</p>
+
+<hr/>
+<h5>Subscription edit alias</h5>
+<pre><code>public String <strong>edit()</strong> {
+ <strong>setTask(Constants.EDIT);</strong>>
+ return find();
+ }
+
+ public String find() {
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+ if (sub == null) {
+ return ERROR;
+ }
+ <strong>setSubscription(sub);</strong>
+ return INPUT;
+ }</code></pre>
+<hr/>
+
+<p>
+ The "edit" alias has two responsibilities.
+ First, it must set the Task property to "Edit".
+ The Subscription page will render itself differently
+ depending on the value of the Task property.
+ Second, "edit" must locate the relevant Subscription
+ and set it to the Subscription property.
+ If all goes well, "edit" returns the INPUT token,
+ so that the "input" result will be invoked.
+</p>
+
+<p>
+ In the normal course, the Subscription should always be found,
+ since we selected the entry from a system-generated list.
+ If the Subscription is not found,
+ it would be because the database disappeared
+ or the request is being spoofed.
+ If the Subscription is not found,
+ edit returns the token for the global "error" result,
+ because this condition is unexpected.
+</p>
+
+<p>
+ The business logic for the "edit" alias is a simple wrapper
+ around the MailReader DAO classes.
+</p>
+
+<hr/>
+<h5>MailreaderSupport findSubscription()</h5>
+<pre><code>public Subscription <strong>findSubscription()</strong> {
+ return findSubscription(getHost());
+ }
+
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = <strong>getUser().findSubscription(host);</strong>
+ return subscription;
+ }</code></pre>
+<hr/>
+
+<p>
+ This code is very simple
+ and doesn't seem to provide much in the way of error handling.
+ But, that's OK.
+ Since the page is suppose to be entered from a link that we created,
+ we do expect everything to go right here.
+ But, if it doesn't, the global exception handler we defined in "struts.xml"
+ will trap the exception for us.
+</p>
+
+<p>
+ Likewise, the AuthentificationInterceptor will ensure that only clients
+ with a valid User object can try to edit a Subscription.
+ If the session expired, or someone bookmarked the page,
+ the client will be redirected to the Logon page automatically.
+</p>
+
+<p>
+ As a final layer of defense, we also configured a validator for Subscription,
+ to ensure that we are passed a Host parameter.
+</p>
+
+<hr/>
+<h5>Subscription-validation.xml</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+ <validators>
+ <field name="<strong>host</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+ </validators></code></pre>
+<hr/>
+
+<p>
+ By keeping routine sety precautions out of the Action class,
+ the all-important Actions becomes smaller and easier to maintain.
+</p>
+
+<p>
+ After setting the relevent Subscription object to the Subscription property,
+ the framework transfers control to the (you guessed it) Subscription page.
+</p>
+
+<hr/>
+<h5>Subscription.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <s:if test="task=='Create'">
+ <title><s:text name="subscription.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="subscription.title.edit"/></title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title><s:text name="subscription.title.delete"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+ <body onLoad="self.focus();document.Subscription.username.focus()">
+
+ <s:actionerror/>
+ <s:form method="POST" <strong>action="SubscriptionSave"</strong> validate="false">
+ <strong><s:token /></strong>
+ <strong><s:hidden name="task"/></strong>
+ <strong><s:label label="%{getText('username')}" name="user.username"/></strong>
+
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('mailHostname')}" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('mailHostname')}" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:label label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:label label="%{getText('mailServerType')}"
+ name="subscription.type"/>
+ <s:label label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.confirm')}"/>
+ </s:if>
+ <s:else>
+ <s:textfield label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:textfield label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <strong><s:select label="%{getText('mailServerType')}"
+ name="subscription.type" list="types"/></strong>
+ <strong><s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/></strong>
+ <s:submit value="%{getText('button.save')}"/>
+ <s:reset value="%{getText('button.reset')}"/>
+ </s:else>
+
+ <s:submit action="Registration!input"
+ value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+ </s:form>
+
+ <jsp:include page="Footer.jsp"/>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ As before, we'll discuss the tags and attributes that are new to this page:
+ "token", "hidden", "label", "select", and "checkbox".
+</p>
+
+<p>
+ When we looked at the form tag for the Logon page,
+ it did not specify a target for the submit.
+ Instead, it just posted back to the Logon action.
+ In this <strong>form</strong> tag, we are specifying a different action,
+ <strong>SubscriptionSave</strong>
+ to be the target of the submit,
+</p>
+
+<p>
+ The main reason we use another action is so that we can use a different set of validations.
+ When we retrieve the Subscription for editing, all we need is the Host property.
+ When we save the Subscription, we want to validate additional properties.
+ Since the validation files are coupled to the classes,
+ we created a new Action class for saving a Subscription.
+</p>
+
+<hr/>
+<h5>Subscription-validation.xml</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+ <validators>
+ <field name="<strong>host</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+ </validators></code></pre>
+<hr/>
+
+<p>
+ The validators follow the same type of inheritance path as the classes.
+ SubscriptionSave extends Subscription,
+ so when SubscriptionSave is validated,
+ the Host property specified by "Subscription-validation.xml" will also be required.
+</p>
+
+<p>
+ The <strong>token</strong> tag works with the Token Session Interceptor to foil double submits.
+ The tag generates a key that is embedded in the form and cached in the session.
+ Without this tag, the Interceptor can't work it's magic.
+</p>
+
+<p>
+ The <strong>hidden</strong> tag embeds the Task property into the form.
+ When the form is submitted,
+ the SubscriptionSave action wil use the Task property to decide
+ whether to insert or update the form.
+</p>
+
+<p>
+ The <strong>label</strong> renders a "read only" version of a property,
+ suitable for placement in the form.
+ In Edit or Delete mode, we want the Host property to be immutable,
+ since it is used as a key. (As unwise as that might sound.)
+ In Delete mode, all of the properties are immutable,
+ since we are simply confirming the delete operation.
+</p>
+
+<p>
+ Saving the best for last, the Subscription utilizes two more interesting
+ tags, "select" and "checkbox".
+</p>
+
+<p>
+ Unsurprisingly, the <strong>select</strong> tag renders a select control,
+ but the tag does so without requiring a lot of markup or redtape.
+</p>
+
+<pre><code><s:select label="%{getText('mailServerType')}"
+ name="subscription.type" <strong>list="types"</strong> />
+</code></pre>
+
+<p>
+ The interesting attribute of the "select" tag is "list",
+ which, in our case, specifies a value of "types".
+ If we take another look at the Subscription action,
+ we can see that it implements an interface named Preparable
+ and populates a Types property in a method named "prepare".
+</p>
+
+<hr/>
+<h5>Subscription-validation.xml</h5>
+<pre><code>public class <strong>Subscription</strong> extends MailreaderSupport
+ <strong>implements Preparable</strong> {
+
+ private Map types = null;
+ public Map <strong>getTypes()</strong> {
+ return types;
+ }
+
+ public void <strong>prepare()</strong> {
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+ setHost(getSubscriptionHost());
+ }
+
+ // ... </code></pre>
+<hr/>
+
+<p>
+ The default Interceptor stack includes the <strong>PrepareInterceptor</strong>,
+ which observes the Preparable interface.
+</p>
+
+<hr/>
+<h5>PrepareInterceptor</h5>
+<pre><code>public class <strong>PrepareInterceptor</strong> extends AroundInterceptor {
+
+ protected void after(ActionInvocation dispatcher, String result) throws Exception {
+ }
+
+ protected void before(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+ <strong>if (action instanceof Preparable) {
+ ((Preparable) action).prepare();</strong>
+ }
+ }
+ }</code></pre>
+
+<p>
+ The PrepareInterceptor ensures that the "prepare" method will always be called
+ before "execute" or an alias method is invoked.
+ We use "prepare" to setup the list of items for the select list to display.
+ We also transfer the Host property from our Subscription object
+ to a local property, where it is easier to manage.
+</p>
+
+
+<h4>
+ <a name="SubscriptionAction.java" id="SubscriptionAction.java">SubscriptionAction.java</a>
+</h4>
+
+<p>
+ Like many applications, the MailReader uses mainly String properties.
+ One exception is the AutoConnect property of the Subscription object.
+ On the HTML form, the AutoConnect property is represented by a checkbox,
+ and checkboxes need to be handled differently that other controls.
+</p>
+
+<p>
+ The <strong>checkbox</strong> starts out as a simple enough control.
+</p>
+
+<pre><code> <s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/></code></pre>
+
+<p>
+ The Subscription object has a boolean AutoConnect property,
+ and the checkbox simply has to represent its state.
+ The problem is, if you clear a checkbox, the browser client will not submit <em>anything</em>.
+ Nada. Zip.
+ It is as if the checkbox control never existed.
+ The HTTP protocol has no way to affirm "false".
+ If the control is missing, we need to figure out it's been unclicked.
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p class="hint">
+ <strong>Checkboxes</strong> -
+ The HTML checkbox is a tricky control.
+ The problem is that, according to the W3C specification, a value is
+ only guaranteed to be sent
+ if the control is checked.
+ If the control is not checked, then the control may be omitted from
+ the request, as if it was on the page.
+ This can cause a problem with session-scope checkboxes.
+ Once you set the checkbox to true, the control can't set it to false
+ again,
+ because if you uncheck the box, nothing is sent, and so the control
+ stays checked.
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ The simplest solution is to employ our old friend Preparable again.
+ In the "prepare" method for SubscriptionSave,
+ we can set the property represented by the checkbox to false.
+ If the control is not submitted, then the property remains false.
+ If the control is submitted, then the property is set to true.
+</p>
+
+<hr/>
+<h5>SubscriptionSave</h5>
+<pre><code>public final class SubscriptionSave extends Subscription {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ <strong>getSubscription().setAutoConnect(false);</strong>
+ }
+
+ public String execute() throws Exception {
+ return save();
+ }
+ }</code></pre>
+<hr/>
+
+
+<p>
+ If we press the SAVE button,
+ the form will be submitted to the SubscriptionSave action.
+ If the validation succeeds, as we've seen,
+ SubscriptionSave will invoke the Subscription.save method.
+</p>
+
+<hr/>
+<h5>Subscription save method</h5>
+<pre><code>public String <strong>save</strong>() throws Exception {
+
+ if (Constants.DELETE.equals(getTask())) {
+ <strong>removeSubscription</strong>();
+ }
+
+ if (Constants.CREATE.equals(getTask())) {
+ <strong>copySubscription(</strong>getHost());
+ }
+
+ saveUser();
+ return SUCCESS;
+ }</code></pre>
+<hr/>
+
+<p>
+ The <strong>save</strong> method uses the Task property to handle
+ the special cases of deleting and creating,
+ and then updates the state of the User object.
+</p>
+
+<p>
+ The <strong>removeSubscription</strong> method calls the DAO facade,
+ and then updates the application state.
+</p>
+
+<hr/>
+<h5>removeSubscription</h5>
+<pre><code>public void <strong>removeSubscription</strong>() throws Exception {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(Constants.SUBSCRIPTION_KEY);
+ }</code></pre>
+<hr/>
+
+<p>
+ The <strong>copySubscription</strong> method is a bit more interesting.
+ The MailReader DAO layer API includes some immutable fields
+ that can't be set once the object is created.
+ Because key fields are immutable,
+ we can't just create a Subscription, let the framework populate all the fields,
+ and then save it when we are done -- because some fields can't be populated,
+ except at construction.
+</p>
+
+<p>
+ One workaround would be to declare properties on the Action
+ for all the properties we need to pass to the Subscription or User objects.
+ When we are ready to create the object,
+ we could pass the new object values from the Action properties.
+</p>
+
+<p>
+ Another workaround is to declare only the immutable properties on the Action,
+ and then use what we can from the domain object.
+</p>
+
+<p>
+ This implementation of the MailReader utilizes the second alternative.
+ We define User and Subscription objects on our base Action,
+ and add other properties only as needed.
+</p>
+
+<p>
+ To add a new Subscription or User,
+ we create a blank object to capture whatever fields we can.
+ When this "input" object returns, we create a new object,
+ setting the immutable fields to appropriate values,
+ and copy over the rest of the properties.
+</p>
+
+<hr/>
+<h5>copySubscription</h5>
+<pre><code>public void <strong>copySubscription</strong>(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ <strong>BeanUtils.setValues</strong>(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }</code></pre>
+
+<p>
+ Of course, this is not a preferred solution,
+ but merely a way to work around an issue in the MailReader DAO API
+ that would not be easy for us change.
+</p>
+
+<h3>Summary</h3>
+
+<p>
+ At this point, we've booted the application, logged on,
+ reviewed a Registration record, and edited a Subscription.
+ Of course, there's more, but from here on, it is mostly more of the same.
+ The full source code for MailReader is
+ <a href="http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/struts2/apps/mailreader/">available online</a>
+ and in the distribution.
+</p>
+
+<p>
+ Enjoy!
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/struts-power.gif b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/struts-power.gif
new file mode 100644
index 0000000..5f4e9d4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-ibatis/src/main/webapp/struts-power.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/README.txt b/struts-sandbox/struts2/apps/mailreader-wildone/README.txt
new file mode 100644
index 0000000..d23a1fb
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/README.txt
@@ -0,0 +1,19 @@
+README.txt - mailreader
+
+The MailReader demonstrates a localized application with a master/child
+CRUD workflow.
+
+This rendition also demonstrates using multiple Action classes as
+opposed to multiple "alias" methods. Each application "entity" has
+its own Java package, and each class in the package represents a command.
+
+See the Sandbox for other MailReader examples using other architectures.
+
+* http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2/apps/
+
+For more about the MailReader applicaton genneraly, visit Struts University.
+
+* http://www.StrutsUniversity.org/
+
+
+----------------------------------------------------------------------------
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/pom.xml b/struts-sandbox/struts2/apps/mailreader-wildone/pom.xml
new file mode 100644
index 0000000..cf23ee6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-apps</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-mailreader</artifactId>
+ <packaging>war</packaging>
+ <name>MailReader Example Application</name>
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>1.8.0.4</version>
+ </dependency>
+ <dependency>
+ <groupId>com.ibatis</groupId>
+ <artifactId>ibatis2-sqlmap</artifactId>
+ <version>2.1.7.597</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>struts-mailreader-dao</artifactId>
+ <version>1.3.5</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty6-plugin</artifactId>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-j2ee_1.4_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/ApplicationListener.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/ApplicationListener.java
new file mode 100644
index 0000000..c7a269c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/ApplicationListener.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: ApplicationListener.java 372087 2006-01-25 03:38:42Z craigmcc $
+ */
+
+package mailreader2;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.io.*;
+
+/**
+ * <p><code>ServletContextListener</code> that initializes and finalizes the
+ * persistent storage of User and Support information for the Struts
+ * Demonstration Application, using an in-memory database backed by an XML
+ * file.</p>
+ * <p/>
+ * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
+ * from a WAR file, or in another environment where reading and writing of the
+ * web application resource is impossible, the initial contents will be copied
+ * to a file in the web application temporary directory provided by the
+ * container. This is for demonstration purposes only - you should
+ * <strong>NOT</strong> assume that files written here will survive a restart
+ * of your servlet container.</p>
+ * <p/>
+ * <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>Path to database.xml (under classes here). </li>
+ * <p/>
+ * <li>Class to store protocol list (an array here). </li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ * </p>
+ */
+
+public final class ApplicationListener implements ServletContextListener {
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Appication scope attribute key under which the in-memory version of
+ * our database is stored.</p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+
+ /**
+ * <p>Application scope attribute key under which the valid selection
+ * items for the protocol property is stored.</p>
+ */
+ public static final String PROTOCOLS_KEY = "protocols";
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>ServletContext</code> for this web application.</p>
+ */
+ private ServletContext context = null;
+
+
+ /**
+ * The {@link MemoryUserDatabase} object we construct and make available.
+ */
+ private MemoryUserDatabase database = null;
+
+
+ /**
+ * <p>Logging output for this plug in instance.</p>
+ */
+ private Log log = LogFactory.getLog(this.getClass());
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * <p>The web application resource path of our persistent database storage
+ * file.</p>
+ */
+ private String pathname = "/WEB-INF/classes/database.xml";
+
+ /**
+ * <p>Return the application resource path to the database.</p>
+ *
+ * @return application resource path path to the database
+ */
+ public String getPathname() {
+ return (this.pathname);
+ }
+
+ /**
+ * <p>Set the application resource path to the database.</p>
+ *
+ * @param pathname to the database
+ */
+ public void setPathname(String pathname) {
+ this.pathname = pathname;
+ }
+
+ // ------------------------------------------ ServletContextListener Methods
+
+
+ /**
+ * <p>Gracefully shut down this database, releasing any resources that
+ * were allocated at initialization.</p>
+ *
+ * @param event ServletContextEvent to process
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ log.info("Finalizing memory database plug in");
+
+ if (database != null) {
+ try {
+ database.close();
+ } catch (Exception e) {
+ log.error("Closing memory database", e);
+ }
+ }
+
+ context.removeAttribute(DATABASE_KEY);
+ context.removeAttribute(PROTOCOLS_KEY);
+ database = null;
+ context = null;
+
+ }
+
+
+ /**
+ * <p>Initialize and load our initial database from persistent
+ * storage.</p>
+ *
+ * @param event The context initialization event
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ log.info("Initializing memory database plug in from '" +
+ pathname + "'");
+
+ // Remember our associated ServletContext
+ this.context = event.getServletContext();
+
+ // Construct a new database and make it available
+ database = new MemoryUserDatabase();
+ try {
+ String path = calculatePath();
+ if (log.isDebugEnabled()) {
+ log.debug(" Loading database from '" + path + "'");
+ }
+ database.setPathname(path);
+ database.open();
+ } catch (Exception e) {
+ log.error("Opening memory database", e);
+ throw new IllegalStateException("Cannot load database from '" +
+ pathname + "': " + e);
+ }
+ context.setAttribute(DATABASE_KEY, database);
+
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Calculate and return an absolute pathname to the XML file to contain
+ * our persistent storage information.</p>
+ *
+ * @throws Exception if an input/output error occurs
+ */
+ private String calculatePath() throws Exception {
+
+ // Can we access the database via file I/O?
+ String path = context.getRealPath(pathname);
+ if (path != null) {
+ return (path);
+ }
+
+ // Does a copy of this file already exist in our temporary directory
+ File dir = (File)
+ context.getAttribute("javax.servlet.context.tempdir");
+ File file = new File(dir, "struts-example-database.xml");
+ if (file.exists()) {
+ return (file.getAbsolutePath());
+ }
+
+ // Copy the static resource to a temporary file and return its path
+ InputStream is =
+ context.getResourceAsStream(pathname);
+ BufferedInputStream bis = new BufferedInputStream(is, 1024);
+ FileOutputStream os =
+ new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = bis.read(buffer);
+ if (n <= 0) {
+ break;
+ }
+ bos.write(buffer, 0, n);
+ }
+ bos.close();
+ bis.close();
+ return (file.getAbsolutePath());
+
+ }
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/AuthenticationInterceptor.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/AuthenticationInterceptor.java
new file mode 100644
index 0000000..627c456
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/AuthenticationInterceptor.java
@@ -0,0 +1,33 @@
+package mailreader2;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import org.apache.struts.apps.mailreader.dao.User;
+
+import java.util.Map;
+
+public class AuthenticationInterceptor implements Interceptor {
+
+ public void destroy() {
+ }
+
+ public void init() {
+ }
+
+ public String intercept(ActionInvocation actionInvocation) throws Exception {
+
+ Map session = actionInvocation.getInvocationContext().getSession();
+
+ User user = (User) session.get(Constants.USER_KEY);
+
+ boolean isAuthenticated = (null != user) && (null != user.getDatabase());
+
+ if (!isAuthenticated) {
+ return Action.LOGIN;
+ } else {
+ return actionInvocation.invoke();
+ }
+
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/ChangePassword.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/ChangePassword.java
new file mode 100644
index 0000000..9bd958b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/ChangePassword.java
@@ -0,0 +1,10 @@
+package mailreader2;
+
+/**
+ * <p>
+ * When implemented, allow guest to change password,
+ * given correct credentials.
+ * </p>
+ */
+public class ChangePassword extends MailreaderSupport {
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Constants.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Constants.java
new file mode 100644
index 0000000..45afd48
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Constants.java
@@ -0,0 +1,150 @@
+/*
+ * $Id: Constants.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+/**
+ * <p> Manifest constants for the MailReader application. </p>
+ */
+public final class Constants {
+
+ // -- Statements --
+
+ public static final Integer DB_FALSE = 0;
+ public static final Integer DB_TRUE = 1;
+
+ public static final String LOCALE_LIST = "LOCALE_LIST";
+ public static final String REGISTRATION_INSERT_ASSERT = "REGISTRATION_INSERT_ASSERT";
+ public static final String REGISTRATION_INSERT = "REGISTRATION_INSERT";
+ public static final String REGISTRATION_PASSWORD = "REGISTRATION_PASSWORD";
+ public static final String REGISTRATION_FULLNAME = "REGISTRATION_FULLNAME";
+ public static final String REGISTRATION_EDIT = "REGISTRATION_EDIT";
+ public static final String REGISTRATION_UPDATE = "REGISTRATION_UPDATE";
+ public static final String SUBSCRIPTION_INSERT_ASSERT = "SUBSCRIPTION_INSERT_ASSERT";
+ public static final String SUBSCRIPTION_INSERT = "SUBSCRIPTION_INSERT";
+ public static final String SUBSCRIPTION_LIST = "SUBSCRIPTION_LIST";
+ public static final String SUBSCRIPTION_EDIT = "SUBSCRIPTION_EDIT";
+ public static final String SUBSCRIPTION_UPDATE = "SUBSCRIPTION_UPDATE";
+
+ // -- Tokens --
+
+ /**
+ * <p> The token representing a "cancel" request. </p>
+ */
+ public static final String CANCEL = "cancel";
+
+ /**
+ * <p> The token representing a "create" task. </p>
+ */
+ public static final String CREATE = "Create";
+
+ /**
+ * <p> The application scope attribute under which our user database is
+ * stored. </p>
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ * <p> The token representing a "edit" task. </p>
+ */
+ public static final String DELETE = "Delete";
+
+ /**
+ * <p> The token representing a "edit" task. </p>
+ */
+ public static final String EDIT = "Edit";
+
+ /**
+ * <p> The package name for this application. </p>
+ */
+ public static final String PACKAGE = "org.apache.struts.apps.mailreader";
+
+ /**
+ * <p> The session scope attribute under which the Support object
+ * currently selected by our logged-in User is stored. </p>
+ */
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ /**
+ * <p> The session scope attribute under which the User object for the
+ * currently logged in user is stored. </p>
+ */
+ public static final String USER_KEY = "user";
+
+ /**
+ * <p>The token representing the "Host" property.
+ */
+ public static final String HOST = "host";
+
+ // ---- Error Messages ----
+
+ /**
+ * <p/>
+ * A static message in case message resource is not loaded.
+ * </p>
+ */
+ public static final String ERROR_MESSAGES_NOT_LOADED =
+ "ERROR: Message resources not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p/>
+ * A static message in case database resource is not loaded.
+ * <p/>
+ */
+ public static final String ERROR_DATABASE_NOT_LOADED =
+ "ERROR: User database not loaded -- check servlet container logs for error messages.";
+
+ /**
+ * <p/>
+ * A standard key from the message resources file, to test if it is available.
+ * <p/>
+ */
+ public static final String ERROR_DATABASE_MISSING = "error.database.missing";
+
+ /**
+ * <p/>
+ * A "magic" username to trigger an ExpiredPasswordException for testing.
+ * </p>
+ */
+ public static final String EXPIRED_PASSWORD_EXCEPTION = "ExpiredPasswordException";
+
+ /**
+ * <p/>
+ * Name of field to associate with authentification errors.
+ * <p/>
+ */
+ public static final String PASSWORD_MISMATCH_FIELD = "password";
+
+ /**
+ * <p/>
+ * A static message in case message resource is not loaded.
+ * </p>
+ */
+ public static final String ERROR_INVALID_WORKFLOW =
+ "ERROR: Action is being executed out of sequence!";
+
+ // ---- Log Messages ----
+
+ /**
+ * <p> Message to log if saving a user fails. </p>
+ */
+ public static final String LOG_DATABASE_SAVE_ERROR =
+ " Unexpected error when saving User: ";
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Logoff.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Logoff.java
new file mode 100644
index 0000000..4d88393
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Logoff.java
@@ -0,0 +1,30 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+/**
+ * <p> Log user out of the current session. </p>
+ */
+public class Logoff extends MailreaderSupport {
+
+ public String execute() {
+ setUser(null);
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport.java
new file mode 100644
index 0000000..1f4b648
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport.java
@@ -0,0 +1,558 @@
+/*
+ * $Id: BaseAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2;
+
+import com.opensymphony.util.BeanUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.ModelDriven;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.Subscription;
+import org.apache.struts.apps.mailreader.dao.User;
+import org.apache.struts.apps.mailreader.dao.UserDatabase;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription;
+import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUser;
+import org.apache.struts2.interceptor.ApplicationAware;
+import org.apache.struts2.interceptor.SessionAware;
+
+import java.util.Map;
+
+/**
+ * <p> Base Action for MailreaderSupport application. </p>
+ * <p/>
+ * <p> Note that this class does NOT implement model driven because of the way
+ * the pre-existing model is designed. The MailReader DAO includes immutable
+ * fields that can only be set on construction, and some objects do not have a
+ * default construction. One approach would be to mirror all the DAO
+ * properties on the Actions. As an alternative, this implementations uses the
+ * DAO properties where possible, and uses local Action properties only as
+ * needed. To create new objects, a blank temporary object is constructed, and
+ * the page uses a mix of local Action properties and DAO properties. When the
+ * new object is to be saved, the local Action properties are used to create
+ * the object using the DAO factory methods, the input values are copied from
+ * the temporary object, and the new object is saved. It's kludge, but it
+ * avoids creating unnecessary local properties. Pick your poison.</p>
+ */
+public class MailreaderSupport extends ActionSupport
+ implements SessionAware, ApplicationAware {
+
+ /**
+ * Return CANCEL so apropriate result can be selected.
+ *
+ * @return "cancel" so apropriate result can be selected.
+ */
+ public String cancel() {
+ return Constants.CANCEL;
+ }
+
+ // ---- ApplicationAware ----
+
+ /**
+ * <p>Field to store application context or its proxy.</p>
+ * <p/>
+ * <p>The application context lasts for the life of the application. A
+ * reference to the database is stored in the application context at
+ * startup.</p>
+ */
+ private Map application;
+
+ /**
+ * <p>Store a new application context.</p>
+ *
+ * @param value A Map representing application state
+ */
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ /**
+ * <p>Provide application context.</p>
+ */
+ public Map getApplication() {
+ return application;
+ }
+
+ // ---- SessionAware ----
+
+ /**
+ * <p>Field to store session context, or its proxy.</p>
+ */
+ private Map session;
+
+ /**
+ * <p>Store a new session context.</p>
+ *
+ * @param value A Map representing session state
+ */
+ public void setSession(Map value) {
+ session = value;
+ }
+
+ /**
+ * <p>Provide session context.</p>
+ *
+ * @return session context
+ */
+ public Map getSession() {
+ return session;
+ }
+
+ // ---- Task property (utilized by UI) ----
+
+ /**
+ * <p>Field to store workflow task.</p>
+ * <p/>
+ * <p>The Task is used to track the state of the CRUD workflows. It can be
+ * set to Constant.CREATE, Constant.EDIT, or Constant.DELETE as
+ * needed.</p>
+ */
+ private String task = null;
+
+
+ /**
+ * <p>Provide worklow task.</p>
+ *
+ * @return Returns the task.
+ */
+ public String getTask() {
+ return task;
+ }
+
+ /**
+ * <p>Store new workflow task.</p>
+ *
+ * @param value The task to set.
+ */
+ public void setTask(String value) {
+ task = value;
+ }
+
+ // ---- Token property (utilized by UI) ----
+
+ /**
+ * <p>Field to store double-submit guard.</p>
+ */
+ private String token = null;
+
+
+ /**
+ * <p>Provide Token.</p>
+ *
+ * @return Returns the token.
+ */
+ public String getToken() {
+ return token;
+ }
+
+ /**
+ * <p>Store new Token.</p>
+ *
+ * @param value The token to set.
+ */
+ public void setToken(String value) {
+ token = value;
+ }
+
+ // ---- Host property ----
+
+ /**
+ * <p>Field to store Support host.</p>
+ * <p/>
+ * <p> The host is an immutable property of the Subscrtion DAP object, so
+ * we need to store it locally until we are ready to create the
+ * Support. </p>
+ */
+ private String host;
+
+ /**
+ * <p>Provide tSubscription host.</p>
+ *
+ * @return host property
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * <p>Store new Support host.</p>
+ *
+ * @param value
+ */
+ public void setHost(String value) {
+ host = value;
+ }
+
+ // ---- Password property ----
+
+ /**
+ * <p>Field to store User password property.</p>
+ * <p/>
+ * <p>The User DAO object password proerty is immutable, so we store it
+ * locally until we are ready to create the object.</p>
+ */
+ private String password = null;
+
+
+ /**
+ * <p>Provide User password</p>
+ *
+ * @return Returns the password.
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * <p>Store new User Password</p>
+ *
+ * @param value The password to set.
+ */
+ public void setPassword(String value) {
+ password = value;
+ }
+
+ // ---- Password2 property (confirmation) ----
+
+ /**
+ * <p>Field to store the User password confirmation.</p>
+ * <p/>
+ * <p>When a User object is created, we ask the client to enter the
+ * password twice, to help ensure the password is being typed
+ * correctly.</p>
+ */
+ private String password2 = null;
+
+
+ /**
+ * <p>Provide the User password confirmation.</p>
+ *
+ * @return Returns the confirmationpassword.
+ */
+ public String getPassword2() {
+ return password2;
+ }
+
+ /**
+ * <p>Store a new User password confirmation.</p>
+ *
+ * @param value The confirmation password to set.
+ */
+ public void setPassword2(String value) {
+ password2 = value;
+ }
+
+ // ---- Username property ----
+
+ /**
+ * <p>Field to store User username.</p>
+ * <p/>
+ * <p>The User DAO object password proerty is immutable, so we store it
+ * locally until we are ready to create the object.</p>
+ */
+ private String username = null;
+
+
+ /**
+ * <p>Provide User username.</p>
+ *
+ * @return Returns the User username.
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * <p>Store new User username</p>
+ *
+ * @param value The username to set.
+ */
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ // ---- Database property ----
+
+ /**
+ * <p>Provide reference to UserDatabase, or null if the database is not
+ * available. </p>
+ *
+ * @return a reference to the UserDatabase or null if the database is not
+ * available
+ */
+ public UserDatabase getDatabase() {
+ Object db = getApplication().get(Constants.DATABASE_KEY);
+ if (db == null) {
+ this.addActionError(getText("error.database.missing"));
+ }
+ return (UserDatabase) db;
+ }
+
+ /**
+ * <p>Store a new reference to UserDatabase</p>
+ *
+ * @param database
+ */
+ public void setDatabase(UserDatabase database) {
+ getApplication().put(Constants.DATABASE_KEY, database);
+ }
+
+ // ---- User property ----
+
+ /**
+ * <p>Provide reference to User object for authenticated user.</p>
+ *
+ * @return User object for authenticated user.
+ */
+ public User getUser() {
+ return (User) getSession().get(Constants.USER_KEY);
+ }
+
+ /**
+ * <p>Store new reference to User Object.</p>
+ *
+ * @param user User object for authenticated user
+ */
+ public void setUser(User user) {
+ getSession().put(Constants.USER_KEY, user);
+ }
+
+ /**
+ * <p>Obtain User object from database, or return null if the credentials
+ * are not found or invalid.</p>
+ *
+ * @param username User username
+ * @param password User password
+ * @return User object or null if not found
+ * @throws ExpiredPasswordException
+ */
+ public User findUser(String username, String password)
+ throws ExpiredPasswordException {
+ // FIXME: Stupid testing hack to compensate for inadequate DAO layer
+ if (Constants.EXPIRED_PASSWORD_EXCEPTION.equals(username)) {
+ throw new ExpiredPasswordException(Constants.EXPIRED_PASSWORD_EXCEPTION);
+ }
+
+ User user = getDatabase().findUser(username);
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ this.addFieldError(Constants.PASSWORD_MISMATCH_FIELD,
+ getText("error.password.mismatch"));
+ }
+ return user;
+ }
+
+ /**
+ * <p><code>Log</code> instance for this application. </p>
+ */
+ protected Log log = LogFactory.getLog(Constants.PACKAGE);
+
+ /**
+ * <p> Persist the User object, including subscriptions, to the database.
+ * </p>
+ *
+ * @throws java.lang.Exception on database error
+ */
+ public void saveUser() throws Exception {
+ try {
+ getDatabase().save();
+ } catch (Exception e) {
+ String message = Constants.LOG_DATABASE_SAVE_ERROR + getUser()
+ .getUsername();
+ log.error(message, e);
+ throw new Exception(message, e);
+ }
+ }
+
+ public void createInputUser() {
+ User user = new MemoryUser(null, null);
+ setUser(user);
+ }
+
+ /**
+ * <p> Verify input for creating a new user, create the user, and process
+ * the login. </p>
+ *
+ * @return A new User and empty Errors if create succeeds, or null and
+ * Errors if create fails
+ */
+ public User createUser(String username, String password) {
+
+ UserDatabase database = getDatabase();
+ User user;
+
+ try {
+ user = database.findUser(username);
+ }
+
+ catch (ExpiredPasswordException e) {
+ user = getUser(); // Just so that it is not null
+ }
+
+ if (user != null) {
+ this.addFieldError("username", "error.username.unique");
+ return null;
+ }
+
+ return database.createUser(username);
+ }
+
+ // Since user.username is immutable, we have to use some local properties
+
+ /**
+ * <p>Use the current User object to create a new User object, and make
+ * the new User object the authenticated user.</p>
+ * <p/>
+ * <p>The "current" User object is usually a temporary object being used
+ * to capture input.</p>
+ *
+ * @param _username User username
+ * @param _password User password
+ */
+ public void copyUser(String _username, String _password) {
+ User input = getUser();
+ input.setPassword(_password);
+ User user = createUser(_username, _password);
+ if (null != user) {
+ BeanUtils.setValues(user, input, null);
+ setUser(user);
+ }
+ }
+
+ // ---- Support property ----
+
+ /**
+ * <p>Obtain the cached Support object, if any. </p>
+ *
+ * @return Cached Support object or null
+ */
+ public Subscription getSubscription() {
+ return (Subscription) getSession().get(Constants.SUBSCRIPTION_KEY);
+ }
+
+ /**
+ * <p>Store new User Support.</p>
+ *
+ * @param subscription
+ */
+ public void setSubscription(Subscription subscription) {
+ getSession().put(Constants.SUBSCRIPTION_KEY, subscription);
+ }
+
+ /**
+ * <p> Obtain User Support object for the given host, or return null
+ * if not found. </p>
+ * <p/>
+ * <p>It would be possible for this code to throw a NullPointerException,
+ * but the ExceptionHandler in the xwork.xml will catch that for us.</p>
+ *
+ * @return The matching Support or null
+ */
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = getUser().findSubscription(host);
+ return subscription;
+ }
+
+ /**
+ * <p>Obtain uSER Support for the local Host property.</p>
+ * <p/>
+ * <p>Usually, the host property will be set from the client request,
+ * because it was embedded in a link to the Subcription action.
+ *
+ * @return Support or null if not found
+ */
+ public Subscription findSubscription() {
+ return findSubscription(getHost());
+ }
+
+ /**
+ * <p>Provide a "temporary" User Support object that can be used to
+ * capture input values.</p>
+ */
+ public void createInputSubscription() {
+ Subscription sub = new MemorySubscription(getUser(), null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+
+ /**
+ * <p>Provide new User Support object for the given host, or null if
+ * the host is not unique.</p>
+ *
+ * @param host
+ * @return New User Support object or null
+ */
+ public Subscription createSubscription(String host) {
+
+ Subscription sub;
+
+ sub = findSubscription(host);
+
+ if (null != sub) {
+ // FIXME - localization - "error.host.unique")
+ addFieldError(Constants.HOST, "That hostname is already defined");
+ return null;
+ }
+
+ return getUser().createSubscription(host);
+ }
+
+ /**
+ * <p>Create a new Support from the current Support object,
+ * making the new Support the current Support. </p>
+ * <p/>
+ * <p>Usually, the "current" Support is a temporary object being used
+ * to capture input values.</p>
+ *
+ * @param host
+ */
+ public void copySubscription(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ BeanUtils.setValues(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }
+
+ /**
+ * <p>Delete the current Support object from the database.</p>
+ */
+ public void removeSubscription() {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(Constants.SUBSCRIPTION_KEY);
+ }
+
+ /**
+ * <p>Provide MailServer Host for current User Support.</p>
+ *
+ * @return MailServer Host for current User Support
+ */
+ public String getSubscriptionHost() {
+ Subscription sub = getSubscription();
+ if (null == sub) {
+ return null;
+ }
+ return sub.getHost();
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport.properties b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport.properties
new file mode 100644
index 0000000..df33d47
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport.properties
@@ -0,0 +1,93 @@
+button.cancel=Cancel
+button.confirm=Confirm
+button.doSubmit=DO_SUBMIT
+button.doReset=DO_RESULT
+button.doCancel=org.apache.struts.taglib.html.CANCEL
+button.reset=Reset
+button.save=Save
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+error.database.missing=User database is missing, cannot validate logon credentials
+error.fromAddress.format=Invalid format for From Address
+error.fromAddress.required=From Address is required
+error.fullName.required=Full Name is required
+error.host.required=Mail Server is required
+error.noSubscription=No Subscription bean in user session
+error.password.expired=Your password has expired for username {0}
+error.password.required=Password is required
+error.password2.required=Confirmation password is required
+error.password.match=Password and confirmation password must match
+error.password.mismatch=Invalid username and/or password, please try again
+error.replyToAddress.format=Invalid format for Reply To Address
+struts.messages.invalid.token=Cannot submit this form out of order
+error.type.invalid=Server Type must be 'imap' or 'pop3'
+error.type.required=Server Type is required
+error.username.required=Username is required
+error.username.unique=That username is already in use - please select another
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O exception rendering error messages: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.logon=Log on to the MailReader Demonstration Application
+index.registration=Register with the MailReader Demonstration Application
+index.title=MailReader Demonstration Application
+index.tour=A Walking Tour of the MailReader Demonstration Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+logon.title=MailReader Demonstration Application - Logon
+mainMenu.heading=Main Menu Options for
+mainMenu.logoff=Log off MailReader Demonstration Application
+mainMenu.registration=Edit your user registration profile
+mainMenu.title=MailReader Demonstration Application - Main Menu
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+# prompt.
+autoConnect=Auto Connect
+fromAddress=From Address
+fullName=Full Name
+mailHostname=Mail Server
+mailPassword=Mail Password
+mailServerType=Server Type
+mailUsername=Mail Username
+password=Password
+password2=(Repeat) Password
+replyToAddress=Reply To Address
+username=Username
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+registration.title.create=Register for the MailReader Demonstration Application
+registration.title.edit=Edit Registration for the MailReader Demonstration Application
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
+errors.literal=${getText(fieldName)}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport_ja.properties b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport_ja.properties
new file mode 100644
index 0000000..df4f174
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport_ja.properties
@@ -0,0 +1,89 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
+change.try=\u518D\u8A66\u884C
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
+error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
+error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
+error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
+error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
+error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
+struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
+error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
+error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
+error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.logon=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+logon.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+mainMenu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+mainMenu.logoff=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+mainMenu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+mainMenu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+# prompt.
+autoConnect=\u81ea\u52d5\u63a5\u7d9a
+fromAddress=From\u30a2\u30c9\u30ec\u30b9
+fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
+mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
+mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
+mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
+replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
+username=\u30e6\u30fc\u30b6\u540d
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
+errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
+errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport_ru.properties b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport_ru.properties
new file mode 100644
index 0000000..b80ecd5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MailreaderSupport_ru.properties
@@ -0,0 +1,89 @@
+button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
+button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
+button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
+button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
+error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
+error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
+error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
+error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
+error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.password.expired=Your password has expired for username {0}
+error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
+error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
+error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
+error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
+error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
+struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
+error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
+error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
+error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
+errors.prefix=<li>
+errors.suffix=</li>
+errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
+expired.password=User Password has expired for {0}
+heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
+heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
+heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
+heading.user=\u0418\u043c\u044f
+heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
+heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
+index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+index.logon=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
+index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
+index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
+linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
+linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
+linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
+logon.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
+mainMenu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f
+mainMenu.logoff=\u0412\u044b\u0439\u0442\u0438
+mainMenu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438
+mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e
+option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP
+option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3
+# prompt.
+autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435:
+fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:
+fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f:
+mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440:
+mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430:
+password=\u041f\u0430\u0440\u043e\u043b\u044c:
+password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c:
+replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:
+username=\u0418\u043c\u044f:
+registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
+registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
+registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
+registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
+registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438
+subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443
+
+# Standard error messages for validator framework checks
+errors.required=${getText(fieldName)} is required.
+errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
+errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters.
+errors.invalid=${getText(fieldName)} is invalid.
+errors.byte=${getText(fieldName)} must be an byte.
+errors.short=${getText(fieldName)} must be an short.
+errors.integer=${getText(fieldName)} must be an integer.
+errors.long=${getText(fieldName)} must be an long.
+errors.float=${getText(fieldName)} must be an float.
+errors.double=${getText(fieldName)} must be an double.
+errors.date=${getText(fieldName)} is not a date.
+errors.range=${getText(fieldName)} is not in the range {1} through {2}.
+errors.creditcard=${getText(fieldName)} is not a valid credit card number.
+errors.email=${getText(fieldName)} is an invalid e-mail address.
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MainMenu.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MainMenu.java
new file mode 100644
index 0000000..dfa5e6c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/MainMenu.java
@@ -0,0 +1,9 @@
+package mailreader2;
+
+/**
+ * <p>
+ * Provide access to MailreaderSupport properties.
+ * </p>
+ */
+public class MainMenu extends MailreaderSupport {
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Welcome-action.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Welcome-action.xml
new file mode 100644
index 0000000..8577d07
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Welcome-action.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <package name="Welcome" namespace="/" extends="MailreaderSupport">
+
+ <action name="Welcome" class="mailreader2.Welcome">
+ <result>/pages/Welcome.jsp</result>
+ <interceptor-ref name="guest"/>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Welcome.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Welcome.java
new file mode 100644
index 0000000..ce54263
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/Welcome.java
@@ -0,0 +1,31 @@
+package mailreader2;
+
+import com.opensymphony.xwork2.Preparable;
+import com.opensymphony.xwork2.ModelDriven;
+import java.util.List;
+
+/**
+ * Verify that essential resources are available.
+ */
+public class Welcome extends MailreaderSupport {
+
+ public String execute() {
+
+ // Confirm message resources loaded
+ String message = getText(Constants.ERROR_DATABASE_MISSING);
+ if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
+ addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);
+ }
+
+ // Confirm database loaded
+ if (null == getDatabase()) {
+ addActionError(Constants.ERROR_DATABASE_NOT_LOADED);
+ }
+
+ if (hasErrors()) {
+ return ERROR;
+ } else {
+ return SUCCESS;
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Input.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Input.java
new file mode 100644
index 0000000..597bfaa
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Input.java
@@ -0,0 +1,9 @@
+package mailreader2.logon;
+
+import mailreader2.MailreaderSupport;
+
+/**
+ * <p>Stub class for login/Input.</p>
+ */
+public class Input extends MailreaderSupport {
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Retrieve-validation.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Retrieve-validation.xml
new file mode 100644
index 0000000..4a04c76
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Retrieve-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Retrieve.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Retrieve.java
new file mode 100644
index 0000000..b8d78ec
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/logon/Retrieve.java
@@ -0,0 +1,46 @@
+/*
+ * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $
+ *
+ * Copyright 2000-2004 Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mailreader2.logon;
+
+import mailreader2.MailreaderSupport;
+import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
+import org.apache.struts.apps.mailreader.dao.User;
+
+/**
+ * <p> Validate a user logon. </p>
+ */
+public final class Retrieve extends MailreaderSupport {
+
+ public String execute() throws ExpiredPasswordException {
+
+ User user = findUser(getUsername(), getPassword());
+
+ if (user != null) {
+ setUser(user);
+ }
+
+ if (hasErrors()) {
+ return INPUT;
+ }
+
+ return SUCCESS;
+
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Create-validation.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Create-validation.xml
new file mode 100644
index 0000000..ccf277b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Create-validation.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ <field-validator type="stringlength">
+ <param name="trim">true</param>
+ <param name="minLength">4</param>
+ <param name="maxLength">10</param>
+ <message key="errors.range"/>
+ </field-validator>
+ </field>
+
+ <field name="password2">
+ <field-validator type="requiredstring">
+ <message key="error.password2.required"/>
+ </field-validator>
+ </field>
+
+ <validator type="expression">
+ <param name="expression">password eq password2</param>
+ <message key="error.password.match"/>
+ </validator>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Create.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Create.java
new file mode 100644
index 0000000..53fdad9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Create.java
@@ -0,0 +1,37 @@
+package mailreader2.registration;
+
+import mailreader2.Constants;
+import org.apache.struts.apps.mailreader.dao.User;
+
+/**
+ * <p>Insert new user, providing extra validation.</p>
+ * <p/>
+ * <p>(On an update, the password change is optional.)</p>
+ */
+public final class Create extends Update {
+
+ public String execute()
+ throws Exception {
+
+ // trust but verify
+ boolean creating = Constants.CREATE.equals(getTask());
+ creating = creating && isCreating();
+ if (!creating) {
+ addActionError("registration/Create: ");
+ addActionError(Constants.ERROR_INVALID_WORKFLOW);
+ return ERROR;
+ }
+
+ User user = findUser(getUsername(), getPassword());
+ boolean haveUser = (user != null);
+
+ if (haveUser) {
+ addActionError(getText("error.username.unique"));
+ return INPUT;
+ }
+
+ copyUser(getUsername(), getPassword());
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Input.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Input.java
new file mode 100644
index 0000000..a034366
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Input.java
@@ -0,0 +1,31 @@
+package mailreader2.registration;
+
+import mailreader2.Constants;
+
+/**
+ * <p> Retrieve User object to edit or null if User does not exist. </p>
+ */
+public class Input extends Support {
+
+ /**
+ * <p> Retrieve User object to edit or null if User does not exist. </p>
+ *
+ * @return The "Success" result for this mapping
+ * @throws Exception on any error
+ */
+ public String execute() throws Exception {
+
+ if (isCreating()) {
+ createInputUser();
+ setTask(Constants.CREATE);
+ } else {
+ setTask(Constants.EDIT);
+ setUsername(getUser().getUsername());
+ setPassword(getUser().getPassword());
+ setPassword2(getUser().getPassword());
+ }
+
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Support.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Support.java
new file mode 100644
index 0000000..0316314
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Support.java
@@ -0,0 +1,20 @@
+package mailreader2.registration;
+
+import mailreader2.MailreaderSupport;
+import org.apache.struts.apps.mailreader.dao.User;
+
+/**
+ * <p>Base class to store shared methods.</p>
+ */
+public class Support extends MailreaderSupport {
+
+ /**
+ * <p>Double check that there is not a valid User logon. </p>
+ *
+ * @return True if there is not a valid User logon
+ */
+ protected boolean isCreating() {
+ User user = getUser();
+ return (null == user) || (null == user.getDatabase());
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Update-validation.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Update-validation.xml
new file mode 100644
index 0000000..44d66bc
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Update-validation.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="user.fullName">
+ <field-validator type="requiredstring">
+ <message key="error.fullName.required"/>
+ </field-validator>
+ </field>
+
+ <field name="user.fromAddress">
+ <field-validator type="requiredstring">
+ <message key="error.fromAddress.required"/>
+ </field-validator>
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+ <field name="user.replyToAddress">
+ <field-validator type="email">
+ <message key="errors.email"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Update.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Update.java
new file mode 100644
index 0000000..7d116dc
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/registration/Update.java
@@ -0,0 +1,45 @@
+package mailreader2.registration;
+
+import mailreader2.Constants;
+
+/**
+ * <p> Update Registration object to the persistent store. </p>
+ */
+public class Update extends Support {
+
+ private String fixNull(String value) {
+ if (value == null) return null;
+ String buffer = value.trim();
+ if (buffer.length() == 0) return null;
+ return buffer;
+ }
+
+ public String execute()
+ throws Exception {
+
+ boolean creating = Constants.CREATE.equals(getTask());
+ creating = creating && isCreating(); // trust but verify
+ if (creating) {
+ addActionError("registration/Update: ");
+ addActionError(Constants.ERROR_INVALID_WORKFLOW);
+ return ERROR;
+ }
+ // FIXME: Any way to call the Update validators from here?
+ String newPassword = fixNull(getPassword());
+ String confirmPassword = fixNull(getPassword2());
+ if (newPassword != null) {
+ boolean matches = ((confirmPassword != null)
+ && (confirmPassword.equals(newPassword)));
+ if (matches) {
+ getUser().setPassword(newPassword);
+ } else {
+ addActionError(getText("error.password.match"));
+ return INPUT;
+ }
+ }
+
+ saveUser();
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Delete.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Delete.java
new file mode 100644
index 0000000..893916f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Delete.java
@@ -0,0 +1,15 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p>Prepare to present a confirmation page before removing
+ * subscription.</p>
+ */
+public class Delete extends Edit {
+
+ public String execute() throws Exception {
+ setTask(Constants.DELETE);
+ return find();
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Edit-validation.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Edit-validation.xml
new file mode 100644
index 0000000..df903c2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Edit-validation.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="host">
+ <field-validator type="requiredstring">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Edit.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Edit.java
new file mode 100644
index 0000000..1baf3f9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Edit.java
@@ -0,0 +1,16 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p>Prepare to edit User Support.</p>
+ */
+public class Edit extends Support {
+
+ public String execute() throws Exception {
+ setTask(Constants.EDIT);
+ return find();
+ }
+
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Input.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Input.java
new file mode 100644
index 0000000..2053dd6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Input.java
@@ -0,0 +1,17 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p>Setup a temporary User Support object to capture input
+ * values.</p>
+ */
+public class Input extends Support {
+
+ public String execute() {
+ createInputSubscription();
+ setTask(Constants.CREATE);
+ return SUCCESS;
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Support.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Support.java
new file mode 100644
index 0000000..1b880e9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Support.java
@@ -0,0 +1,69 @@
+package mailreader2.subscription;
+
+import com.opensymphony.xwork2.Preparable;
+import mailreader2.MailreaderSupport;
+import mailreader2.Constants;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * <p> Provide an Edit method for retrieving an existing subscription, and a
+ * Update method for updating or inserting a subscription. </p>
+ */
+public class Support extends MailreaderSupport
+ implements Preparable {
+
+ /**
+ * <p>Field to store list of MailServer types</p>
+ */
+ private Map types = null;
+
+ /**
+ * <p>Provide the list of MailServer types.</p>
+ *
+ * @return List of MailServer types
+ */
+ public Map getTypes() {
+ return types;
+ }
+
+ /**
+ * <p>Setup the MailerServer types and set the local Host property from
+ * the User Support (if any). </p>
+ */
+ public void prepare() {
+
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+
+ setHost(getSubscriptionHost());
+
+ }
+
+ /**
+ * <p>Load User Support for the local Host property.</p>
+ * <p/>
+ * <p>Usually, the Host is being set from the request by a link to an Edit
+ * or Delete task.</p>
+ *
+ * @return INPUT or Error, if Support is not found
+ */
+ public String find() {
+
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+
+ if (sub == null) {
+ addActionError("find (Subscription): ");
+ addActionError(Constants.ERROR_INVALID_WORKFLOW);
+ return ERROR;
+ }
+
+ setSubscription(sub);
+
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Update-validation.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Update-validation.xml
new file mode 100644
index 0000000..9f2f6d7
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Update-validation.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+
+ <field name="subscription.username">
+ <field-validator type="requiredstring">
+ <message key="error.username.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.password">
+ <field-validator type="requiredstring">
+ <message key="error.password.required"/>
+ </field-validator>
+ </field>
+
+ <field name="subscription.type">
+ <field-validator type="requiredstring">
+ <message key="error.type.invalid"/>
+ </field-validator>
+ </field>
+
+</validators>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Update.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Update.java
new file mode 100644
index 0000000..2c77f82
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/mailreader2/subscription/Update.java
@@ -0,0 +1,38 @@
+package mailreader2.subscription;
+
+import mailreader2.Constants;
+
+/**
+ * <p> Workaround class. Submitting to an alias doesn't seem to work. </p>
+ */
+public final class Update extends Edit {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ getSubscription().setAutoConnect(false);
+ }
+
+ /**
+ * <p> Examine the Task property and DELETE, CREATE, or save the User
+ * Support, as appropriate. </p>
+ *
+ * @return SUCCESS
+ * @throws Exception on a database error
+ */
+ public String execute() throws Exception {
+
+ if (Constants.DELETE.equals(getTask())) {
+ removeSubscription();
+ }
+
+ if (Constants.CREATE.equals(getTask())) {
+ copySubscription(getHost());
+ }
+
+ if (hasErrors()) return INPUT;
+
+ saveUser();
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/struts.properties b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/struts.properties
new file mode 100644
index 0000000..8e355e3
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/struts.properties
@@ -0,0 +1,3 @@
+struts.objectFactory = spring
+struts.devMode = true
+struts.enable.DynamicMethodInvocation = false
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/struts.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/struts.xml
new file mode 100644
index 0000000..4e7a8e1
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/java/struts.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <include file="struts-default.xml"/>
+
+ <package name="default" namespace="" extends="struts-default">
+
+ <global-results>
+ <result name="error">/pages/Error.jsp</result>
+ <result name="invalid.token">/pages/Error.jsp</result>
+ <result name="success" type="redirect-action">MainMenu</result>
+ <result name="expired" type="chain">ChangePassword</result>
+ </global-results>
+
+ <global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Throwable"/>
+ <exception-mapping
+ exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
+ result="expired"/>
+ </global-exception-mappings>
+
+ <!-- goto actions: Exit to another workflow -->
+
+ <action name="subscription/Save" class="mailreader2.subscription.Update">
+ <result name="input">/pages/subscription.jsp</result>
+ <result type="redirect-action">registration/+Input</result>
+ </action>
+
+ <!-- display actions: Welcome, Logoff, MainMenu -->
+
+ <action name="*" class="mailreader2.{1}">
+ <result>/pages/{1}.jsp</result>
+ </action>
+
+ <!-- prepare actions: Confirm/Delete, Edit, Input -->
+
+ <action name="*/+*" class="mailreader2.{1}.{2}">
+ <result>/pages/{1}.jsp</result>
+ </action>
+
+ <!-- execute actions: Create, Retrieve, Update, Update -->
+
+ <action name="*/*" class="mailreader2.{1}.{2}">
+ <result name="input">/pages/{1}.jsp</result>
+ </action>
+
+ </package>
+
+</struts>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/alternate.properties b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/alternate.properties
new file mode 100644
index 0000000..45f4dd5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/alternate.properties
@@ -0,0 +1,3 @@
+password=Enter your Password here ==>
+struts.logo.path=/struts-power.gif
+struts.logo.alt=Powered by Struts
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/alternate_ja.properties b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/alternate_ja.properties
new file mode 100644
index 0000000..981adc8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/alternate_ja.properties
@@ -0,0 +1 @@
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b==>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/applicationContext.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..b98e1d8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/applicationContext.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans default-autowire="autodetect">
+ <!-- add your spring beans here -->
+</beans>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/database.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/database.xml
new file mode 100644
index 0000000..0bc833d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/resources/database.xml
@@ -0,0 +1,13 @@
+<?xml version='1.0'?>
+<database>
+ <user username="user" fromAddress="John.User@somewhere.com"
+ fullName="John Q. User" password="pass">
+ <subscription host="mail.hotmail.com" autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user>
+</database>
+
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/META-INF/context.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..9b0b5d0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context path="/">
+</Context>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/WEB-INF/web.xml b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..758310a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Struts 2 Mailreader</display-name>
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath*:applicationContext*.xml</param-value>
+ </context-param>
+
+ <filter>
+ <filter-name>Struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>Struts2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <!-- Application Listener for Mailreader database -->
+ <listener>
+ <listener-class>
+ mailreader2.ApplicationListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+</web-app>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/css/mailreader.css b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/css/mailreader.css
new file mode 100644
index 0000000..bfc7648
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/css/mailreader.css
@@ -0,0 +1,46 @@
+/**
+* Mailreader stylesheet
+*/
+
+body {
+ background-color: #FFFFFF;
+ color: #000000;
+ link: 000066;
+ visited: #660066;
+ active: #33CCCC;
+}
+
+A:hover {
+ color: #FF0000;
+}
+
+h1 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h5 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h6 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+font.hint {
+ font-style: italic;
+ font-size: 80%;
+ font-family: Arial, Helvetica, sans-serif;
+ text-align: left;
+}
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/index.html b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/index.html
new file mode 100644
index 0000000..528d5f4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.action">
+</head>
+
+<body>
+<p>Loading ...</p>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/ChangePassword.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/ChangePassword.jsp
new file mode 100644
index 0000000..37d85be
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/ChangePassword.jsp
@@ -0,0 +1,25 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="change.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+
+<p>
+ <s:text name="change.message"/>
+</p>
+
+<p>
+ <a href="<s:url action="Logon"/>">
+ <s:text name="change.try"/>
+ </a>
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Error.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Error.jsp
new file mode 100644
index 0000000..481eddb
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Error.jsp
@@ -0,0 +1,40 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Unexpected Error</title>
+</head>
+
+<body>
+<h2>An unexpected error has occured</h2>
+
+<p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+</p>
+
+<hr/>
+
+<h3>Error Message</h3>
+
+<s:actionerror/>
+
+<p>
+ <s:property value="%{exception.message}"/>
+</p>
+
+<hr/>
+
+<h3>Technical Details</h3>
+
+<p>
+ <s:property value="%{exceptionStack}"/>
+</p>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Footer.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Footer.jsp
new file mode 100644
index 0000000..b2eae1e
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Footer.jsp
@@ -0,0 +1,6 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<hr/>
+
+<p>
+ <a href="<s:url action="Welcome" />"><s:text name="index.title"/></a>
+</p>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Logoff.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Logoff.jsp
new file mode 100644
index 0000000..8928aea
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Logoff.jsp
@@ -0,0 +1 @@
+<% response.sendRedirect("Welcome.action"); %>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/MainMenu.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/MainMenu.jsp
new file mode 100644
index 0000000..ed5d804
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/MainMenu.jsp
@@ -0,0 +1,33 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="mainMenu.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h3><s:text name="mainMenu.heading"/> <s:property
+ value="user.fullName"/></h3>
+<ul>
+ <li>
+ <s:url id="Input" action="registration/+Input" />
+ <s:a href="%{Input}">
+ <s:text name="mainMenu.registration"/>
+ </s:a>
+ </li>
+ <li>
+ <s:url id="Logoff" action="Logoff"/>
+ <s:a href="%{Logoff}">
+ <s:text name="mainMenu.logoff"/>
+ </s:a>
+ </li>
+</ul>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Welcome.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Welcome.jsp
new file mode 100644
index 0000000..0604974
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/Welcome.jsp
@@ -0,0 +1,64 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><s:text name="index.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body>
+<h3><s:text name="index.heading"/></h3>
+
+<ul>
+ <li>
+ <s:url id="registration" action="registration/+Input" />
+ <s:a href="%{registration}"><s:text name="index.registration"/></s:a>
+ </li>
+ <li>
+ <s:url id="logon" action="logon/+Input"/>
+ <s:a href="%{logon}"><s:text name="index.logon"/></s:a>
+ </li>
+</ul>
+
+<h3>Language Options</h3>
+<ul>
+ <li>
+ <s:url id="en" action="Welcome">
+ <s:param name="request_locale">en</s:param>
+ </s:url>
+ <s:a href="%{en}">English</s:a>
+ </li>
+ <li>
+ <s:url id="ja" action="Welcome">
+ <s:param name="request_locale">ja</s:param>
+ </s:url>
+ <s:a href="%{ja}">Japanese</s:a>
+ </li>
+ <li>
+ <s:url id="ru" action="Welcome">
+ <s:param name="request_locale">ru</s:param>
+ </s:url>
+ <s:a href="%{ru}">Russian</s:a>
+ </li>
+</ul>
+
+<hr/>
+
+<p>
+ <s:i18n name="alternate">
+ <img src="<s:text name="struts.logo.path"/>"
+ alt="<s:text name="struts.logo.alt"/>"/>
+ </s:i18n>
+</p>
+
+<p>
+ <s:url id="Tour" action="Tour"/><s:a href="%{Tour}"><s:text name="index.tour"/></s:a>
+</p>
+
+</body>
+</html>
+
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/logon.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/logon.jsp
new file mode 100644
index 0000000..1f210d6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/logon.jsp
@@ -0,0 +1,30 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.logon_Retrieve.logon_Retrieve_username.focus()">
+
+<s:actionerror/>
+<s:form id="logon_Retrieve" action="logon/Retrieve" validate="true">
+ <s:textfield label="%{getText('username')}" name="username"/>
+
+ <s:password label="%{getText('password')}" name="password" showPassword="true"/>
+
+ <s:submit value="%{getText('button.save')}"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Welcome" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="Footer.jsp"/>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/registration.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/registration.jsp
new file mode 100644
index 0000000..c8bd45a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/registration.jsp
@@ -0,0 +1,130 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title><s:text name="registration.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="registration.title.edit"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.registration_Update.registration_Update_username.focus()">
+
+<s:actionerror/>
+<s:form id="registration_Update" action="registration/Update" validate="true">
+ <s:token/>
+ <s:hidden name="task"/>
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('username')}" name="username"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('username')}" name="username"/>
+ <s:hidden name="username"/>
+ </s:else>
+
+ <s:password label="%{getText('password')}" name="password"/>
+
+ <s:password label="%{getText('password2')}" name="password2"/>
+
+ <s:textfield label="%{getText('fullName')}"
+ name="user.fullName"/>
+
+ <s:textfield label="%{getText('fromAddress')}"
+ name="user.fromAddress"/>
+
+ <s:textfield label="%{getText('replyToAddress')}"
+ name="user.replyToAddress"/>
+
+ <s:if test="task == 'Create'">
+ <s:submit value="%{getText('button.save')}" action="registration/Create"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Welcome" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+ </s:if>
+ <s:else>
+ <s:submit value="%{getText('button.save')}"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit value="%{getText('button.cancel')}"
+ action="MainMenu" onclick="form.onsubmit=null"/>
+ </s:else>
+
+</s:form>
+
+<s:if test="task == 'Edit'">
+ <div align="center">
+ <h3><s:text name="heading.subscriptions"/></h3>
+ </div>
+
+ <table border="1" width="100%">
+
+ <tr>
+ <th align="center" width="30%">
+ <s:text name="heading.host"/>
+ </th>
+ <th align="center" width="25%">
+ <s:text name="heading.user"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.type"/>
+ </th>
+ <th align="center" width="10%">
+ <s:text name="heading.autoConnect"/>
+ </th>
+ <th align="center" width="15%">
+ <s:text name="heading.action"/>
+ </th>
+ </tr>
+
+ <s:iterator value="user.subscriptions">
+ <tr>
+ <td align="left">
+ <s:property value="host"/>
+ </td>
+ <td align="left">
+ <s:property value="username"/>
+ </td>
+ <td align="center">
+ <s:property value="type"/>
+ </td>
+ <td align="center">
+ <s:property value="autoConnect"/>
+ </td>
+ <td align="center">
+ <s:url id="Delete" action="subscription/+Delete" >
+ <s:param name="host" value="host"/>
+ </s:url>
+ <s:a href="%{Delete}">
+ <s:text name="registration.deleteSubscription"/>
+ </s:a>
+
+ <s:url id="Edit" action="subscription/+Edit">
+ <s:param name="host" value="host"/>
+ </s:url>
+ <s:a href="%{Edit}">
+ <s:text name="registration.editSubscription"/>
+ </s:a>
+ </td>
+ </tr>
+ </s:iterator>
+
+ </table>
+
+ <s:url id="Input" action="subscription/+Input" />
+ <s:a href="%{Input}"><s:text name="registration.addSubscription"/></s:a>
+
+</s:if>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/registration/Retrieve.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/registration/Retrieve.jsp
new file mode 100644
index 0000000..6595226
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/registration/Retrieve.jsp
@@ -0,0 +1,31 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.registration/Retrieve.username.focus()">
+
+<s:actionerror/>
+<s:url id="Retrieve" action="registration/Retrieve" />
+<s:form action="registration/Retrieve" validate="true">
+ <s:textfield label="%{getText('username')}" name="username"/>
+
+ <s:password label="%{getText('password')}" name="password" showPassword="true"/>
+
+ <s:submit value="%{getText('button.save')}"/>
+
+ <s:reset value="%{getText('button.reset')}"/>
+
+ <s:submit action="Welcome" value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="../Footer.jsp"/>
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/subscription.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/subscription.jsp
new file mode 100644
index 0000000..adac06d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/subscription.jsp
@@ -0,0 +1,68 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <s:if test="task=='Create'">
+ <title><s:text name="subscription.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="subscription.title.edit"/></title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title><s:text name="subscription.title.delete"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+</head>
+
+<body onLoad="self.focus();document.subscription_Update.subscription_Update_username.focus()">
+
+<s:actionerror/>
+<s:form id="subscription_Update" action="subscription/Update" validate="true">
+ <s:token/>
+ <s:hidden name="task"/>
+ <s:label label="%{getText('username')}" name="user.username"/>
+
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('mailHostname')}" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('mailHostname')}" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:label label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:label label="%{getText('mailServerType')}"
+ name="subscription.type"/>
+ <s:label label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.confirm')}"/>
+ </s:if>
+ <s:else>
+ <s:textfield label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:textfield label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:select label="%{getText('mailServerType')}"
+ name="subscription.type" list="types"/>
+ <s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.save')}"/>
+ <s:reset value="%{getText('button.reset')}"/>
+ </s:else>
+
+ <s:submit action="registration/+Input"
+ value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+</s:form>
+
+<jsp:include page="Footer.jsp"/>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/tour.jsp b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/tour.jsp
new file mode 100644
index 0000000..a6ceb46
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/pages/tour.jsp
@@ -0,0 +1,2431 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"/>
+ <link rel="stylesheet" type="text/css" href="../css/mailreader.css"/>
+
+ <title>A Walking Tour of the Struts 2 MailReader Application</title>
+</head>
+
+<body>
+<blockquote>
+<h2>A Walking Tour of the Struts 2 MailReader Application</h2>
+
+<p>
+ <i>
+ This article is meant to introduce a new user to Apache Struts 2 by
+ "walking through" a simple, but functional, application.
+ The article includes code snippets, but for the best result, you might
+ want to install the MailReader application on your own development
+ workstation and follow along.
+ Of course, the full source code to the MailReader is included in the
+ distribution.
+ </i>
+
+</p>
+
+<p>
+ <i>
+ The tour assumes the reader has a basic understanding of the Java
+ language, JavaBeans, web applications, and JavaServer Pages. For
+ background on these technologies, see the
+ <a href="http://struts.apache.org/primer.html">
+ Key Technologies Primer</a>.
+ </i>
+</p>
+
+<hr/>
+
+<p>Logging In</p>
+
+<ul>
+ <li>
+ <a href="#Welcome">Welcome</a>
+
+ <ul>
+ <li><a href="#web.xml">web.xml and resources.properties</a></li>
+
+ <li><a href="#Welcome.do">Welcome.do</a></li>
+
+ <li><a href="#Welcome.java">Welcome Action</a></li>
+
+ <li><a href="#global-results">Global Results</a></li>
+
+ <li><a href="#ApplicationListener.java">ApplicationListener.java</a></li>
+
+ <li><a href="#resources.properties">Message Resources</a></li>
+
+ <li><a href="#Welcome.jsp">Welcome Page</a></li>
+
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Logon">Logon</a>
+ <ul>
+
+ <li><a href="#Logon.jsp">Logon Page</a></li>
+
+ <li><a href="#Logon-validation.xml">Logon-validation.xml</a></li>
+
+ <li><a href="#Logon.java">Logon.java</a></li>
+
+ <li><a href="#MailreaderSupport.java">MailreaderSupport.java</a></li>
+
+ <li><a href="#Logon.xml">Logon Configuration</a></li>
+
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#MainMenu">MainMenu</a>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Registration.jsp">Registration page</a>
+ <ul>
+ <li><a href="#iterator">iterator</a></li>
+ </ul>
+ </li>
+</ul>
+
+<ul>
+ <li>
+ <a href="#Subscription">Subscription</a>
+
+ <ul>
+ <li><a href="#SubscriptionAction.java">Subscription.java</a>
+ </li>
+ </ul>
+ </li>
+</ul>
+<hr/>
+
+<p>
+ The premise of the MailReader is that it is the first iteration of a
+ portal application.
+ This version allows users to register and maintain a set of
+ accounts with various mail servers.
+ If completed, the application would let users read mail from their
+ accounts.
+</p>
+
+<p>
+ The MailReader application demonstrates registering with an application,
+ logging into an application, maintaining a master record, and maintaining
+ child records.
+ This article overviews the constructs needed to do these things,
+ including the server pages, Java classes, and configuration elements.
+</p>
+
+<p>
+ For more about the MailReader, including alternate implementations and a
+ set of formal Use Cases,
+ please visit the <a href="http://www.StrutsUniversity.org/MailReader">
+ Struts University MailReader site</a>.
+</p>
+
+<hr/>
+<blockquote>
+ <p><font class="hint">
+ <strong>JAAS</strong> -
+ Note that for compatibility and ease of deployment, the MailReader
+ uses "application-based" authorization.
+ However, use of the standard Java Authentication and Authorization
+ Service (JAAS) is recommended for most applications.
+ (See the <a
+ href="http://struts.apache.org/primer.html">
+ Key Technologies Primer</a> for more about
+ authentication technologies.)
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The tour starts with how the initial welcome page is displayed, and
+ then steps through logging into the application and editing a subscription.
+ Please note that this not a quick peek at a "Hello World" application.
+ The tour is a rich trek into a realistic, best practices application.
+ You may need to adjust your chair and get a fresh cup of coffee.
+ Printed, the article is 29 pages long (US).
+</p>
+
+<h3><a name="Welcome" id="Welcome">Welcome Page</a></h3>
+
+<p>
+ A web application, like any other web site, can specify a list of welcome pages.
+ When you open a web application without specifying a particular page, a
+ default "welcome page" is served as the response.
+</p>
+
+<h4><a name="web.xml" id="web.xml">web.xml</a></h4>
+
+<p>
+ When a web application loads,
+ the container reads and parses the "Web Application Deployment
+ Descriptor", or "web.xml" file.
+ The framework plugs into a web application via a servlet filter.
+ Like any filter, the "struts2" filter is deployed via the "web.xml".
+</p>
+
+<hr/>
+<h5>web.xml - The Web Application Deployment Descriptor</h5>
+<pre><code><?xml version="1.0" encoding="ISO-8859-1"?>
+ <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+ <web-app>
+
+ <display-name>Struts 2 MailReader</display-name>
+
+ <strong><filter>
+ <filter-name>struts2</filter-name>
+ <filter-class>
+ org.apache.struts2.dispatcher.FilterDispatcher
+ </filter-class>
+ </filter></strong>
+
+ <filter-mapping>
+ <filter-name><strong>struts2</strong></filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <!-- Application Listener for MailReader database -->
+ <listener>
+ <listener-class>
+ mailreader2.ApplicationListener
+ </listener-class>
+ </listener>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ </web-app></code></pre>
+<hr/>
+
+<p>
+ Among other things,
+ the web.xml specifies the "Welcome File List" for an application.
+ When a web address refers to a directory rather than an individual file,
+ the container consults the Welcome File List for the name of a page to
+ open by default.
+</p>
+
+<p>
+ However, most Struts applications do not refer to physical pages,
+ but to "virtual resources" called <i>actions</i>.
+ Actions specify code that we want to be run before a page
+ or other resource renders the response.
+ An accepted practice is to never link directly to server pages,
+ but only to logical action mappings.
+ By linking to actions, developers can often "rewire" an application
+ without editing the server pages.
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Link actions not pages."</font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The actions are listed in one or more XML configuration files,
+ the default configuration file being named "struts.xml".
+ When the application loads, the struts.xml, and any other files
+ it includes, are parsed, and the framework creates a set of
+ configuration objects.
+ Among other things, the configuration maps a request for a certain
+ page to a certain action mapping.
+</p>
+
+<p>
+ Sites can list zero or more "Welcome" pages in the web.xml.
+ Unless you are using Java 1.5, actions cannot be specified as a Welcome
+ page.
+ So, in the case of a Welcome page,
+ how do we follow the best practice of navigating through actions
+ rather than pages?
+</p>
+
+<p>
+ One solution is to use a page to "bootstrap" one of our actions.
+ We can register the usual "index.html" as the Welcome page and have it
+ redirect to a "Welcome" action.
+</p>
+
+<hr/>
+<h5>MailReader's index.html</h5>
+<pre><code><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+ <html><head>
+ <META HTTP-EQUIV="Refresh" CONTENT="0;<strong>URL=Welcome.do</strong>">
+ </head>
+ <body>
+ <p>Loading ...</p>
+ </body></html></code></pre>
+<hr/>
+
+<p>
+ As an alternative,
+ we could also have used a JSP page that issued the redirect with a Struts tag,
+ but a plain HTML solution works as well.
+</p>
+
+<h4><a name="Welcome.do" id="Welcome.do">Welcome.do</a></h4>
+
+<p>
+ When the client requests "Welcome.do", the request is passed to the "struts2" FilterDispatcher
+ (that we registered in the web.xml file).
+ The FilterDispatcher retrieves the appropriate action mapping from the
+ configuration.
+ If we just wanted to forward to the Welcome page, we could use a simple
+ configuration element.
+</p>
+<hr/>
+<h5>A simple "forward thru" action element</h5>
+<pre><code><action name="<strong>Welcome</strong>">
+ <result><strong>/pages/Welcome.jsp</strong></result>
+ </action></code></pre>
+<hr/>
+
+<p>
+ If a client asks for the Welcome action ("Welcome.do), the "/page/Welcome.jsp"
+ page would be returned in response.
+ The client does not know, or need to know, that the physical resource is located at
+ "/pages/Welcome.jsp".
+ All the client knows is that it requested the resource "Welcome.do".
+</p>
+
+<p>
+ But if we peek at the configuration file for the MailReader,
+ we find a slightly more complicated XML element for the Welcome action.
+</p>
+
+<hr/>
+<h5>The Welcome action element</h5>
+<pre><code><action name="Welcome" <b>class="mailreader2.Welcome"</b>>
+ <result>/pages/Welcome.jsp</result>
+ <strong><interceptor-ref name="guest"/></strong>
+ </action></code></pre>
+<hr/>
+
+<p>
+ Here, the <strong>Welcome</strong> Java class executes whenever
+ someone asks for the Welcome action.
+ As it completes, the Action class can select which "result" is displayed.
+ The default result name is "success".
+ Another available result, defined at a global scope, is "error".
+</p>
+
+<hr/>
+<h5>Key concept:</h5>
+<blockquote>
+ <p>
+ The Action class doesn't need to know what result type is needed
+ for "success" or "error".
+ The Action can just return the logical name for a result,
+ without knowing how the result is implemented.
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ The net effect is that all of the result details,
+ including the paths to server pages,
+ all can be declared <em>once</em> in the configuration.
+ Tightly coupled implementation details are not scattered all over
+ the application.
+</p>
+
+<hr/>
+<h5>Key concept:</h5>
+<blockquote>
+ <p>
+ The Struts configuration lets us separate concerns and "say it once".
+ The configuration helps us "normalize" an application,
+ in much the same way we normalize a database schema.
+ </p>
+</blockquote>
+<hr/>
+
+
+<p>
+ OK ... but why would a Welcome Action want to choose between "success" and
+ "error"?
+</p>
+
+<h4><a name="Welcome.java" id="Welcome.java">Welcome Action</a></h4>
+
+<p>
+ The MailReader application retains a list of users along with their email
+ accounts.
+ The application stores this information in a database.
+ If the application can't connect to the database, the application can't do
+ its job.
+ So before displaying the Welcome <strong>page</strong>, the Welcome
+ <strong>class</strong> checks to see if the database is available.
+</p>
+
+<p>
+ The MailReader is also an internationalized application.
+ So, the Welcome Action class checks to see if the message resources are
+ available too.
+ If both resources are available, the class passes back the "success" token.
+ Otherwise, the class passes back the "error" token,
+ so that the appropriate messages can be displayed.
+</p>
+
+<hr/>
+<h5>The Welcome Action class</h5>
+<pre><code>package mailreader2;
+ public class Welcome extends MailreaderSupport {
+
+ public String execute() {
+
+ // Confirm message resources loaded
+ String message = getText(Constants.ERROR_DATABASE_MISSING);
+ if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
+ <strong>addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);</strong>
+ }
+
+ // Confirm database loaded
+ if (null==getDatabase()) {
+ <strong>addActionError(Constants.ERROR_DATABASE_NOT_LOADED);</strong>
+ }
+
+ if (hasErrors()) {
+ <strong>return ERROR;</strong>
+ }
+ else {
+ <strong>return SUCCESS;</strong>
+ }
+ }
+ }</code></pre>
+<hr/>
+
+<p>
+ Several common result names are predefined,
+ including ERROR, SUCCESS, LOGIN, NONE, and INPUT,
+ so that these tokens can be used consistently across Struts 2 applications.
+</p>
+
+
+<h4><a name="global-results" id="global-results">Global Results</a></h4>
+
+<p>
+ As mentioned, "error" is defined in a global scope.
+ Other actions may have trouble connecting to the database later,
+ or other unexpected errors may occur.
+ The MailReader defines the "error" result as a Global Result,
+ so that any action can use it.
+</p>
+
+<hr/>
+<h5>MailReader's global-result element</h5>
+<pre><code> <global-results>
+ <result name=<strong>"error"</strong>><strong>/pages/Error.jsp</strong></result>
+ <result name="invalid.token">/pages/Error.jsp</result>
+ <result name="login" type="redirect-action">Logon!input</result>
+ </global-results></code></pre>
+<hr/>
+
+<p>
+ Of course, if an individual action mapping defines its own "error" result type,
+ the local result would be used instead.
+</p>
+
+<h4><a name="ApplicationListener.java" id="ApplicationListener.java">ApplicationListener.java</a>
+</h4>
+
+<p>
+ The database is exposed as an object stored in application scope.
+ The database object is based on an interface.
+ Different implementations of the database could be loaded without changing
+ the rest of the application.
+ But how is the database object loaded in the first place?
+</p>
+
+<p>
+ The database is created by a custom Listener that we configured in the "web.xml".
+</p>
+
+<hr/>
+<h5>mailreader2.ApplicationListener</h5>
+<pre><code> <listener>
+ <listener-class>
+ <strong>mailreader2.ApplicationListener</strong>
+ </listener-class>
+ </listener></code></pre>
+<hr/>
+
+<p>
+ By default, our ApplicationListener loads a <strong>MemoryDatabase</strong>
+ implementation of the UserDatabase.
+ MemoryDatabase stores the database content as a XML document,
+ which is parsed and loaded as a set of nested hashtables.
+ The outer table is the list of user objects, each of which has its own
+ inner hashtable of subscriptions.
+ When you register, a user object is stored in this hashtable.
+ When you login, the user object is stored within the session context.
+</p>
+
+<p>
+ The database comes seeded with a sample user.
+ If you check the "database.xml" file under "/src/main",
+ you'll see the sample user described in XML.
+</p>
+
+<hr/>
+<h5>The "seed" user element from the MailReader database.xml</h5>
+<pre><code><user username="<strong>user</strong>" fromAddress="John.User@somewhere.com"
+ fullName="<strong>John Q. User</strong>" password="<strong>pass</strong>">
+ <subscription host="<strong>mail.hotmail.com"</strong> autoConnect="false"
+ password="bar" type="pop3" username="user1234">
+ </subscription>
+ <subscription host="<strong>mail.yahoo.com</strong>" autoConnect="false" password="foo"
+ type="imap" username="jquser">
+ </subscription>
+ </user></code></pre>
+<hr/>
+
+<p>
+ The "seed" user element creates a registration record for "John Q. User",
+ with the subscription detail for his hotmail and yahoo accounts.
+</p>
+
+<h4><a name="resources.properties" id="resources.properties">Message Resources</a>
+</h4>
+
+<p>
+ As mentioned, MailReader is an internationalized application.
+ The message resources for the application are loaded through a reference in the
+ "struts.properties" file.
+ Like the database contents, the "struts.properties" file is kept under
+ "/src/main/" in the source tree.
+</p>
+
+<hr/>
+<h5>struts.properties</h5>
+<pre><code>struts.custom.i18n.resources = <strong>resources</strong>
+ struts.action.extension = <strong>do</strong></code></pre>
+<hr/>
+
+<p>
+ When we specify "resources" in the properties file,
+ we are telling the framework to scan the classpath
+ for a Resource Bundle named "resources.properties".
+ The bundle might be embedded in a JAR, or found in the "WEB-INF/classes"
+ folder, or anywhere else on the runtime classpath.
+ In the MailReader, we keep the <strong>original</strong> bundle in the
+ source tree under "src/main/". When the application is built, the
+ properties files are <strong>copied</strong> to "WEB-INF/classes", so
+ that they are on the Java classpath.
+</p>
+
+<hr/>
+<h5>Message Resource entries used by the Welcome page</h5>
+<pre><code><strong>index.heading=</strong>MailReader Application Options
+ <strong>index.logon=</strong>Log on to the MailReader Application
+ <strong>index.registration=</strong>Register with the MailReader Application
+ <strong>index.title=</strong>MailReader Demonstration Application
+ <strong>index.tour=</strong>A Walking Tour of the MailReader Demonstration Application</code></pre>
+<hr/>
+
+<p>
+ If you change a message in the resource, and then rebuild and reload the
+ application, the change will appear throughout the application.
+ If you provide message resources for additional locales, you can
+ localize your application.
+ The MailReader provides resources for English, Russian, and Japanese.
+</p>
+
+<h4><a name="Welcome.jsp" id="Welcome.jsp">Welcome Page</a></h4>
+
+<p>
+ After confirming that the necessary resources exist, the Welcome action
+ forwards to the Welcome page.
+</p>
+<hr/>
+<h5>Welcome.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <strong><%@ taglib prefix="s" uri="http://struts.apache.org/tags" %></strong>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <title><strong><s:text name="index.title"/></strong></title>
+ <link href="<strong><s:url value="/css/mailreader.css"/></strong>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+
+ <body>
+ <h3><s:text name="index.heading"/></h3>
+
+ <ul>
+ <li><a href="<s:url action="Registration!input"/>"><s:text
+ name="index.registration"/></a></li>
+ <li><a href="<s:url action="Logon!input"/>"><s:text
+ name="index.logon"/></a></li>
+ </ul>
+
+ <h3>Language Options</h3>
+ <ul>
+ <li><a href="<s:url action="Welcome?request_locale=en"/>">English</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ja"/>">Japanese</a></li>
+ <li><a href="<s:url action="Welcome?request_locale=ru"/>">Russian</a></li>
+ </ul>
+
+ <hr />
+
+ <p><strong><s:i18n name="alternate"></strong>
+ <img src="<s:text name="struts.logo.path"/>"
+ alt="<s:text name="struts.logo.alt"/>"/>
+ <strong></s:i18n></strong></p>
+
+ <p><a href="<s:url action="Tour" />"><s:text name="index.tour"/></a></p>
+
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ At the top of the Welcome page, there are several directives that load the
+ Struts 2 tag libraries.
+ These are just the usual red tape that goes with any JSP file.
+ The rest of the page utilizes three Struts JSP tags:
+ "text", "url", and "i18n".
+</p>
+
+<p>
+ (We use the tag prefix "s:" in the Struts 2 MailReader application,
+ but you can use whatever prefix you like in your applications.)
+</p>
+
+<p>
+ The <strong>text</strong> tag inserts a message from an
+ application's default resource bundle.
+ If the framework's locale setting is changed for a user,
+ the text tag will render messages from the new locale's resource
+ bundle instead.
+</p>
+
+<p>
+ The <strong>url</strong> tag can render a reference to an
+ action or any other web resource,
+ applying "URL encoding" to the hyperlinks as needed.
+ Java's URL encoding feature lets your application maintain client state
+ without requiring cookies.
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p><font class="hint">
+ <strong>Cookies</strong> -
+ If you turn cookies off in your browser, and then reload your browser
+ and this page,
+ you will see the links with the Java session id information attached.
+ (If you are using Internet Explorer and try this,
+ be sure you reset cookies for the appropriate security zone,
+ and that you disallow "per-session" cookies.)
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The <strong>i18n</strong> tag provides access to multiple resource bundles.
+ The MailReader application uses a second set of message resources for
+ non-text elements.
+ When these are needed, we use the "i18n" tag to specify a different bundle.
+</p>
+
+<p>
+ The <strong>alternate</strong> bundle is stored next to the default bundle,
+ so that it ends up under "classes", which is on the application's class path.
+</p>
+
+<p>
+ In the span of a single request for the Welcome page, the framework has done
+ quite a bit already:
+</p>
+
+<ul>
+ <li>
+ Confirmed that required resources were loaded during initialization.
+ </li>
+
+ <li>
+ Written all the page headings and labels from internationalized
+ message resources.
+ </li>
+
+ <li>
+ Automatically URL-encoded paths as needed.
+ </li>
+</ul>
+
+<p>
+ When rendered, the Welcome page lists two menu options:
+ one to register with the application and one to log on (if you have
+ already registered).
+ Let's follow the Logon link first.
+</p>
+
+<h3><a name="Logon" id="Logon">Logon</a></h3>
+
+<p>
+ If you choose the Logon link, and all goes well, the Logon action forwards
+ control to the Logon page.
+</p>
+
+<h4><a name="Logon.jsp" id="Logon.jsp">Logon Page</a></h4>
+
+<p>
+ The Logon page displays a form that accepts a username and password.
+ You can use the default username and password to logon
+ (<strong>user</strong> and <strong>pass</strong>), if
+ you like. Try omitting or misspelling the username and password in
+ various combinations to see how the application reacts.
+ Note that both the username and password are case sensitive.
+</p>
+
+<hr/>
+<h5>Login.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title><s:text name="logon.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+ <body onLoad="self.focus();document.Logon.username.focus()">
+ <strong><s:actionerror/></strong>
+ <strong><s:form method="POST" validate="true"></strong>
+ <strong><s:textfield label="%{getText('username')}" name="username"/></strong>
+ <strong><s:password label="%{getText('password')}" name="password"/></strong>
+ <strong><s:submit value="%{getText('button.save')}"/></strong>
+ <strong><s:reset value="%{getText('button.reset')}"/></strong>
+ <s:submit <strong>action="Logon!cancel" onclick="form.onsubmit=null"</strong>
+ value="%{getText('button.cancel')}"/>
+ </s:form>
+ <jsp:include page="Footer.jsp"/>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ We already saw some of the tags used by the Logon page on the Welcome page.
+ Let's focus on the new tags.
+</p>
+
+<p>
+ The first new tag on the Logon page is <strong>actionerrors</strong>.
+ Most of the possible validation errors are related to a single field.
+ If you don't enter a username,
+ the framework can place an error message near the tag prompting you to
+ enter a username.
+ But some messages are not related to a single field.
+ For example, the database might be down.
+ If the action returns an "Action Error", as opposed to a "Field Error",
+ the messages are rendered in place of the "actionerror" tag.
+ The text for the validation errors, whether they are Action Errors or
+ Field Errors, can be specified in the resource bundle,
+ making the messages easy to manage and localize.
+</p>
+
+<p>
+ The second new tag is <strong>form</strong>.
+ This tag renders a HTML form tag.
+ By default, the form will submit back to whatever action invoked the page.
+ The "validate=true" setting enables client-side validation,
+ so that the form can be validated with JavaScript before being sent
+ back to the server.
+ The framework will still validate the form again, just to be sure, but the
+ client-side validation can save a few round-trips to the server.
+ You can use the method attribute to designate "GET" or "POST",
+ just like the HTML form tag.
+</p>
+
+<p>
+ Within the form tag,
+ we see four more new tags: "textfield", "password", "submit",
+ and "reset". We also see a second usage of "submit" that utilizes an
+ "action" attribute.
+</p>
+
+<p>
+ When we place a control on a form, we usually need to code a set of
+ HTML tags to do everything we want to do.
+ Most often, we do not just want a plain "input type=text" tag.
+ We want the input field to have a label too, and maybe even
+ a tooltip. And, of course, a place to print a message
+ should invalid data be entered.
+</p>
+
+<p>
+ The UI Tags support templates and themes so that a set of HTML tags can be
+ rendered from a single UI Tag. For example, the single tag
+</p>
+
+<pre><code>
+ <s:<strong>textfield</strong> label="%{getText('username')}" name="username"/>
+</code></pre>
+
+<p>
+ generates a wad of HTML markup.
+</p>
+
+<hr/>
+<pre><code><tr>
+ <td class="tdLabel">
+ <label for="Logon_username" class="label">Username:</label>
+ </td>
+ <td>
+ <input type="text" name="username" value="" id="Logon_username"/>
+ </td>
+ </tr></code></pre>
+<hr/>
+
+<p>
+ If for some reason you don't like the markup generated by a UI Tag,
+ it's each to change.
+ Each tag is driven by a template that can be updated on a tag-by-tag basis.
+ For example,
+ here is the default template that generates the markup for the ActionErrors tag:
+</p>
+
+<hr/>
+<pre><code><#if (actionErrors?exists && actionErrors?size > 0)>
+ <ul>
+ <#list actionErrors as error>
+ <li><span class="errorMessage">${error}</span></li>
+ </#list>
+ </ul>
+ </#if></code></pre>
+<hr/>
+
+<p>
+ If you wanted ActionErrors displayed in a table instead of a list,
+ you could edit a copy of this file, save it as a file named "actionerror.ftl",
+ and place this one file somewhere on your classpath.
+</p>
+
+<hr/>
+<pre><code><#if (actionErrors?exists && actionErrors?size > 0)>
+ <strong><table></strong>
+ <#list actionErrors as error>
+ <strong><tr><td></strong><span class="errorMessage">${error}</span><strong></td></tr></strong>
+ </#list>
+ <strong></table></strong>
+ </#if></code></pre>
+<hr/>
+
+<p>
+ Under the covers, the framework uses
+ <a href="http://freemarker.sourceforge.net/">Freemarker</a>
+ for its standard templating language.
+ FreeMarker is similar to
+ <a href="http://jakarta.apache.org/velocity/">Velocity</a>,
+ but it offers better error reporting and some additional features.
+ If you prefer, Velocity and JSP templates can also be used to create your own UI Tags.
+</p>
+
+<p>
+ The <strong>password</strong> tag renders a "input type=password"
+ tag, along with the usual template/theme markup.
+ By default, the password tag will not retain input if the submit fails.
+ If the username is wrong,
+ the client will have to enter the password again too.
+ (If you did want to retain the password when validation fails,
+ you can set the tag's "showPassword" property to true.)
+</p>
+
+<p>
+ Unsurprisingly, the <strong>submit</strong> and <strong>reset</strong> tags
+ render buttons of the corresponding types.
+</p>
+
+<p>
+ The second submit button is more interesting.
+</p>
+
+<pre><code> <s:submit <strong>action="Logon!cancel" onclick="form.onsubmit=null"</strong>
+ value="%{getText('button.cancel')}"/>
+</code></pre>
+
+<p>
+ Here we are creating the Cancel button for the form.
+ The button's attribute <em>action="Logon<strong>!</strong>cancel"</em>
+ tells the framework to submit to the Logon's "cancel" method
+ instead of the usual "execute" method.
+ The <em>onclick="form.onsubmit=null"</em> script defeats client-side validation.
+ On the server side, "cancel" is on a special list of methods that bypass validation,
+ so the request will go directly to the Action's <strong>cancel</strong> method.
+ (Other special aliases on the bypass list include "input" and "back".)
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p><font class="hint">
+ The UI tags have options and capabilities beyond what we have shown here.
+ For more see, the <a href="http://confluence.twdata.org/display/WW/Tags">UI Tag documentation.</a>
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ OK, but how do the tags know that both of these fields are required?
+ How do they know what message to display when the fields are empty?
+</p>
+
+<p>
+ For the answers, we need to look at another flavor of configuration file:
+ the "validation" file.
+</p>
+
+<h4><a name="Logon-validation.xml" id="Logon-validation.xml">Logon-validation.xml</a>
+</h4>
+
+<p>
+ While it is not hard to code data-entry validation into an Action class,
+ the framework provides an even easier way to validate input.
+</p>
+
+<p>
+ The validation framework is configured through another XML document, the <strong>
+ Logon-validation.xml</strong>.
+</p>
+
+<hr/>
+<h5>Validation file for Logon Action</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+ <validators>
+ <field name="<strong>username</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="<strong>error.username.required</strong>"/>
+ </field-validator>
+ </field>
+ <field name="<strong>password</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="<strong>error.password.required</strong>"/>
+ </field-validator>
+ </field>
+ </validators>
+</code></pre>
+<hr/>
+
+<p>
+ You may note that the DTD refers to "XWork".
+ <a href="http://www.opensymphony.com/xwork/">
+ Open Symphony XWork
+ </a> is a generic command-pattern framework that can be used outside of a
+ web environment. In practice, Struts 2 is a web-based extension of the
+ XWork framework.
+</p>
+
+<p>
+ The field elements correspond to the ActionForm properties.
+ The <strong>username</strong> and <strong>password</strong> field elements
+ say that each field depends on the "requiredstring" validator.
+ If the username is blank or absent, validation will fail and an error
+ message is generated.
+ The messages would be based on the "error.username.required" or
+ "error.password.required" message templates, from the resource bundle.
+</p>
+
+<!--
+<p>
+ The <strong>password</strong> field (or property) is also required.
+ In addition, it must also pass the "maxlength" and "minlength"
+ validations.
+ Here, the minimum length is three characters and the maximum length is
+ sixteen.
+ If the length of the password doesn't meet these criteria, a corresponding
+ error message is generated.
+ Of course, the messages are generated from the MessageResource bundles and
+ are easy to localize.
+</p>
+-->
+
+<h4><a name="Logon.java" id="Logon.java">Logon Action</a></h4>
+
+<p>
+ If validation passes, the framework invokes the "execute" method of the Logon Action.
+ The actual Logon Action is brief, since most of the functionality derives
+ from the base class, <strong>MailreaderSupport</strong>.
+</p>
+
+<hr/>
+<h5>Logon.java</h5>
+<pre><code>package mailreader2;
+ import org.apache.struts.apps.mailreader.dao.User;
+ public final class <strong>Logon</strong> extends MailreaderSupport {
+ public String <strong>execute()</strong> throws ExpiredPasswordException {
+ User user = <strong>findUser(getUsername(), getPassword());</strong>
+ if (user != null) {
+ <strong>setUser(user);</strong>
+ }
+ if (<strong>hasErrors()</strong>) {
+ return INPUT;
+ }
+ return SUCCESS;
+ }
+ }</code></pre>
+<hr/>
+
+<p>
+ Logon lays out what we do to authenticate a user.
+ We try to find the user using the credentials provided.
+ If the user is found, we cache a reference.
+ If the user is not found, we return "input" so the client can try again.
+ Otherwise, we return "success", so that the client can access the rest of the application.
+</p>
+
+<h4><a name="MailreaderSupport.java" id="MailreaderSupport.java">MailreaderSupport.java</a></h4>
+
+<p>
+ Let's look at the relevant properties and methods from MailreaderSupport
+ and another base class, <strong>ActionSupport</strong>, namely
+ "getUsername", "getPassword", "findUser", "setUser", and "hasErrors".
+</p>
+
+<p>
+ The framework lets you define
+ <a href="http://struts.apache.org/primer.html#javabeans">JavaBean properties</a>
+ directly on the Action.
+ Any JavaBean property can be used, including rich objects.
+ When a request comes in,
+ any public properties on the Action class are matched with the request parameters.
+ When the names match, the request parameter value is set to the JavaBean property.
+ The framework will make its best effort to convert the data,
+ and, if necessary, it will report any conversion errors.
+</p>
+
+<p>
+ The <strong>Username</strong> and <strong>Password</strong> properties are nothing fancy,
+ just standard JavaBean properties.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.getUsername() and getPassword()</h5>
+<pre><code>private String username = null;
+ public String <strong>getUsername()</strong> {
+ return this.username;
+ }
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ private String password = null;
+ public String <strong>getPassword()</strong> {
+ return this.password;
+ }
+ public void setPassword(String password) {
+ this.password = password;
+ }</code></pre>
+<hr/>
+
+<p>
+ We use these properties to capture the client's credentials,
+ and pass them to the more interesting <strong>findUser</strong> method.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.findUser</h5>
+<pre><code>public User <strong>findUser</strong>(String username, String password)
+ throws <strong>ExpiredPasswordException</strong> {
+ User user = <strong>getDatabase().findUser(username)</strong>;
+ if ((user != null) && !user.getPassword().equals(password)) {
+ user = null;
+ }
+ if (user == null) {
+ this.<strong>addFieldError</strong>("password", getText("error.password.mismatch"));
+ }
+ return user;
+ }</code></pre>
+<hr/>
+
+<p>
+ The "findUser" method dips into the MailReader Data Access Object layer,
+ which is represented by the <strong>Database</strong> property.
+ The code for the DAO layer is maintained as a separate component.
+ The MailReader application imports the DAO JAR,
+ but it is not responsible for maintaining any of the DAO source.
+ Keeping the data access layer at "arms-length" is a very good habit.
+ It encourages a style of development where the data access layer
+ can be tested and developed independently of a specific end-user application.
+ In fact, there are several renditions of the MailReader application,
+ all which share the same MailReader DAO JAR!
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Strongly separate data access and business logic from the rest of the application."</font>
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ When "findUser" returns,
+ the Logon Action looks to see if a valid (non-null) User object is returned.
+ A valid User is passed to the <strong>User property</strong>.
+ Although it is still a JavaBean property,
+ the User property is not implemented in quite the same way as Username and Password.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.setUser</h5>
+<pre><code>public User getUser() {
+ return (User) <strong>getSession().get(Constants.USER_KEY)</strong>;
+ }
+ public void setUser(User user) {
+ getSession().put(Constants.USER_KEY, user);
+ }</code></pre>
+<hr/>
+
+<p>
+ Instead of using a field to store the property value,
+ "setUser" passes it to a <strong>Session</strong> property.
+</p>
+
+<hr/>
+<h5>MailreaderSupport.getSession() and setSession()</h5>
+<pre><code>private Map session;
+ public Map <strong>getSession()</strong> {
+ return session;
+
+ public void <strong>setSession(Map value)</strong> {
+ session = value;
+ }</code></pre>
+<hr/>
+
+<p>
+ To look at the MailreaderSupport class, you would think the Session property is a plain-old Map.
+ In fact, the Session property is an adapter that is backed by the servlet session object at runtime.
+ The MailreaderSupport class doesn't need to know that though.
+ It can treat Session like any other Map.
+ We can also test the MailreaderSupport class by passing it some other implementation of Map,
+ running the test,
+ and then looking to see what changes MailreaderSupport made to our "mock" Session object.
+</p>
+
+<p>
+ But, when MailreaderSupport is running inside a web application,
+ how does it acquire a reference to the servlet session?
+</p>
+
+<p>
+ Good question. If you were to look at just the MailreaderSupport class,
+ you would not see a single line of code that sets the session property.
+ But, yet, when we run the class, the session property is not null.
+ Hmmm.
+</p>
+
+<p>
+ The magic that provides the Session property a runtime value is called "dependency injection".
+ The MailreaderSupport class implements a interface called <strong>SessionAware</strong>.
+ SessionAware is bundled with the framework, and it defines a setter for the Session property.
+</p>
+
+<p>
+ <code>public void <strong>setSession</strong>(Map session);</code>
+</p>
+
+<p>
+ Also bundled with the framework is an object called the <strong>ServletConfigInterceptor</strong>.
+ If the ServletConfigInterceptor sees that an Action implements the SessionAware interface,
+ it automatically set the session property.
+</p>
+
+<pre><code>if (action instanceof <code>SessionAware</code>) {
+ ((SessionAware) action).<code>setSession</code>(context.getSession());
+ }</code></pre>
+
+<p>
+ The framework uses these "Interceptor" classes to create a <strong>front controller</strong>
+ for each action an application defines.
+ Each Interceptor can peek at the request before an Action class is invoked,
+ and then again after the Action class is invoked.
+ (If you have worked with Servlet
+ <a href="http://struts.apache.org/primer.html#filters">Filters</a>,
+ you will recognize this pattern.
+ But, unlike Filters, Interceptors are not tied to HTTP.
+ Interceptors can be tested and developed outside of a web application.)
+</p>
+
+<p>
+ You can use the same set of Interceptors for all your actions,
+ or define a special set of Interceptors for any given action,
+ or define different sets of Interceptors to use with different types of actions.
+ The framework comes with a default set of Interceptors,
+ that it will use when another set is not specified,
+ but you can designate your own default Interceptor set (or "stack")
+ in the struts.xml configuration file.
+</p>
+
+<p>
+ Many Interceptors provide a utility or helper functions, like setting the session property.
+ Others, like the <strong>ValidationInterceptor</strong>, can change the workflow of an action.
+ Interceptors are key feature of the framework,
+ and we will see a few more on the tour.
+</p>
+
+<p>
+ If a valid User is not found, or the password doesn't match,
+ the "findUser" method invokes the <strong>addFieldError</strong> method to note the problem.
+ When "findUser" returns, the Logon Action checks for errors,
+ and then it returns either INPUT or SUCCESS.
+</p>
+
+<p>
+ The "addFieldError" method is provided by the ActionSupport class,
+ which is bundled with the framework.
+ The constants for INPUT and SUCCESS are also provided by ActionSupport.
+ While the ActionSupport class provides many useful utilities,
+ you are not required to use it as a base class.
+ Any Java class can be used as an Action, if you like.
+</p>
+
+<p>
+ It is a good practice to provide a base class with utilities
+ that can be shared by an application's Action classes.
+ The framework does this with ActionSupport,
+ and the MailReader application does the same with the MailreaderSupport class.
+</p>
+
+<hr/>
+<h5>Best Practice:</h5>
+<blockquote>
+ <p><font class="hint">"Use a base class to define common functionality."</font></p>
+</blockquote>
+<hr/>
+
+<p>
+ But, what happens if Logon returns INPUT instead of SUCCESS.
+ How does the framework know what to do next?
+</p>
+
+<p>
+ To answer that question,
+ we need to turn back to the "struts.xml" file and look at how Logon is configured.
+</p>
+
+
+<h4><a name="Logon.xml" id="Logon.xml">Logon Configuration</a></h4>
+
+<p>
+ The Logon action element outlines how the Logon workflow operates,
+ including what to do when the Action returns "input",
+ or the default result name "success".
+</p>
+
+<hr/>
+<h5>struts.xml Logon</h5>
+<pre><code><action name="<strong>Logon</strong>" class="mailreader2.registration.Retrieve">
+ <result name="<strong>input</strong>">/pages/Logon.jsp</result>
+ <result name="<strong>cancel</strong>" type="redirect-action">Welcome</result>
+ <result type="redirect-action">MainMenu</result>
+ <result name="<strong>expired</strong>" type="chain">ChangePassword</result>
+ <<strong>exception-mapping</strong>
+ exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
+ result="<strong>expired</strong>"/>
+ <interceptor-ref name="<strong>guest</strong>"/>
+ </action></code></pre>
+<hr/>
+
+<p>
+ In the Logon action element, the first result element is named "input".
+ If validation or authentification fail,
+ the Action class will return "input" and the framework will transfer control to the
+ "Logon.jsp" page.
+</p>
+
+<p>
+ The second result element is named <strong>cancel</strong>.
+ If someone presses the cancel button on the Logon page,
+ the Action class will return "cancel", this result will be selected,
+ and the framework will issue a redirect to the Welcome action.
+</p>
+
+<p>
+ The third result has no name,
+ so it will be called if the default <strong>success</strong> token is returned.
+ So, if the Logon succeeds,
+ control will transfer to the MainMenu action.
+</p>
+
+<p>
+ The MailReader DAO exposes a "ExpiredPasswordException".
+ If the DAO throws this exception when the User logs in,
+ the framework will process the exception-mapping
+ and transfer control to the "ChangePassword" action.
+</p>
+
+<p>
+ Just in case any other Exceptions are thrown,
+ the MailReader application also defines a global handler.
+</p>
+
+<hr/>
+<h5>struts.xml exception-mapping</h5>
+<pre><code><global-exception-mappings>
+ <exception-mapping
+ result="error"
+ exception="java.lang.Exception"/>
+ </global-exception-mappings></code></pre>
+<hr/>
+
+<p>
+ If an unexpected Exception is thrown,
+ the exception-mapping will transfer control to the action's "error" result,
+ or to a global "error" result.
+ The MailReader defines a global "error" result
+ which transfers control to an "Error.jsp" page
+ that can display the error message.
+</p>
+
+<hr/>
+<h5>Error.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Unexpected Error</title>
+ </head>
+ <body>
+ <h2>An unexpected error has occured</h2>
+ <p>
+ Please report this error to your system administrator
+ or appropriate technical support personnel.
+ Thank you for your cooperation.
+ </p>
+ <hr />
+ <h3>Error Message</h3>
+ <strong><s:actionerror /></strong>
+ <p>
+ <strong><s:property value="%{exception.message}"/></strong>
+ </p>
+ <hr />
+ <h3>Technical Details</h3>
+ <p>
+ <strong><s:property value="%{exceptionStack}"/></strong>
+ </p>
+ <jsp:include page="Footer.jsp"/>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ The Error page uses <strong>property</strong> tags to expose
+ the Exception message and the Exception stack.
+</p>
+
+<p>
+ Finally, the Logon action specifies an <strong>InterceptorStack</strong>
+ named <strong>defaultStack.</strong>
+ If you've worked with Struts 2 or WebWork 2 before, that might seem strange,
+ since "defaultStack" is the factory default.
+</p>
+
+<p>
+ In the MailReader application, most of the actions are only available
+ to authenticated users.
+ The exceptions are the Welcome, Logon, and Register actions
+ which are available to everyone.
+ To authenticate clients,
+ the MailReader uses a custom Interceptor and a custom Interceptor stack.
+</p>
+
+<hr/>
+<h5>mailreader2.AuthenticationInterceptor</h5>
+<pre><code>package mailreader2;
+ import com.opensymphony.xwork2.interceptor.Interceptor;
+ import com.opensymphony.xwork2.ActionInvocation;
+ import com.opensymphony.xwork2.Action;
+ import java.util.Map;
+ import org.apache.struts.apps.mailreader.dao.User;
+
+ public class <strong>AuthenticationInterceptor</strong> implements Interceptor {
+ public void destroy () {}
+ public void init() {}
+ public String <strong>intercept</strong>(ActionInvocation actionInvocation) throws Exception {
+ Map session = actionInvocation.getInvocationContext().getSession();
+ User user = (User) session.get(Constants.USER_KEY);
+ boolean isAuthenticated = (null!=user) && (null!=user.getDatabase());
+ if (<strong>isAuthenticated</strong>) {
+ return actionInvocation.invoke();
+ }
+ else {
+ return Action.LOGIN;
+ }
+ }
+ }</code></pre>
+<hr/>
+
+<p>
+ The <strong>AuthenticationInterceptor</strong> looks to see if a User object
+ has been stored in the client's session state.
+ If so, it returns normally, and the next Interceptor in the set would be invoked.
+ If the User object is missing, the Interceptors returns "login".
+ The framework would match "login" to the global result,
+ and transfer control to the Logon action.
+</p>
+
+<p>
+ The MailReader defines four custom Interceptor stacks: "user", "user-submit",
+ "guest", and "guest-submit".
+</p>
+
+<hr/>
+<h5>struts.xml interceptors</h5>
+<pre><code><interceptors>
+ <interceptor name="<strong>authentication</strong>"
+ class="mailreader2.AuthenticationInterceptor"/>
+ <interceptor-stack name="<strong>user</strong>" >
+ <interceptor-ref name="authentication" />
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>user-submit</strong>" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="user"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>guest</strong>" >
+ <interceptor-ref name="defaultStack"/>
+ </interceptor-stack>
+ <interceptor-stack name="<strong>guest-submit</strong>" >
+ <interceptor-ref name="token-session" />
+ <interceptor-ref name="guest"/>
+ </interceptor-stack>
+ </interceptors>
+ <<strong>default-interceptor-ref</strong> name="user"/></code></pre>
+<hr/>
+
+<p>
+ The <strong>user</strong> stacks require that the client be authenticated.
+ In other words, that a User object is present in the session.
+ The actions using a <strong>guest</strong> stack can be accessed by any client.
+ The <strong>-submit</strong> versions of each can be used with actions
+ with forms, to guard against double submits.
+</p>
+
+<h5>Double Submits</h5>
+
+<p>
+ A common problem with designing web applications is that users are impatient
+ and response times can vary.
+ Sometimes, people will press a submit button a second time.
+ When this happens, the browser submits the request again,
+ so that we now have two requests for the same thing.
+ In the case of registering a user, if someone does press the submit button
+ again, and their timing is bad,
+ it could result in the system reporting that the username has already been
+ used.
+ (The first time the button was pressed.)
+ In practice, this would probably never happen, but for a longer running
+ process, like checking out a shopping cart,
+ it's easier for a double submit to occur.
+</p>
+
+<p>
+ To forestall double submits, and "back button" resubmits,
+ the framework can generate a token that is embedded in the form
+ and also kept in the session.
+ If the value of the tokens do not compare,
+ then we know that there has been a problem,
+ and that a form has been submitted twice or out of sequence.
+</p>
+
+<p>
+ The Token Session Interceptor will also attempt to provide intelligent
+ fail-over in the event of multiple requests using the same session.
+ That is, it will block subsequent requests until the first request is complete,
+ and then instead of returning the "invalid.token" code,
+ it will attempt to display the same response that the
+ original, valid action invocation would have displayed
+</p>
+
+<p>
+ Because the default interceptor stack will now authenticate the client,
+ we need to specify the standard "defaultStack" for the three
+ "guest actions", Welcome, Logon, and Register.
+ Requiring authentification by default is the better practice, since it
+ means that we won't forget to enable it when creating new actions.
+ Meanwhile, those pesky users will ensure that we don't forget to disable
+ authentification for "guest" services.
+</p>
+
+<h3><a name="MainMenu" id="MainMenu">MainMenu</a></h3>
+
+<p>
+ On a successful logon, the Main Menu page displays.
+ If you logged in using the demo account,
+ the page title should be "Main Menu Options for John Q. User".
+ Below this legend should be two links:
+</p>
+
+<ul>
+ <li>
+ Edit your user registration profile
+ </li>
+ <li>
+ Log off MailReader Demonstration Application
+ </li>
+</ul>
+
+<p>
+ Let's review the source for the "MainMenu" action mapping,
+ and the "MainMenu.jsp".
+</p>
+
+<hr/>
+<h5>Action mapping element for MainMenu</h5>
+<pre><code><action name="MainMenu" class="mailreader2.MailreaderSupport">
+ <result>/pages/MainMenu.jsp</result>
+ </action></code></pre>
+
+<h5>MainMenu.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title><s:text name="mainMenu.title"/></title>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+
+ <body>
+ <h3><s:text name="mainMenu.heading"/> <strong><s:property
+ value="user.fullName"/></strong></h3>
+ <ul>
+ <li><a href="<s:url <strong>action="Registration!input"</strong> />">
+ <s:text name="mainMenu.registration"/>
+ </a>
+ </li>
+ <li><a href="<s:url <strong>action="Logoff"</strong> />">
+ <s:text name="mainMenu.logoff"/>
+ </a>
+ </ul>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ The source for "MainMenu.jsp" also contains a new tag, <strong>
+ property</strong>, which we use to customize the page with the
+ "fullName" property of the authenticated user.
+</p>
+
+<p>
+ Displaying the user's full name is the reason the MainMenu action
+ references the MailreaderSupport class.
+ The MailreaderSupport class has a User property that the text tag
+ can access.
+ If we did not utilize MailreaderSupport,
+ the property tag would not be able to find the User object to print
+ the full name.
+</p>
+
+<p>
+ The customized MainMenu page offers two standard links.
+ One is to "Edit your user registration profile".
+ The other is to "Logoff the MailReader Demonstration Application".
+</p>
+
+<h3><a name="Registration.jsp" id="Registration.jsp">Registration page</a>
+</h3>
+
+<p>
+ If you follow the "Edit your user registration profile" link from the Main
+ Menu page,
+ we will finally reach the heart of the MailReader application: the
+ Registration, or "Profile", page.
+ This page displays everything MailReader knows about you
+ (or at least your login),
+ while utilizing several interesting techniques.
+</p>
+
+<p>
+ To do double duty as the "Create" Registration page and the "Edit"
+ Registration page,
+ the "Registration.jsp" makes extensive use of the test tags,
+ to make it appears as though there are two distinct pages.
+</p>
+
+<hr/>
+<h5>Registration.jsp - head element</h5>
+<pre><code><head>
+ <s:if test="<strong>task=='Create'</strong>">
+ <title><s:text name="registration.title.create"/></title>
+ </s:if>
+ <s:if test="<strong>task=='Edit'</strong>">
+ <title><s:text name="registration.title.edit"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head></code></pre>
+<hr/>
+
+<p>
+ For example, if client is editing the form (task == 'Edit'),
+ the page inserts the username from the User object.
+ For a new Registration (task == 'Create'),
+ the page creates an empty data-entry field.
+</p>
+
+<hr/>
+<h5>Note:</h5>
+<blockquote>
+ <p><font class="hint">
+ <strong>Presention Logic</strong> -
+ The "test" tag is a convenient way to express presentation
+ logic within your pages.
+ Customized pages help to prevent user error,
+ and dynamic customization reduces the number of server pages your
+ application needs to maintain, among other benefits.
+ </font></p>
+</blockquote>
+<hr/>
+
+<p>
+ The page also uses logic tags to display a list of subscriptions
+ for the given user.
+ If the RegistrationForm has task set to "Edit",
+ the lower part of the page that lists the subscriptions is exposed.
+</p>
+
+<hr/>
+<h5></h5>
+<pre><code><s:if test=<strong>"task == 'Edit'"</strong>>
+ <div align="center">
+ <h3><s:text name="heading.subscriptions"/></h3>
+ </div>
+ <!-- ... -->
+ </s:if>
+ <jsp:include page="Footer.jsp"/>
+ </body></html></code></pre>
+<hr/>
+
+<p>
+ Otherwise, the page contains just the top portion --
+ a data-entry form for managing the user's registration.
+</p>
+
+<h4><a name="iterator" id="iterator">iterator</a></h4>
+
+<p>
+ Besides "if" there are several other control tags that you can use
+ to sort, filter, or iterate over data.
+ The Registration page includes a good example of using the <strong>iterator</strong>
+ tag to display the User's Subscriptions.
+</p>
+
+<p>
+ The subscriptions are stored in a hashtable object, which is in turn
+ stored in the user object.
+ So to display each subscription, we have to reach into the user object,
+ and loop through the members of the subscription collection.
+ Using the iterator tag, you can code it the way it sounds.
+</p>
+
+<hr/>
+<h5>Using iterator to list the Subscriptions</h5>
+<pre><code><s:iterator value="<strong>user.subscriptions</strong>">
+ <tr>
+ <td align="left">
+ <s:property value="<strong>host</strong>"/>
+ </td>
+ <td align="left">
+ <s:property value="<strong>username</strong>"/>
+ </td>
+ <td align="center">
+ <s:property value="<strong>type</strong>"/>
+ </td>
+ <td align="center">
+ <s:property value="<strong>autoConnect</strong>"/>
+ </td>
+ <td align="center">
+ <a href="<s:url action="<strong>Subscription!delete</strong>"><s:param name="<strong>host</strong>"
+ value="host"/></s:url>">
+ <s:text name="registration.deleteSubscription"/>
+ </a>
+ <a href="<s:url action="<strong>Subscription!edit</strong>"><s:param name="<strong>host</strong>"
+ value="host"/></s:url>">
+ <s:text name="registration.editSubscription"/>
+ </a>
+ </td>
+ </tr>
+ </s:iterator></code></pre>
+<hr/>
+
+<p>
+ When the iterator renders, it generates a list of Subscriptions for the current User.
+</p>
+
+<hr/>
+
+<div align="center">
+ <h3>Current Subscriptions</h3>
+</div>
+
+<table border="1" width="100%">
+ <tr>
+ <th align="center" width="30%">
+ Host Name
+ </th>
+ <th align="center" width="25%">
+ User Name
+ </th>
+
+ <th align="center" width="10%">
+ Server Type
+ </th>
+ <th align="center" width="10%">
+ Auto
+ </th>
+ <th align="center" width="15%">
+ Action
+ </th>
+ </tr>
+ <tr>
+ <td align="left">
+ mail.hotmail.com
+ </td>
+ <td align="left">
+ user1234
+ </td>
+ <td align="center">
+ pop3
+ </td>
+
+ <td align="center">
+ false
+ </td>
+ <td align="center">
+ <a href="/struts2-mailreader/Subscription!delete.do?host=mail.hotmail.com">
+ Delete
+ </a>
+
+ <a href="/struts2-mailreader/Subscription!edit.do?host=mail.hotmail.com">
+ Edit
+ </a>
+ </td>
+ </tr>
+ <tr>
+ <td align="left">
+ mail.yahoo.com
+ </td>
+ <td align="left">
+ jquser
+ </td>
+ <td align="center">
+ imap
+ </td>
+ <td align="center">
+ false
+ </td>
+ <td align="center">
+ <a href="/struts2-mailreader/Subscription!delete.do?host=mail.yahoo.com">
+ Delete
+ </a>
+
+ <a href="/struts2-mailreader/Subscription!edit.do?host=mail.yahoo.com">
+ Edit
+ </a>
+ </td>
+ </tr>
+</table>
+<a href="/struts2-mailreader/Subscription!input.do">Add</a>
+
+<hr/>
+
+<p>
+ Now look back at the code used to generate this block.
+</p>
+
+<p>
+ Notice anything nifty?
+</p>
+
+<p>
+ How about that the markup between the iterator tag is
+ actually <em>simpler</em> than the markup that we would use to render one row of the table?
+</p>
+
+<p>
+ Instead of using a qualified reference like "value=user.subscription[0].host",
+ we use the simplest possible reference: "value=host".
+ We didn't have to define a local variable, and reference that local in the loop code.
+ The reference to each item in the list is automatically resolved, no fuss, no muss.
+</p>
+
+<p>
+ Nice trick!
+</p>
+
+<p>
+ The secret to this magic is the <strong>value stack</strong>.
+ Next to Interceptors, the value stack is probably the coolest thing there is about the framework.
+ To explain the value stack, let's step back and start from the beginning.
+</p>
+
+<p>
+ Merging dynamic data into static web pages is a primary reason
+ we create web applications.
+ The Java API has a mechanism that allows you to
+ place objects in a servlet scope (page, request, session, or
+ application), and then retrieve them using a JSP scriplet.
+ If the object is placed directly in one of the scopes,
+ a JSP tag or scriptlet can find that object by searching page scope and
+ then request scope, and session scope, and finally application scope.
+</p>
+
+<p>
+ The value stack works much the same way, only better.
+ When you push an object on the value stack,
+ the public properties of that object become first-class properties of the stack.
+ The object's properties become the stack's properties.
+ If another object on the stack has properties of the same name,
+ the last object pushed onto the stack wins. (Last-In, First-Out.)
+</p>
+
+<p>
+ When the iterator tag loops through a collection,
+ it pushes each item in the collection onto the stack.
+ The item's properties become the stack's property.
+ In the case of the Subscriptions,
+ if the Subscription has a public Host property,
+ then during that iteration,
+ the stack can access the same property.
+</p>
+
+<p>
+ Of course, at the end of each iteration, the tag "pops" the item off the stack.
+ If we were to try and access the Host property later in the page,
+ it won't be there.
+</p>
+
+<p>
+ When an Action is invoked, the Action class is pushed onto the value stack.
+ Since the Action is on the value stack,
+ our tags can access any property of the Action as if it were an implicit property of the page.
+ The tags don't access the Action directly.
+ If a textfield tag is told to render the "Username" property,
+ the tag asks the value stack for the value of "Username",
+ and the value stack returns the first property it finds by that name.
+</p>
+
+<p>
+ The Validators also use the stack.
+ When validation fails on a field,
+ the value for the field is pushed onto the value stack.
+ As a result, if the client enters text into an Integer field,
+ the framework can still redisplay whatever was entered.
+ An invalid input value is not stored in the field (even if it could be).
+ The invalid input is pushed onto the stack for the scope of the request.
+</p>
+
+<p>
+ The Subscription list uses another new tag: the <strong>param</strong> tag.
+ As tags go, "param" takes very few parameters of its own: just "name" and "value", and neither is required.
+ Although simple, "param" is one of the most powerful tags the framework provides.
+ Not so much because of what it does, but because of what "param" allows the other tags to do.
+</p>
+
+<p>
+ Essentially, the "param" tag provides parameters to other tags.
+ A tag like "text" might be retrieving a message template with several replaceable parameters.
+ No matter how many parameters are in the template, and no matter what they are named,
+ you can use the "param" tag to pass in whatever you need.
+</p>
+
+<pre><code>pager.legend = Displaying {current} of {count} items matching {criteria}.
+ ...
+ <s:text name="pager.legend">
+ <s:<strong>param</strong> name="current" value="42" />
+ <s:<strong>param</strong> name="count" value="314" />
+ <s:<strong>param</strong> name="criteria" value="Life, the Universe, and Everything" />
+ </s:text></code></pre>
+
+<p>
+ In the case of an "url" tag,
+ we can use "param" to create the query string.
+ A statement like this:
+</p>
+
+<pre><code>
+ <s:url action="Subscription!edit"><s:param name="<strong>host" value="host</strong>"/></s:url>">
+</code></pre>
+
+<p>
+ can render a hyperlink like this:
+</p>
+
+<pre><code>
+ <a href="/struts2-mailreader/Subscription!edit.do?<strong>host=mail.yahoo.com</strong>">Edit</a>
+</code></pre>
+
+
+<!--
+<p>
+ At the foot of the Register page is a link for adding a subscription.
+ Let's wind up the tour by following the Add link and then logging off.
+ Like the link for creating a Support, Add points to an "Edit" action,
+ namely "EditSubscription".
+</p>
+-->
+
+<p>
+ If a hyperlink needs more parameters,
+ you can use "param" to add as many parameters as needed.
+</p>
+
+<h3>
+ <a name="Subscription" id="Subscription">Subscription</a>
+</h3>
+
+<p>
+ If we follow one of the "Edit" subscription links on the Registration page,
+ we come to the Subscriptions page,
+ which displays the details of our description in a data-entry form.
+ Let's have a look a the Subscription configuration in "struts.xml"
+ and follow the bouncing ball from page to action to page.
+</p>
+
+<hr/>
+<h5>struts.xml Subscription element</h5>
+<pre><code><action name="Subscription" class="mailreader2.SubscriptionSupport">
+ <result name="input">/pages/Subscription.jsp</result>
+ <result type="redirect-action">Registration!input</result>
+ </action></code></pre>
+<hr/>
+
+<p>
+ The Edit link specified the Subscription action,
+ but also includes the qualifier <strong>!edit</strong>.
+ The <strong>!</strong> idiom tells the framework to invoke the
+ "edit" method of the Subscription action,
+ instead of the default "execute" method
+ The "alternate" execute methods are called <strong>alias</strong> methods.
+</p>
+
+<hr/>
+<h5>Subscription edit alias</h5>
+<pre><code>public String <strong>edit()</strong> {
+ <strong>setTask(Constants.EDIT);</strong>>
+ return find();
+ }
+
+ public String find() {
+ org.apache.struts.apps.mailreader.dao.Subscription
+ sub = findSubscription();
+ if (sub == null) {
+ return ERROR;
+ }
+ <strong>setSubscription(sub);</strong>
+ return INPUT;
+ }</code></pre>
+<hr/>
+
+<p>
+ The "edit" alias has two responsibilities.
+ First, it must set the Task property to "Edit".
+ The Subscription page will render itself differently
+ depending on the value of the Task property.
+ Second, "edit" must locate the relevant Subscription
+ and set it to the Subscription property.
+ If all goes well, "edit" returns the INPUT token,
+ so that the "input" result will be invoked.
+</p>
+
+<p>
+ In the normal course, the Subscription should always be found,
+ since we selected the entry from a system-generated list.
+ If the Subscription is not found,
+ it would be because the database disappeared
+ or the request is being spoofed.
+ If the Subscription is not found,
+ edit returns the token for the global "error" result,
+ because this condition is unexpected.
+</p>
+
+<p>
+ The business logic for the "edit" alias is a simple wrapper
+ around the MailReader DAO classes.
+</p>
+
+<hr/>
+<h5>MailreaderSupport findSubscription()</h5>
+<pre><code>public Subscription <strong>findSubscription()</strong> {
+ return findSubscription(getHost());
+ }
+
+ public Subscription findSubscription(String host) {
+ Subscription subscription;
+ subscription = <strong>getUser().findSubscription(host);</strong>
+ return subscription;
+ }</code></pre>
+<hr/>
+
+<p>
+ This code is very simple
+ and doesn't seem to provide much in the way of error handling.
+ But, that's OK.
+ Since the page is suppose to be entered from a link that we created,
+ we do expect everything to go right here.
+ But, if it doesn't, the global exception handler we defined in "struts.xml"
+ will trap the exception for us.
+</p>
+
+<p>
+ Likewise, the AuthentificationInterceptor will ensure that only clients
+ with a valid User object can try to edit a Subscription.
+ If the session expired, or someone bookmarked the page,
+ the client will be redirected to the Logon page automatically.
+</p>
+
+<p>
+ As a final layer of defense, we also configured a validator for Subscription,
+ to ensure that we are passed a Host parameter.
+</p>
+
+<hr/>
+<h5>Subscription-validation.xml</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+ <validators>
+ <field name="<strong>host</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+ </validators></code></pre>
+<hr/>
+
+<p>
+ By keeping routine sety precautions out of the Action class,
+ the all-important Actions becomes smaller and easier to maintain.
+</p>
+
+<p>
+ After setting the relevent Subscription object to the Subscription property,
+ the framework transfers control to the (you guessed it) Subscription page.
+</p>
+
+<hr/>
+<h5>Subscription.jsp</h5>
+<pre><code><%@ page contentType="text/html; charset=UTF-8" %>
+ <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <s:if test="task=='Create'">
+ <title><s:text name="subscription.title.create"/></title>
+ </s:if>
+ <s:if test="task=='Edit'">
+ <title><s:text name="subscription.title.edit"/></title>
+ </s:if>
+ <s:if test="task=='Delete'">
+ <title><s:text name="subscription.title.delete"/></title>
+ </s:if>
+ <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
+ type="text/css"/>
+ </head>
+ <body onLoad="self.focus();document.Subscription.username.focus()">
+
+ <s:actionerror/>
+ <s:form method="POST" <strong>action="SubscriptionSave"</strong> validate="false">
+ <strong><s:token /></strong>
+ <strong><s:hidden name="task"/></strong>
+ <strong><s:label label="%{getText('username')}" name="user.username"/></strong>
+
+ <s:if test="task == 'Create'">
+ <s:textfield label="%{getText('mailHostname')}" name="host"/>
+ </s:if>
+ <s:else>
+ <s:label label="%{getText('mailHostname')}" name="host"/>
+ <s:hidden name="host"/>
+ </s:else>
+
+ <s:if test="task == 'Delete'">
+ <s:label label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:label label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <s:label label="%{getText('mailServerType')}"
+ name="subscription.type"/>
+ <s:label label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/>
+ <s:submit value="%{getText('button.confirm')}"/>
+ </s:if>
+ <s:else>
+ <s:textfield label="%{getText('mailUsername')}"
+ name="subscription.username"/>
+ <s:textfield label="%{getText('mailPassword')}"
+ name="subscription.password"/>
+ <strong><s:select label="%{getText('mailServerType')}"
+ name="subscription.type" list="types"/></strong>
+ <strong><s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/></strong>
+ <s:submit value="%{getText('button.save')}"/>
+ <s:reset value="%{getText('button.reset')}"/>
+ </s:else>
+
+ <s:submit action="Registration!input"
+ value="%{getText('button.cancel')}"
+ onclick="form.onsubmit=null"/>
+ </s:form>
+
+ <jsp:include page="Footer.jsp"/>
+ </body>
+ </html></code></pre>
+<hr/>
+
+<p>
+ As before, we'll discuss the tags and attributes that are new to this page:
+ "token", "hidden", "label", "select", and "checkbox".
+</p>
+
+<p>
+ When we looked at the form tag for the Logon page,
+ it did not specify a target for the submit.
+ Instead, it just posted back to the Logon action.
+ In this <strong>form</strong> tag, we are specifying a different action,
+ <strong>SubscriptionSave</strong>
+ to be the target of the submit,
+</p>
+
+<p>
+ The main reason we use another action is so that we can use a different set of validations.
+ When we retrieve the Subscription for editing, all we need is the Host property.
+ When we save the Subscription, we want to validate additional properties.
+ Since the validation files are coupled to the classes,
+ we created a new Action class for saving a Subscription.
+</p>
+
+<hr/>
+<h5>Subscription-validation.xml</h5>
+<pre><code><!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+ <validators>
+ <field name="<strong>host</strong>">
+ <field-validator type="<strong>requiredstring</strong>">
+ <message key="error.host.required"/>
+ </field-validator>
+ </field>
+ </validators></code></pre>
+<hr/>
+
+<p>
+ The validators follow the same type of inheritance path as the classes.
+ SubscriptionSave extends Subscription,
+ so when SubscriptionSave is validated,
+ the Host property specified by "Subscription-validation.xml" will also be required.
+</p>
+
+<p>
+ The <strong>token</strong> tag works with the Token Session Interceptor to foil double submits.
+ The tag generates a key that is embedded in the form and cached in the session.
+ Without this tag, the Interceptor can't work it's magic.
+</p>
+
+<p>
+ The <strong>hidden</strong> tag embeds the Task property into the form.
+ When the form is submitted,
+ the SubscriptionSave action wil use the Task property to decide
+ whether to insert or update the form.
+</p>
+
+<p>
+ The <strong>label</strong> renders a "read only" version of a property,
+ suitable for placement in the form.
+ In Edit or Delete mode, we want the Host property to be immutable,
+ since it is used as a key. (As unwise as that might sound.)
+ In Delete mode, all of the properties are immutable,
+ since we are simply confirming the delete operation.
+</p>
+
+<p>
+ Saving the best for last, the Subscription utilizes two more interesting
+ tags, "select" and "checkbox".
+</p>
+
+<p>
+ Unsurprisingly, the <strong>select</strong> tag renders a select control,
+ but the tag does so without requiring a lot of markup or redtape.
+</p>
+
+<pre><code><s:select label="%{getText('mailServerType')}"
+ name="subscription.type" <strong>list="types"</strong> />
+</code></pre>
+
+<p>
+ The interesting attribute of the "select" tag is "list",
+ which, in our case, specifies a value of "types".
+ If we take another look at the Subscription action,
+ we can see that it implements an interface named Preparable
+ and populates a Types property in a method named "prepare".
+</p>
+
+<hr/>
+<h5>Subscription-validation.xml</h5>
+<pre><code>public class <strong>Subscription</strong> extends MailreaderSupport
+ <strong>implements Preparable</strong> {
+
+ private Map types = null;
+ public Map <strong>getTypes()</strong> {
+ return types;
+ }
+
+ public void <strong>prepare()</strong> {
+ Map m = new LinkedHashMap();
+ m.put("imap", "IMAP Protocol");
+ m.put("pop3", "POP3 Protocol");
+ types = m;
+ setHost(getSubscriptionHost());
+ }
+
+ // ... </code></pre>
+<hr/>
+
+<p>
+ The default Interceptor stack includes the <strong>PrepareInterceptor</strong>,
+ which observes the Preparable interface.
+</p>
+
+<hr/>
+<h5>PrepareInterceptor</h5>
+<pre><code>public class <strong>PrepareInterceptor</strong> extends AroundInterceptor {
+
+ protected void after(ActionInvocation dispatcher, String result) throws Exception {
+ }
+
+ protected void before(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+ <strong>if (action instanceof Preparable) {
+ ((Preparable) action).prepare();</strong>
+ }
+ }
+ }</code></pre>
+
+<p>
+ The PrepareInterceptor ensures that the "prepare" method will always be called
+ before "execute" or an alias method is invoked.
+ We use "prepare" to setup the list of items for the select list to display.
+ We also transfer the Host property from our Subscription object
+ to a local property, where it is easier to manage.
+</p>
+
+
+<h4>
+ <a name="SubscriptionAction.java" id="SubscriptionAction.java">SubscriptionAction.java</a>
+</h4>
+
+<p>
+ Like many applications, the MailReader uses mainly String properties.
+ One exception is the AutoConnect property of the Subscription object.
+ On the HTML form, the AutoConnect property is represented by a checkbox,
+ and checkboxes need to be handled differently that other controls.
+</p>
+
+<p>
+ The <strong>checkbox</strong> starts out as a simple enough control.
+</p>
+
+<pre><code> <s:checkbox label="%{getText('autoConnect')}"
+ name="subscription.autoConnect"/></code></pre>
+
+<p>
+ The Subscription object has a boolean AutoConnect property,
+ and the checkbox simply has to represent its state.
+ The problem is, if you clear a checkbox, the browser client will not submit <em>anything</em>.
+ Nada. Zip.
+ It is as if the checkbox control never existed.
+ The HTTP protocol has no way to affirm "false".
+ If the control is missing, we need to figure out it's been unclicked.
+</p>
+
+<hr/>
+<h5>Tip:</h5>
+<blockquote>
+ <p class="hint">
+ <strong>Checkboxes</strong> -
+ The HTML checkbox is a tricky control.
+ The problem is that, according to the W3C specification, a value is
+ only guaranteed to be sent
+ if the control is checked.
+ If the control is not checked, then the control may be omitted from
+ the request, as if it was on the page.
+ This can cause a problem with session-scope checkboxes.
+ Once you set the checkbox to true, the control can't set it to false
+ again,
+ because if you uncheck the box, nothing is sent, and so the control
+ stays checked.
+ </p>
+</blockquote>
+<hr/>
+
+<p>
+ The simplest solution is to employ our old friend Preparable again.
+ In the "prepare" method for SubscriptionSave,
+ we can set the property represented by the checkbox to false.
+ If the control is not submitted, then the property remains false.
+ If the control is submitted, then the property is set to true.
+</p>
+
+<hr/>
+<h5>SubscriptionSave</h5>
+<pre><code>public final class SubscriptionSave extends Subscription {
+
+ public void prepare() {
+ super.prepare();
+ // checkbox workaround
+ <strong>getSubscription().setAutoConnect(false);</strong>
+ }
+
+ public String execute() throws Exception {
+ return save();
+ }
+ }</code></pre>
+<hr/>
+
+
+<p>
+ If we press the SAVE button,
+ the form will be submitted to the SubscriptionSave action.
+ If the validation succeeds, as we've seen,
+ SubscriptionSave will invoke the Subscription.save method.
+</p>
+
+<hr/>
+<h5>Subscription save method</h5>
+<pre><code>public String <strong>save</strong>() throws Exception {
+
+ if (Constants.DELETE.equals(getTask())) {
+ <strong>removeSubscription</strong>();
+ }
+
+ if (Constants.CREATE.equals(getTask())) {
+ <strong>copySubscription(</strong>getHost());
+ }
+
+ saveUser();
+ return SUCCESS;
+ }</code></pre>
+<hr/>
+
+<p>
+ The <strong>save</strong> method uses the Task property to handle
+ the special cases of deleting and creating,
+ and then updates the state of the User object.
+</p>
+
+<p>
+ The <strong>removeSubscription</strong> method calls the DAO facade,
+ and then updates the application state.
+</p>
+
+<hr/>
+<h5>removeSubscription</h5>
+<pre><code>public void <strong>removeSubscription</strong>() throws Exception {
+ getUser().removeSubscription(getSubscription());
+ getSession().remove(Constants.SUBSCRIPTION_KEY);
+ }</code></pre>
+<hr/>
+
+<p>
+ The <strong>copySubscription</strong> method is a bit more interesting.
+ The MailReader DAO layer API includes some immutable fields
+ that can't be set once the object is created.
+ Because key fields are immutable,
+ we can't just create a Subscription, let the framework populate all the fields,
+ and then save it when we are done -- because some fields can't be populated,
+ except at construction.
+</p>
+
+<p>
+ One workaround would be to declare properties on the Action
+ for all the properties we need to pass to the Subscription or User objects.
+ When we are ready to create the object,
+ we could pass the new object values from the Action properties.
+</p>
+
+<p>
+ Another workaround is to declare only the immutable properties on the Action,
+ and then use what we can from the domain object.
+</p>
+
+<p>
+ This implementation of the MailReader utilizes the second alternative.
+ We define User and Subscription objects on our base Action,
+ and add other properties only as needed.
+</p>
+
+<p>
+ To add a new Subscription or User,
+ we create a blank object to capture whatever fields we can.
+ When this "input" object returns, we create a new object,
+ setting the immutable fields to appropriate values,
+ and copy over the rest of the properties.
+</p>
+
+<hr/>
+<h5>copySubscription</h5>
+<pre><code>public void <strong>copySubscription</strong>(String host) {
+ Subscription input = getSubscription();
+ Subscription sub = createSubscription(host);
+ if (null != sub) {
+ <strong>BeanUtils.setValues</strong>(sub, input, null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+ }</code></pre>
+
+<p>
+ Of course, this is not a preferred solution,
+ but merely a way to work around an issue in the MailReader DAO API
+ that would not be easy for us change.
+</p>
+
+<h3>Summary</h3>
+
+<p>
+ At this point, we've booted the application, logged on,
+ reviewed a Registration record, and edited a Subscription.
+ Of course, there's more, but from here on, it is mostly more of the same.
+ The full source code for MailReader is
+ <a href="http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/struts2/apps/mailreader/">available online</a>
+ and in the distribution.
+</p>
+
+<p>
+ Enjoy!
+</p>
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/struts-power.gif b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/struts-power.gif
new file mode 100644
index 0000000..5f4e9d4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/main/webapp/struts-power.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/mailreader-wildone/src/test/java/mailreader2/ConfigTest.java b/struts-sandbox/struts2/apps/mailreader-wildone/src/test/java/mailreader2/ConfigTest.java
new file mode 100644
index 0000000..abe1127
--- /dev/null
+++ b/struts-sandbox/struts2/apps/mailreader-wildone/src/test/java/mailreader2/ConfigTest.java
@@ -0,0 +1,66 @@
+package mailreader2;
+
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.config.RuntimeConfiguration;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
+
+import java.util.Map;
+
+public class ConfigTest extends XWorkTestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ XmlConfigurationProvider c = new XmlConfigurationProvider("struts.xml");
+ configurationManager.addConfigurationProvider(c);
+ configurationManager.reload();
+ }
+
+ private ActionConfig assertClass(String action_name, String class_name) {
+ RuntimeConfiguration configuration = configurationManager.getConfiguration().getRuntimeConfiguration();
+ ActionConfig config = configuration.getActionConfig("", action_name);
+ assertNotNull(config);
+ assertTrue("Wrong class name: [" + config.getClassName() + "]",
+ class_name.equals(config.getClassName()));
+ return config;
+ }
+
+ private void assertResult(ActionConfig config, String result_name, String result_value) {
+ Map results = config.getResults();
+ ResultConfig result = (ResultConfig) results.get(result_name);
+ Map params = result.getParams();
+ String value = (String) params.get("actionName");
+ if (value==null)
+ value = (String) params.get("location");
+ assertTrue("Wrong result value: [" + value + "]",
+ result_value.equals(value));
+ }
+
+ public void testSubscriptionSave() throws Exception {
+ ActionConfig config = assertClass("subscription/Update", "mailreader2.subscription.Update");
+ assertResult(config, ActionSupport.SUCCESS, "registration/+Input");
+ assertResult(config, ActionSupport.INPUT, "/pages/subscription.jsp");
+ }
+
+ // */!*
+ public void testPrepareWildcard() throws Exception {
+ ActionConfig config = assertClass("logon/+Input", "mailreader2.logon.Input");
+ assertResult(config, ActionSupport.SUCCESS, "/pages/logon.jsp");
+ }
+
+ // */*
+ public void testExecuteWildcard() throws Exception {
+ ActionConfig config = assertClass("registration/Update", "mailreader2.registration.Update");
+ assertResult(config, ActionSupport.INPUT, "/pages/registration.jsp");
+ ActionConfig config2 = assertClass("logon/Retrieve", "mailreader2.logon.Retrieve");
+ assertResult(config2, ActionSupport.INPUT, "/pages/logon.jsp");
+ }
+
+ // single wildcard
+ public void testDisplayWildcard() throws Exception {
+ assertClass("Welcome", "mailreader2.Welcome");
+ }
+
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/pom.xml b/struts-sandbox/struts2/apps/shopping-cart/pom.xml
new file mode 100644
index 0000000..7e03546
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-apps</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-shopping-cart</artifactId>
+ <packaging>war</packaging>
+ <name>Shopping Cart Webapp</name>
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>opensymphony</groupId>
+ <artifactId>sitemesh</artifactId>
+ <version>2.2.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>uk.ltd.getahead</groupId>
+ <artifactId>dwr</artifactId>
+ <version>1.1-beta-3</version>
+ </dependency>
+
+ </dependencies>
+
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty6-plugin</artifactId>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-j2ee_1.4_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/AbstractModifyCartAction-validation.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/AbstractModifyCartAction-validation.xml
new file mode 100644
index 0000000..8aba0c5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/AbstractModifyCartAction-validation.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+ <field name="productId">
+ <field-validator type="required">
+ <message>You must select a product.</message>
+ </field-validator>
+ </field>
+ <field name="quantity">
+ <field-validator type="int">
+ <param name="min">0</param>
+ <message>The quantity cannot be less than zero.</message>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/AbstractModifyCartAction.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/AbstractModifyCartAction.java
new file mode 100644
index 0000000..956508f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/AbstractModifyCartAction.java
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.actions;
+
+import org.apache.struts2.example.ajax.catalog.Catalog;
+import org.apache.struts2.example.ajax.catalog.Product;
+
+/**
+ * AbstractModifyCartAction
+ *
+ */
+public abstract class AbstractModifyCartAction extends ShowCart {
+ protected int quantity;
+ private Integer productId;
+ protected Product product;
+ protected Catalog catalog;
+
+ public void setCatalog(Catalog catalog) {
+ this.catalog = catalog;
+ }
+
+ public void setQuantity(int quantity) {
+ this.quantity = quantity;
+ }
+
+ public int getQuantity() {
+ return quantity;
+ }
+
+ public void setProductId(Integer productId) {
+ this.productId = productId;
+ }
+
+ public Integer getProductId() {
+ return productId;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void validate() {
+ if (productId != null) {
+ product = catalog.findProductById(productId);
+ if (product == null) {
+ addFieldError("productId", "There is no product '" + productId + "' in the catalog " + catalog.getName());
+ }
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ActiveCategory.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ActiveCategory.java
new file mode 100644
index 0000000..92dcff5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ActiveCategory.java
@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.actions;
+
+import org.apache.struts2.example.ajax.cart.ShoppingCart;
+import org.apache.struts2.example.ajax.catalog.Catalog;
+import org.apache.struts2.example.ajax.catalog.Category;
+import org.apache.struts2.interceptor.SessionAware;
+import com.opensymphony.xwork2.ActionSupport;
+
+import java.util.Map;
+
+/**
+ * ActiveCategory
+ *
+ */
+public class ActiveCategory extends ActionSupport implements SessionAware {
+ public static final String ACTIVE_CATEGORY_ID = "catalog_activeCategoryId";
+ private Map session;
+ private Category category;
+ private Catalog catalog;
+ private ShoppingCart cart;
+
+ public void setSession(Map session) {
+ this.session = session;
+ }
+
+ public void setCatalog(Catalog catalog) {
+ this.catalog = catalog;
+ }
+
+ public Catalog getCatalog() {
+ return catalog;
+ }
+
+ public Integer getCategoryId() {
+ return (Integer) session.get(ACTIVE_CATEGORY_ID);
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public String execute() throws Exception {
+ Integer categoryId = getCategoryId();
+ if (categoryId != null) {
+ category = catalog.findCategoryForId(categoryId);
+ }
+ return SUCCESS;
+ }
+
+ public void setShoppingCart(ShoppingCart cart) {
+ this.cart = cart;
+ }
+
+ public ShoppingCart getCart() {
+ return cart;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/SetActiveCategory.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/SetActiveCategory.java
new file mode 100644
index 0000000..87794cd
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/SetActiveCategory.java
@@ -0,0 +1,57 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.actions;
+
+import org.apache.struts2.interceptor.SessionAware;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+
+/**
+ * SetActiveCategory
+ *
+ */
+public class SetActiveCategory extends ActionSupport implements SessionAware {
+ private Map session;
+ private Integer categoryId;
+ private static Log LOG = LogFactory.getLog(SetActiveCategory.class);
+
+ public void setSession(Map session) {
+ this.session = session;
+ }
+
+ public void setCategoryId(Integer categoryId) {
+ this.categoryId = categoryId;
+ }
+
+ public Integer getCategoryId() {
+ return categoryId;
+ }
+
+ public String execute() throws Exception {
+ LOG.debug("Setting the active category to " + categoryId);
+ if (categoryId != null) {
+ session.put(ActiveCategory.ACTIVE_CATEGORY_ID, categoryId);
+ } else {
+ session.remove(ActiveCategory.ACTIVE_CATEGORY_ID);
+ }
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ShowCart.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ShowCart.java
new file mode 100644
index 0000000..c5fd711
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ShowCart.java
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.actions;
+
+import org.apache.struts2.example.ajax.cart.ShoppingCart;
+import com.opensymphony.xwork2.ActionSupport;
+
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * ShowCart
+ *
+ */
+public class ShowCart extends ActionSupport {
+ private ShoppingCart cart;
+
+ public void setShoppingCart(ShoppingCart cart) {
+ this.cart = cart;
+ }
+
+ public ShoppingCart getCart() {
+ return cart;
+ }
+
+ public int getNumCartItems() {
+ ShoppingCart cart = getCart();
+ if ((cart == null) || (cart.getContents() == null)) {
+ return 0;
+ }
+ Set contents = cart.getContents();
+ int number = 0;
+ for( Iterator i=contents.iterator(); i.hasNext(); ) {
+ ShoppingCart.CartEntry entry = (ShoppingCart.CartEntry)i.next();
+ number += entry.getQuantity();
+ }
+ return number;
+ }
+
+ public double getCartTotal() {
+ ShoppingCart cart = getCart();
+ if ((cart == null) || (cart.getContents() == null)) {
+ return 0;
+ }
+ double total = 0.0;
+ for (Iterator iterator = cart.getContents().iterator(); iterator.hasNext();) {
+ ShoppingCart.CartEntry cartEntry = (ShoppingCart.CartEntry) iterator.next();
+ total += (cartEntry.getQuantity() * cartEntry.getProduct().getPrice());
+ }
+ return total;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ShowCatalog.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ShowCatalog.java
new file mode 100644
index 0000000..489f50b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/ShowCatalog.java
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.actions;
+
+import org.apache.struts2.example.ajax.catalog.Catalog;
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * ShowCatalog
+ *
+ */
+public class ShowCatalog extends ActionSupport {
+ protected Catalog catalog;
+
+ public void setCatalog(Catalog catalog) {
+ this.catalog = catalog;
+ }
+
+ public Catalog getCatalog() {
+ return catalog;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/UpdateQuantityInCart.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/UpdateQuantityInCart.java
new file mode 100644
index 0000000..6187a65
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/actions/UpdateQuantityInCart.java
@@ -0,0 +1,34 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.actions;
+
+import org.apache.struts2.example.ajax.cart.ShoppingCart;
+
+/**
+ * UpdateQuantityInCart
+ *
+ */
+public class UpdateQuantityInCart extends AbstractModifyCartAction {
+ public String execute() throws Exception {
+ ShoppingCart cart = getCart();
+ if (cart != null) {
+ cart.setQuantity(quantity, product);
+ }
+ return NONE;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/cart/DefaultCart.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/cart/DefaultCart.java
new file mode 100644
index 0000000..880966e
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/cart/DefaultCart.java
@@ -0,0 +1,101 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.cart;
+
+import org.apache.struts2.example.ajax.catalog.Product;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * DefaultCart
+ *
+ */
+public class DefaultCart implements ShoppingCart {
+ Map contents = new HashMap();
+
+ public void addToCart(int quantity, Product product) {
+ CartEntry entry = (CartEntry) contents.get(product);
+ if (entry == null) {
+ entry = new DefaultCartEntry(quantity, product);
+ contents.put(product, entry);
+ } else {
+ entry.setQuantity(entry.getQuantity() + quantity);
+ }
+ }
+
+ public void setQuantity(int quantity, Product product) {
+ if (quantity <= 0) {
+ contents.remove(product);
+ return;
+ }
+ CartEntry entry = (CartEntry) contents.get(product);
+ if (entry == null) {
+ entry = new DefaultCartEntry(quantity, product);
+ contents.put(product, entry);
+ } else {
+ entry.setQuantity(quantity+entry.getQuantity());
+ }
+ }
+
+ public void removeFromCart(Product product) {
+ contents.remove(product);
+ }
+
+ public Set getContents() {
+ return new HashSet(contents.values());
+ }
+
+ public int getQuantityForProduct(Product product) {
+ CartEntry entry = (CartEntry) contents.get(product);
+ if (entry == null) {
+ return 0;
+ }
+ return entry.getQuantity();
+ }
+
+ public String toString() {
+ return "DefaultCart{" +
+ "contents=" + contents +
+ "}";
+ }
+
+ class DefaultCartEntry implements CartEntry {
+ private int quantity;
+ private Product product;
+
+ public DefaultCartEntry(int quantity, Product product) {
+ this.quantity = quantity;
+ this.product = product;
+ }
+
+ public int getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(int quantity) {
+ this.quantity = quantity;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/cart/ShoppingCart.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/cart/ShoppingCart.java
new file mode 100644
index 0000000..74da0f8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/cart/ShoppingCart.java
@@ -0,0 +1,77 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.cart;
+
+import org.apache.struts2.example.ajax.catalog.Product;
+
+import java.util.Set;
+import java.io.Serializable;
+
+/**
+ * ShoppingCart
+ *
+ */
+public interface ShoppingCart extends Serializable {
+ /**
+ * Adds the specified quantity of the given {@link Product} to the shopping cart. This will add to any
+ * existing quantity of this {@link Product} in the cart.
+ *
+ * @param quantity the quantity to add to the cart
+ * @param product the {@link Product} to add the quantity of
+ */
+ void addToCart(int quantity, Product product);
+
+ /**
+ * Sets the quantity of the specifed {@link Product} in the shopping cart. If the {@link Product} does not
+ * exist in the Cart, it is added.
+ *
+ * @param quantity the quantity to set in the cart for the {@link Product}
+ * @param product the {@link Product} to set the quantity for
+ */
+ void setQuantity(int quantity, Product product);
+
+ /**
+ * Removes the given {@link Product} from the Cart
+ *
+ * @param product the {@link Product} to remove from the Cart
+ */
+ void removeFromCart(Product product);
+
+ /**
+ * Get a {@link java.util.List} of {@link CartEntry} objects in the cart
+ *
+ * @return a {@link java.util.List} of {@link CartEntry} objects in the Cart. Will not return null.
+ */
+ Set getContents();
+
+ /**
+ * Get the quantity of the product in the shopping cart
+ *
+ * @param product
+ * @return the quantity, or 0 if the product is not in the cart
+ */
+ int getQuantityForProduct(Product product);
+
+ interface CartEntry {
+ int getQuantity();
+
+ Product getProduct();
+
+ void setQuantity(int quantity);
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Catalog.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Catalog.java
new file mode 100644
index 0000000..18753cc
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Catalog.java
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.catalog;
+
+import java.util.Set;
+import java.io.Serializable;
+
+/**
+ * Catalog
+ *
+ */
+public interface Catalog extends Identifiable, Serializable {
+ /**
+ * Get a Set of all {@link Category}s in this Catalog.
+ */
+ Set findAllCategories();
+
+ /**
+ * Get a Set of all {@link Product}s in this Catalog.
+ *
+ * @return all {@link Product}s in this Catalog. Will not be null.
+ */
+ Set findAllProducts();
+
+ /**
+ * Get the {@link Category} for the given Id.
+ *
+ * @param id the Category Id
+ * @return the {@link Category} for this Id, or null if none exists.
+ */
+ Category findCategoryForId(Integer id);
+
+ /**
+ * Find the {@link Product} for the given Id
+ *
+ * @param productId the Product id
+ * @return the {@link Product} for this Id, or null if none exists.
+ */
+ Product findProductById(Integer productId);
+
+
+ /**
+ * Find all {@link Product}s for the given {@link Category}
+ *
+ * @param category the category of products to return
+ * @return a Set of {@link Product}s in this {@link Category}. Will not be null.
+ */
+ Set findProductsByCategory(Category category);
+}
+
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Category.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Category.java
new file mode 100644
index 0000000..5976235
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Category.java
@@ -0,0 +1,26 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.catalog;
+
+/**
+ * Category
+ *
+ */
+public interface Category extends Identifiable {
+ Category getParent();
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Identifiable.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Identifiable.java
new file mode 100644
index 0000000..25457ab
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Identifiable.java
@@ -0,0 +1,28 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.catalog;
+
+/**
+ * Identifiable
+ *
+ */
+public interface Identifiable {
+ int getId();
+
+ String getName();
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Product.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Product.java
new file mode 100644
index 0000000..ea265cd
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/Product.java
@@ -0,0 +1,30 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.catalog;
+
+/**
+ * Product
+ *
+ */
+public interface Product extends Identifiable {
+ double getPrice();
+
+ String getDescription();
+
+ Category getCategory();
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/TestCatalog.java b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/TestCatalog.java
new file mode 100644
index 0000000..3900950
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/java/org/apache/struts2/example/ajax/catalog/TestCatalog.java
@@ -0,0 +1,197 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.example.ajax.catalog;
+
+import java.util.*;
+
+/**
+ * TestCatalog
+ *
+ */
+public class TestCatalog implements Catalog {
+ private static Map categories = new HashMap();
+ private static Map products = new HashMap();
+
+ public static Category CATEGORY_ELECTRONICS = new TestCategory(5001, "Electronics", null);
+ public static Category CATEGORY_CLOTHING = new TestCategory(5002, "Clothing", null);
+ public static Category CATEGORY_TELEVISIONS = new TestCategory(5003, "Televisions", CATEGORY_ELECTRONICS);
+ public static Category CATEGORY_STEREOS = new TestCategory(5004, "Stereos", CATEGORY_ELECTRONICS);
+ public static Category CATEGORY_SHIRTS = new TestCategory(5005, "Shirts", CATEGORY_CLOTHING);
+ public static Category CATEGORY_SLACKS = new TestCategory(5006, "Slacks", CATEGORY_CLOTHING);
+
+ public static Product PRODUCT_HD_TV = new TestProduct(7001, "High Definition Television", "54\" High Definition Plasma Television", 5445.00, CATEGORY_TELEVISIONS);
+ public static Product PRODUCT_STEREO = new TestProduct(7002, "All-in-one stereo", "All-in-one stereo with AM/FM tuner, 6 CD changer, 2x300 Watt speakers", 99.99, CATEGORY_STEREOS);
+
+ public static Product PRODUCT_BLUE_SHIRT = new TestProduct(8001, "Blue Shirt", "Blue Shirt", 29.99, CATEGORY_SHIRTS);
+ public static Product PRODUCT_RED_SHIRT = new TestProduct(8002, "Red Shirt", "Red Shirt", 29.99, CATEGORY_SHIRTS);
+ public static Product PRODUCT_GREEN_SHIRT = new TestProduct(8003, "Green Shirt", "Green Shirt", 29.99, CATEGORY_SHIRTS);
+
+ public TestCatalog() {
+ }
+
+ public int getId() {
+ return 1001;
+ }
+
+ public String getName() {
+ return "Test Catalog";
+ }
+
+ public Set findAllCategories() {
+ return new HashSet(categories.values());
+ }
+
+ public Set findAllProducts() {
+ return new HashSet(products.values());
+ }
+
+ public Category findCategoryForId(Integer id) {
+ return (Category) categories.get(id);
+ }
+
+ public Product findProductById(Integer productId) {
+ return (Product) products.get(productId);
+ }
+
+ public Set findProductsByCategory(Category category) {
+ Set categoryProducts = new HashSet();
+ for (Iterator iterator = products.values().iterator(); iterator.hasNext();) {
+ Product product = (Product) iterator.next();
+ if (product.getCategory().equals(category)) {
+ categoryProducts.add(product);
+ }
+ }
+ return categoryProducts;
+ }
+
+ public String toString() {
+ return "Test Catalog";
+ }
+
+ private static class TestCategory implements Category {
+ private int id;
+ private String name;
+ private Category parent;
+
+ private TestCategory(int id, String name, Category parent) {
+ this.id = id;
+ this.name = name;
+ this.parent = parent;
+
+ categories.put(new Integer(id), this);
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Category getParent() {
+ return parent;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final TestCategory testCategory = (TestCategory) o;
+
+ return id == testCategory.id;
+
+ }
+
+ public int hashCode() {
+ return id;
+ }
+
+
+ public String toString() {
+ return "TestCategory{" +
+ "id='" + id + "'" +
+ ", name='" + name + "'" +
+ ", parent=" + parent +
+ "}";
+ }
+ }
+
+ private static class TestProduct implements Product {
+ private int id;
+ private String name;
+ private String description;
+ private double price;
+ private Category category;
+
+ public TestProduct(int id, String name, String description, double price, Category category) {
+ this.id = id;
+ this.name = name;
+ this.description = description;
+ this.price = price;
+ this.category = category;
+
+ products.put(new Integer(id), this);
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public double getPrice() {
+ return price;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final TestProduct testProduct = (TestProduct) o;
+
+ return id == testProduct.id;
+
+ }
+
+ public int hashCode() {
+ return id;
+ }
+
+
+ public String toString() {
+ return "TestProduct{" +
+ "id='" + id + "'" +
+ ", name='" + name + "'" +
+ ", description='" + description + "'" +
+ ", price=" + price +
+ ", category=" + category +
+ "}";
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/default.properties b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/default.properties
new file mode 100644
index 0000000..1f75d67
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/default.properties
@@ -0,0 +1,11 @@
+format.money={0,number,currency}
+format.date={0,date,short}
+
+text.openAll=open all
+text.closeAll=close all
+
+text.category=Category
+text.categories=Categories
+text.submit=Submit
+text.search=Search
+text.setLanguage=Set Language
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/log4j.properties b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/log4j.properties
new file mode 100644
index 0000000..a302e22
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/log4j.properties
@@ -0,0 +1,7 @@
+log4j.rootLogger = INFO, stdout
+
+log4j.appender.stdout = org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Threshold = WARN
+log4j.appender.stdout.Target = System.out
+log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern = %d{ISO8601} %-5p [%F:%L] : %m%n
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/struts.properties b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/struts.properties
new file mode 100644
index 0000000..aa081ab
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/struts.properties
@@ -0,0 +1,16 @@
+# extension for actions
+struts.action.extension=action
+
+# spring integration
+struts.objectFactory=spring
+struts.objectFactory.spring.autoWire=type
+
+### Configuration reloading
+# This will cause the configuration to reload struts.xml when it is changed
+struts.configuration.xml.reload=true
+
+### Load custom default resource bundles
+struts.custom.i18n.resources=default
+
+### character encoding
+struts.i18n.encoding=UTF-8
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/struts.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/struts.xml
new file mode 100644
index 0000000..d52d8aa
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/struts.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <include file="struts-default.xml"/>
+ <include file="config-browser.xml"/>
+
+ <package name="catalog" namespace="/catalog" extends="struts-default">
+ <interceptors>
+ <!-- Basic stack -->
+ <interceptor-stack name="catalogStack">
+ <interceptor-ref name="logger"/>
+ <interceptor-ref name="servlet-config"/>
+ <interceptor-ref name="static-params"/>
+ <interceptor-ref name="params"/>
+ <interceptor-ref name="conversionError"/>
+ <interceptor-ref name="validation"/>
+ <interceptor-ref name="workflow"/>
+ </interceptor-stack>
+ </interceptors>
+
+ <default-interceptor-ref name="catalogStack"/>
+
+ <action name="catalog" class="org.apache.struts2.example.ajax.actions.ShowCatalog">
+ <result name="success">/category.jsp</result>
+ </action>
+
+ <action name="cart" class="org.apache.struts2.example.ajax.actions.ShowCart">
+ <result name="success">/cart.jsp</result>
+ </action>
+
+ <action name="main" class="org.apache.struts2.example.ajax.actions.ActiveCategory">
+ <result name="success">/category-main.jsp</result>
+ </action>
+
+
+ </package>
+ <package name="catalog-remote" namespace="/catalog/remote" extends="catalog">
+ <action name="activeCategory" class="org.apache.struts2.example.ajax.actions.ActiveCategory">
+ <result name="success">/category.jsp</result>
+ </action>
+
+ <action name="setActiveCategory" class="org.apache.struts2.example.ajax.actions.SetActiveCategory">
+ <result name="success" type="chain">activeCategory</result>
+ </action>
+
+ <action name="updateQuantity" class="org.apache.struts2.example.ajax.actions.UpdateQuantityInCart"/>
+
+ </package>
+</struts>
+
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/validators.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/validators.xml
new file mode 100644
index 0000000..b7d2b0f
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/resources/validators.xml
@@ -0,0 +1,14 @@
+<validators>
+ <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
+ <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
+ <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
+ <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
+ <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
+ <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
+ <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
+ <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
+ <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
+ <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
+ <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
+ <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
+</validators>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/applicationContext.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 0000000..80dfc1c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans default-autowire="autodetect">
+
+ <bean id="catalog"
+ singleton="true"
+ class="org.apache.struts2.example.ajax.catalog.TestCatalog" />
+
+ <bean id="shoppingCart"
+ singleton="true"
+ class="org.apache.struts2.example.ajax.cart.DefaultCart" />
+
+
+</beans>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/decorators.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/decorators.xml
new file mode 100644
index 0000000..9b5a724
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/decorators.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<decorators defaultdir="/WEB-INF/decorators">
+ <!-- Any urls that are excluded will never be decorated by Sitemesh -->
+ <excludes>
+ <pattern>/debug.jsp</pattern>
+ <pattern>/css/*</pattern>
+ <pattern>/js/*</pattern>
+ <pattern>/images/*</pattern>
+ <pattern>/dojo/*</pattern>
+ <pattern>/struts/*</pattern>
+ <pattern>/catalog/remote/*</pattern>
+ </excludes>
+
+ <decorator name="main" page="main.jsp">
+ <pattern>/*</pattern>
+ </decorator>
+ <!--<decorator name="panel" page="panel.jsp"/>-->
+ <!--<decorator name="dashedBox" page="dashedBox.jsp"/>-->
+ <!--<decorator name="printable" page="printable.jsp"/>-->
+</decorators>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/decorators/main.jsp b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/decorators/main.jsp
new file mode 100644
index 0000000..859673d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/decorators/main.jsp
@@ -0,0 +1,148 @@
+<%
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setDateHeader("Expires", 0);
+%>
+<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
+<%@ taglib uri="sitemesh-page" prefix="page" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title><decorator:title default="CSS Template"/></title>
+ <link href="<s:url value='/css/main.css'/>" rel="stylesheet" type="text/css" media="all"/>
+ <link href="<s:url value='/css/niftyCorners.css'/>" rel="stylesheet" type="text/css"/>
+ <link href="<s:url value='/css/niftyPrint.css'/>" rel="stylesheet" type="text/css" media="print"/>
+ <link href="<s:url value='/css/dtree.css'/>" rel="stylesheet" type="text/css" media="all"/>
+ <link href="<s:url value='/css/cart.css'/>" rel="stylesheet" type="text/css" media="all"/>
+
+ <script language="JavaScript" type="text/javascript" src="<s:url value='/js/nifty.js'/>"></script>
+ <script language="JavaScript" type="text/javascript" src="<s:url value='/js/dtree.js'/>"></script>
+
+ <s:head theme="ajax"/>
+
+ <script language="JavaScript" type="text/javascript">
+
+ dojo.event.connect (window, "onload" , function() {
+ if (!NiftyCheck())
+ return;
+ // Rounded("blockquote","tr bl","#ECF1F9","#CDFFAA","smooth border #88D84F");
+ Rounded("div#outer-header", "all", "white", "#818EBD", "smooth border #434F7C");
+ Rounded("div#footer", "all", "white", "#818EBD", "smooth border #434F7C");
+ Rounded("div#categories", "tl br", "white", "#f0e68c", "smooth border #daa520");
+ Rounded("div#cart", "tl br", "white", "#ffdab9", "smooth border #8b0000");
+ // Rounded("div.productDetails","tr bl","#ECF1F9","#CDFFAA","smooth border #88D84F");
+
+ dojo.event.topic.publish( "cartUpdated" );
+ });
+
+ </script>
+ <decorator:head/>
+</head>
+
+<body id="page-home">
+
+<div id="page">
+ <div id="outer-header">
+ <div id="header" class="clearfix">
+ <div id="branding">
+ <h1 class="title">Struts Ajax</h1>
+ </div><!-- end branding -->
+
+ <div id="search">
+ <form method="post" action="">
+ <div><label for="search-site">Search</label>
+ <input type="text" name="search" id="search-site"/>
+ <input type="submit" value="go" name="search" id="searchBtn"/></div>
+
+ </form>
+ </div><!-- end search -->
+
+ <hr/>
+ </div>
+ </div><!-- end header -->
+
+ <div id="content" class="clearfix">
+
+ <decorator:body/>
+
+
+ <div id="local">
+ <s:action namespace="/catalog" name="catalog" executeResult="false" id="catalog"/>
+ <div id="categories">
+ <p class="boxTitle">Categories</p>
+
+ <div class="dtree">
+ <p><a href="javascript: categoryTree.openAll();">open all</a> | <a
+ href="javascript: categoryTree.closeAll();">close all</a></p>
+
+ <script type="text/javascript">
+ <!--
+ var categoryTopic = dojo.event.topic.getTopic("categorySelected");
+
+ function changeCategory(category) {
+ var serverUrl = "<s:url value="/catalog/remote/setActiveCategory.action"/>?categoryId=" + category;
+// dojo.debug("Url: " + serverUrl);
+ dojo.io.bind({
+ url: serverUrl,
+ load: function(type, data, event) {
+// dojo.debug("Got response: data= " + data + " event = " + event);
+ dojo.event.topic.publish("categorySelected", "" + data);
+ },
+ error: function(type, error){
+ alert( "Error selecting category : " + error.message );
+ },
+ mimetype: "text/plain"
+ });
+ }
+
+ categoryTree = new dTree('categoryTree');
+ categoryTree.add(0,-1,'Categories');
+ <s:iterator value="#catalog.catalog.findAllCategories()">
+ categoryTree.add(<s:property value="id"/>,<s:property value="(parent eq null) ? 0 : parent.id"/>,'<s:property value="name"/>','javascript: changeCategory(<s:property value="id"/>);');
+ </s:iterator>
+ document.write(categoryTree);
+ //-->
+ </script>
+ </div>
+ </div>
+
+ <div id="cart">
+ <s:div href="/catalog/remote/cart.action" theme="ajax" listenTopics="cartUpdated"
+ loadingText="loading..." id="cart-body" />
+ </div>
+ <br clear="all"/>
+ </div><!-- end sub -->
+
+
+ <div id="nav">
+ <div class="wrapper">
+ <h2 class="accessibility">Navigation</h2>
+ <ul class="clearfix">
+ <li><strong><a href="">Home</a></strong></li>
+ <li><a href="#" onclick="alert('No content yet, just an example');">Articles</a></li>
+
+ <li><a href="#" onclick="alert('No content yet, just an example');">Archive</a></li>
+ <li><a href="#" onclick="alert('No content yet, just an example');">Photos</a></li>
+ <li><a href="#" onclick="alert('No content yet, just an example');">About</a></li>
+ <li class="last"><a href="#" onclick="alert('No content yet, just an example');">Contact</a></li>
+ </ul>
+ </div>
+ <hr/>
+
+ </div><!-- end nav -->
+
+ </div><!-- end content -->
+
+
+ <div id="footer" class="clearfix">
+ <p>Copyright © 2005-06 The Apache Software Foundation.</p>
+ </div><!-- end footer -->
+ <p/>
+
+</div><!-- end page -->
+
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/dwr.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/dwr.xml
new file mode 100644
index 0000000..4400b56
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/dwr.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd">
+
+<dwr>
+ <allow>
+ <create creator="new" javascript="validator">
+ <param name="class" value="org.apache.struts2.validators.DWRValidator"/>
+ </create>
+ <convert converter="bean" match="com.opensymphony.xwork2.ValidationAwareSupport"/>
+ </allow>
+
+ <signatures>
+ <![CDATA[
+ import java.util.Map;
+ import org.apache.struts2.validators.DWRValidator;
+
+ DWRValidator.doPost(String, String, Map<String, String>);
+ ]]>
+ </signatures>
+</dwr>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh-decorator.tld b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh-decorator.tld
new file mode 100644
index 0000000..18f525c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh-decorator.tld
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
+
+<taglib>
+
+ <tlibversion>1.0</tlibversion>
+ <jspversion>1.1</jspversion>
+ <shortname>SiteMesh Decorator Tags</shortname>
+ <uri>sitemesh-decorator</uri>
+
+ <tag>
+ <name>head</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.decorator.HeadTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ </tag>
+
+ <tag>
+ <name>body</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.decorator.BodyTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ </tag>
+
+ <tag>
+ <name>title</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.decorator.TitleTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>default</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <name>getProperty</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.decorator.PropertyTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>property</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>default</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>writeEntireProperty</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <name>usePage</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag</tagclass>
+ <teiclass>com.opensymphony.module.sitemesh.taglib.decorator.UsePageTEI</teiclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>id</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <name>useHtmlPage</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag</tagclass>
+ <teiclass>com.opensymphony.module.sitemesh.taglib.decorator.UseHTMLPageTEI</teiclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>id</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+</taglib>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh-page.tld b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh-page.tld
new file mode 100644
index 0000000..797ec5d
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh-page.tld
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
+
+<taglib>
+
+ <tlibversion>1.0</tlibversion>
+ <jspversion>1.1</jspversion>
+ <shortname>SiteMesh Page Tags</shortname>
+ <uri>sitemesh-page</uri>
+
+ <tag>
+ <name>applyDecorator</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>id</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>contentType</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>encoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <!-- Deprecated tag: use applyDecorator instead -->
+ <tag>
+ <name>apply-decorator</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>page</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>title</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>id</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>contentType</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <name>encoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <name>param</name>
+ <tagclass>com.opensymphony.module.sitemesh.taglib.page.ParamTag</tagclass>
+ <bodycontent>JSP</bodycontent>
+ <attribute>
+ <name>name</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+</taglib>
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh.xml
new file mode 100644
index 0000000..4676680
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/sitemesh.xml
@@ -0,0 +1,51 @@
+<sitemesh>
+ <property name="decorators-file" value="/WEB-INF/decorators.xml"/>
+ <excludes file="${decorators-file}"/>
+
+ <page-parsers>
+ <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser"/>
+ </page-parsers>
+
+ <decorator-mappers>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
+ <param name="property.1" value="meta.decorator"/>
+ <param name="property.2" value="decorator"/>
+ </mapper>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.FrameSetDecoratorMapper">
+ </mapper>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.AgentDecoratorMapper">
+ <param name="match.MSIE" value="ie"/>
+ <param name="match.Mozilla [" value="ns"/>
+ <param name="match.Opera" value="opera"/>
+ <param name="match.Lynx" value="lynx"/>
+ </mapper>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper">
+ <param name="decorator" value="printable"/>
+ <param name="parameter.name" value="printable"/>
+ <param name="parameter.value" value="true"/>
+ </mapper>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.RobotDecoratorMapper">
+ <param name="decorator" value="robot"/>
+ </mapper>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.ParameterDecoratorMapper">
+ <param name="decorator.parameter" value="decorator"/>
+ <param name="parameter.name" value="confirm"/>
+ <param name="parameter.value" value="true"/>
+ </mapper>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.FileDecoratorMapper">
+ </mapper>
+
+ <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
+ <param name="config" value="${decorators-file}"/>
+ </mapper>
+
+ </decorator-mappers>
+
+</sitemesh>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/velocity.properties b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/velocity.properties
new file mode 100644
index 0000000..c942705
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/velocity.properties
@@ -0,0 +1,3 @@
+# Velocity Macro libraries. The struts.vm comes standard with Struts. The tigris-macros.vm comes with the config
+# browser.
+velocimacro.library = struts.vm, tigris-macros.vm
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/web.xml b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..3f9af53
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+
+ <filter>
+ <filter-name>action2</filter-name>
+ <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
+ </filter>
+
+ <filter>
+ <filter-name>sitemesh</filter-name>
+ <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>sitemesh</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>action2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>dwr</servlet-name>
+ <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>dwr</servlet-name>
+ <url-pattern>/dwr/*</url-pattern>
+ </servlet-mapping>
+
+ <welcome-file-list>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <taglib>
+ <taglib-uri>sitemesh-page</taglib-uri>
+ <taglib-location>/WEB-INF/sitemesh-page.tld</taglib-location>
+ </taglib>
+
+ <taglib>
+ <taglib-uri>sitemesh-decorator</taglib-uri>
+ <taglib-location>/WEB-INF/sitemesh-decorator.tld</taglib-location>
+ </taglib>
+
+</web-app>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/cart.jsp b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/cart.jsp
new file mode 100644
index 0000000..367b6db
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/cart.jsp
@@ -0,0 +1,13 @@
+<%
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setDateHeader("Expires", 0);
+%>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<p class="boxTitle">Shopping Cart</p>
+
+<div id="cartTable">
+ <div><span class="cartLabel">Number of Items:</span><span class="cartValue"><s:property value="numCartItems"/></span></div>
+ <div><span class="cartLabel">Total:</span><span class="cartValue"> $<s:property value="cartTotal" /></span></div>
+</div>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/category-main.jsp b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/category-main.jsp
new file mode 100644
index 0000000..f00403b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/category-main.jsp
@@ -0,0 +1,17 @@
+<%
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setDateHeader("Expires", 0);
+%>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<html>
+<head><title>Category</title>
+
+</head>
+
+<body id="page-home">
+<%--<s:action name="activeCategory" namespace="/catalog/remote" executeResult="true" />--%>
+<s:div id="main" href="/catalog/remote/activeCategory.action" theme="ajax" listenTopics="categorySelected" loadingText="loading..." />
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/category.jsp b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/category.jsp
new file mode 100644
index 0000000..30225ab
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/category.jsp
@@ -0,0 +1,48 @@
+<%
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setDateHeader("Expires", 0);
+%>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<s:if test="category != null">
+ <h3><s:if test="category.parent != null"><s:property value="category.parent.name"/> > </s:if><s:property value="category.name"/></h3>
+
+ <s:set name="categoryProducts" value="%{catalog.findProductsByCategory(category)}"/>
+ <s:if test="(#categoryProducts != null) && (#categoryProducts.size > 0)">
+ <div>
+ <s:iterator value="#categoryProducts">
+ <s:form id="qtyForm_%{id}" name="qtyForm_%{id}" namespace="/catalog/remote" action="updateQuantity" method="POST" theme="ajax" validate="true">
+ <s:hidden name="productId" value="%{id}"/>
+ <div class="product">
+ <div class="productDetails">
+ <div class="productHeader">
+ <tr>
+ <td><div class="productName"><s:property value="name"/></div></td>
+ <td><div class="productPrice">$<s:property value="price" /></div></td>
+ </tr>
+ </div>
+ <tr><td colspan="2">
+ <div class="productDescription"><s:property value="description"/></div>
+ </td></tr>
+ </div>
+ <tr><td colspan="2">
+ <p class="productQuantity">
+ Quantity: <s:textfield id="quantity" name="quantity" theme="simple" size="2" value="0"/>
+ <s:submit id="qtySubmit" name="qtySubmit" value="Update" theme="ajax" notifyTopics="cartUpdated" onLoadJS="document.qtyForm_%{id}.reset();" />
+ </p>
+ </td></tr>
+ </div>
+ </s:form>
+ </s:iterator>
+ </div>
+ </s:if>
+ <s:else>
+ <b>There are no products in this category</b>
+ </s:else>
+</s:if>
+<s:else>
+ <h2>Struts Ajax Catalog</h2>
+
+ <p>Please choose a category to start shopping.</p>
+</s:else>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/categorySet.jsp b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/categorySet.jsp
new file mode 100644
index 0000000..5f9f621
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/categorySet.jsp
@@ -0,0 +1,8 @@
+<%
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setDateHeader("Expires", 0);
+%>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<%@ page contentType="text/plain;charset=UTF-8" language="java" %>
+Category set to <s:property value="categoryId"/>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/cart.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/cart.css
new file mode 100644
index 0000000..10a1db6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/cart.css
@@ -0,0 +1,104 @@
+.boxTitle {
+ text-align:right;
+ font-style: italic;
+ font-weight: bold;
+ font-size: large;
+ padding: 0 10px 0 0;
+ margin: 0;
+ clear:right;
+}
+
+div#categories, div#cart {
+ width: 250px;
+ float: left;
+}
+div#categories {
+ display: block;
+ background-color: #f0e68c;
+ border-color: #daa520;
+}
+div#categories .dtree {
+ padding-left:5px;
+ padding-right:5px;
+}
+div#cart {
+ display:block;
+ margin-top:20px;
+ background-color: #ffdab9;
+ border-color: #8b0000;
+}
+
+div#cartTable {
+ padding-top:10px;
+ display:block;
+ width:248px;
+}
+.cartLabel, .cartValue {
+ display:table-cell;
+ margin:0px;
+ padding:0px;
+}
+.cartLabel {
+ width: 125px;
+ text-align:right;
+ padding-right:10px;
+ font-weight:bold;
+}
+.cartValue {
+ width: 100px;
+ text-align:left;
+}
+
+.product {
+ display:block;
+}
+
+.productQuantity {
+ display:block;
+ clear: both;
+ text-align:left;
+ width:98%;
+ margin-right: 2%;
+}
+
+.productDetails {
+ display:block;
+ background-color: #CDFFAA;
+ border-width: 1px;
+ border-style: solid;
+ border-color:#88D84F;
+ width:98%;
+ margin-right: 2%;
+}
+
+.productName, .productPrice, .productDescription {
+ margin: auto 0 auto 0;
+ padding: inherit 0 inherit 0;
+}
+
+.productName, .productPrice {
+ font-weight:bold;
+ padding: 10px;
+}
+
+.productName {
+ float:left;
+}
+
+.productPrice {
+ float:right;
+}
+
+.productDescription {
+ font-style: italic;
+ clear: both;
+ padding: 10px;
+ color:#696969;
+}
+
+.productAdd {
+ display:block;
+ clear: both;
+ text-align: right;
+ margin-right:2%;
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/dtree.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/dtree.css
new file mode 100644
index 0000000..8524771
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/dtree.css
@@ -0,0 +1,36 @@
+/*--------------------------------------------------|
+| dTree 2.05 | www.destroydrop.com/javascript/tree/ |
+|---------------------------------------------------|
+| Copyright (c) 2002-2003 Geir Landrö |
+|--------------------------------------------------*/
+
+/* Copyright 2006 The Apache Software Foundation. */
+.dtree {
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ color: #666;
+ white-space: nowrap;
+}
+.dtree img {
+ border: 0px;
+ vertical-align: middle;
+}
+.dtree a {
+ color: #333;
+ text-decoration: none;
+}
+.dtree a.node, .dtree a.nodeSel {
+ white-space: nowrap;
+ padding: 1px 2px 1px 2px;
+}
+.dtree a.node:hover, .dtree a.nodeSel:hover {
+ color: #333;
+ text-decoration: underline;
+}
+.dtree a.nodeSel {
+ background-color: #daa520;
+ font-style:italic;
+}
+.dtree .clip {
+ overflow: hidden;
+}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/forms.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/forms.css
new file mode 100644
index 0000000..4cc2188
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/forms.css
@@ -0,0 +1,102 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* FORM ELEMENTS */
+ form {
+ margin:0;
+ padding:0;
+ }
+ form div,
+ form p {
+ font-size: 1em;
+ margin: 0 0 1em 0;
+ padding: 0;
+ }
+ label {
+ font-weight: bold;
+ }
+ fieldset {
+ border: 1px solid #eee;
+ padding: 5px 10px;
+ margin: 0 0 1.5em 0;
+ }
+ fieldset legend {
+ color: #666;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin: 0 0 0 0px;
+ padding: 0;
+ background-color: #ECF1F9;
+ }
+ * html fieldset legend {
+ margin: 0 0 10px -10px;
+ }
+ fieldset ul {
+ list-style: none;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ fieldset ul li {
+ list-style: none;
+ margin: 0 0 0.5em 0;
+ padding: 0;
+ }
+
+
+ input, select, textarea {
+ font-size:1em;
+ font-family: arial, helvetica, verdana, sans-serif;
+
+ margin: 0;
+ padding: 2px;
+ }
+
+ input, select {
+ vertical-align:middle;
+ }
+
+ textarea {
+ width: 200px;
+ height: 8em;
+ }
+
+ input.check {
+ border: none;
+ width: auto;
+ height: auto;
+ margin: 0;
+ }
+ input.radio {
+ border: none;
+ width: auto;
+ height: auto;
+ margin: 0;
+ }
+ input.file {
+ height: auto;
+ width: 250px;
+ }
+ input.readonly {
+ background-color: transparent;
+ border: none;
+ }
+ input.button {
+ width: 10em;
+ border:1px solid black;
+ background-color: #ddd;
+ }
+ input.image {
+ border: none;
+ width: auto;
+ height: auto;
+ }
+
+ form div.submit {
+ margin: 1em 0;
+ }
+ form div.submit input {
+ height: 2em;
+ width: 15em;
+ }
+
+/* END FORM ELEMENTS */
+
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout-navtop-1col.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout-navtop-1col.css
new file mode 100644
index 0000000..1eab480
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout-navtop-1col.css
@@ -0,0 +1,33 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-horizontal.css");
+
+/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */
+ div#content {
+ position: relative;
+ width: 701px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ width: 100%;
+ }
+ div#local {
+ width: 100%;
+ display: none;
+ }
+ div#sub {
+ width: 100%;
+ }
+ div#nav {
+ position: absolute;
+ top: -15px;
+ left: 0;
+ width: 100%;
+
+ text-align: left;
+ }
+/* END CONTENT */
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout-navtop-localleft.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout-navtop-localleft.css
new file mode 100644
index 0000000..69eb59c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout-navtop-localleft.css
@@ -0,0 +1,36 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-horizontal.css");
+
+/* NAV BAR AT THE TOP, LOCAL NAVIGATION ON THE LEFT AND ONE COLUMN OF CONTENT */
+ div#content {
+ position: relative;
+ width: 701px;
+
+ margin: 5em auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ float: right;
+ width: 425px;
+ display: inline;
+ }
+ div#local {
+ float: left;
+ width: 275px;
+ display: inline;
+ }
+ div#sub {
+ display: none;
+ }
+ div#nav {
+ position: absolute;
+ top: -15px;
+ left: 0;
+ width: 100%;
+
+ text-align: left;
+ }
+/* END CONTENT */
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout.css
new file mode 100644
index 0000000..fc7af87
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/layout.css
@@ -0,0 +1,136 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* SITE SPECIFIC LAYOUT */
+ body {
+ margin: 0;
+ padding: 0;
+
+ background: white;
+
+ text-align: center;
+ }
+ div#page {
+ width: 780px;
+
+ margin: 0 auto;
+ padding: 0;
+
+ text-align: center;
+ }
+
+ /* HEADER */
+ div#header {
+ margin: 0;
+ padding: 5px 0px 0 0;
+
+ color: white;
+ background: #818EBD;
+
+ text-align: left;
+ }
+ div#branding {
+ float: left;
+ width: 40%;
+
+ margin: 0;
+ padding: 5px 0 5px 10px;
+
+ text-align: left;
+ }
+ div#search {
+ float: right;
+ width: 49%;
+
+ margin: 0;
+ padding: 8px 10px 0 0;
+
+ text-align: right;
+ }
+ div#header_spacer {
+ display: block;
+ height: 5em;
+ background-color: transparent;
+ }
+ /* END HEADER */
+
+
+ /* CONTENT */
+
+ /* END HEADER */
+
+
+ /* CONTENT */
+ div#content {
+
+ }
+
+ /* MAIN */
+ div#main {
+
+ }
+ /* END MAIN */
+
+ /* SUB */
+ div#sub {
+
+ }
+ /* END SUB */
+
+ /* END CONTENT */
+
+
+ /* FOOTER */
+ div#footer {
+ color: white;
+ background-color: #818EBD;
+ border-width:0;
+ margin-bottom: 4px;
+ }
+ div#footer p {
+ font-size: 0.8em;
+
+ margin: 0;
+ padding: 5px;
+ }
+ /* END FOOTER */
+/* END LAYOUT */
+
+
+
+
+/* UL.SUBNAV */
+ ul.subnav {
+ margin: 0;
+ padding: 0;
+
+ font-size: 0.8em;
+ list-style: none;
+ }
+ ul.subnav li {
+ margin: 0 0 1em 0;
+ padding: 0;
+ list-style: none;
+ }
+ ul.subnav li a,
+ ul.subnav li a:link,
+ ul.subnav li a:visited,
+ ul.subnav li a:active {
+ text-decoration: none;
+ font-weight: bold;
+ color: black;
+ }
+ ul.subnav li a:hover {
+ text-decoration: underline;
+ }
+ ul.subnav li strong {
+ padding: 0 0 0 12px;
+ background: url("../i/subnav-highlight.gif") left top no-repeat transparent;
+ }
+ ul.subnav li strong a,
+ ul.subnav li strong a:link,
+ ul.subnav li strong a:visited,
+ ul.subnav li strong a:active {
+ color: white;
+ background-color: #818EBD;
+ }
+/* END UL.SUBNAV */
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/main.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/main.css
new file mode 100644
index 0000000..3085ed3
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/main.css
@@ -0,0 +1,5 @@
+@import url(layout-navtop-localleft.css);
+@import url(layout.css);
+@import url(forms.css);
+@import url(typo.css);
+@import url(tools.css);
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/nav-horizontal.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/nav-horizontal.css
new file mode 100644
index 0000000..569b689
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/nav-horizontal.css
@@ -0,0 +1,80 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* NAV */
+ div#nav {
+ font-size: 0.8em;
+ }
+ * html div#nav {
+ /* hide ie/mac \*/
+ height: 1%;
+ /* end hide */
+ }
+ div#nav div.wrapper {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ }
+ div#nav ul {
+ width: auto;
+ width: 100%;
+
+ margin: 0;
+ padding: 0;
+
+ line-height: 1em;
+ list-style: none;
+ }
+ div#nav li {
+ float: left;
+ display: inline;
+
+ list-style: none;
+
+ margin: 0;
+ padding: 0;
+
+ line-height: 1em;
+ border-right: 1px solid #aaa;
+ }
+ div#nav li.last {
+ border-right: none;
+ }
+ div#nav a,
+ div#nav a:link,
+ div#nav a:active,
+ div#nav a:visited {
+ display: inline-block;
+ /* hide from ie/mac \*/
+ display: block;
+ /* end hide */
+ font-weight: bold;
+ text-decoration: none;
+
+ margin: 0;
+ padding: 5px 38px 5px 38px;
+
+ color: black;
+ background: #ddd;
+ }
+ div#nav a:hover {
+ text-decoration: underline;
+ }
+ div#nav strong {
+ display: inline-block;
+ /* hide from ie/mac \*/
+ display: block;
+ /* end hide */
+
+ color: white;
+ background: #818EBD;
+ }
+ div#nav strong a,
+ div#nav strong a:link,
+ div#nav strong a:active,
+ div#nav strong a:visited,
+ div#nav strong a:hover {
+ color: white;
+ background-color: #818EBD;
+ }
+/* END NAV */
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftyCorners.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftyCorners.css
new file mode 100644
index 0000000..e47fc12
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftyCorners.css
@@ -0,0 +1,21 @@
+.rtop,.artop{display:block}
+.rtop *,.artop *{display:block;height:1px;overflow:hidden;font-size:1px}
+.artop *{border-style: solid;border-width:0 1px}
+.r1,.rl1,.re1,.rel1{margin-left:5px}
+.r1,.rr1,.re1,.rer1{margin-right:5px}
+.r2,.rl2,.re2,.rel2,.ra1,.ral1{margin-left:3px}
+.r2,.rr2,.re2,.rer2,.ra1,.rar1{margin-right:3px}
+.r3,.rl3,.re3,.rel3,.ra2,.ral2,.rs1,.rsl1,.res1,.resl1{margin-left:2px}
+.r3,.rr3,.re3,.rer3,.ra2,.rar2,.rs1,.rsr1,.res1,.resr1{margin-right:2px}
+.r4,.rl4,.rs2,.rsl2,.re4,.rel4,.ra3,.ral3,.ras1,.rasl1,.res2,.resl2{margin-left:1px}
+.r4,.rr4,.rs2,.rsr2,.re4,.rer4,.ra3,.rar3,.ras1,.rasr1,.res2,.resr2{margin-right:1px}
+.rx1,.rxl1{border-left-width:5px}
+.rx1,.rxr1{border-right-width:5px}
+.rx2,.rxl2{border-left-width:3px}
+.rx2,.rxr2{border-right-width:3px}
+.re2,.rel2,.ra1,.ral1,.rx3,.rxl3,.rxs1,.rxsl1{border-left-width:2px}
+.re2,.rer2,.ra1,.rar1,.rx3,.rxr3,.rxs1,.rxsr1{border-right-width:2px}
+.rxl1,.rxl2,.rxl3,.rxl4,.rxsl1,.rxsl2,.ral1,.ral2,.ral3,.ral4,.rasl1,.rasl2{border-right-width:0}
+.rxr1,.rxr2,.rxr3,.rxr4,.rxsr1,.rxsr2,.rar1,.rar2,.rar3,.rar4,.rasr1,.rasr2{border-left-width:0}
+.r4,.rl4,.rr4,.re4,.rel4,.rer4,.ra4,.rar4,.ral4,.rx4,.rxl4,.rxr4{height:2px}
+.rer1,.rel1,.re1,.res1,.resl1,.resr1{border-width:1px 0 0;height:0px !important;height /**/:1px}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftyPrint.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftyPrint.css
new file mode 100644
index 0000000..2a871e0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftyPrint.css
@@ -0,0 +1,2 @@
+.rtop,.artop{display: none}
+
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftylayout.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftylayout.css
new file mode 100644
index 0000000..4afce1b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/niftylayout.css
@@ -0,0 +1,57 @@
+/*typography*/
+body{font: 76% verdana,arial,sans-serif;text-align: center}
+h1,h2,h3{font-family: "Trebuchet MS",arial,sans-serif}
+h1{font-size: 200%}
+h2{font-size: 160%}
+h3{font-size:110%;text-transform:uppercase;letter-spacing:1px;margin:0 5px}
+h2,p{margin: 0 15px;padding:0}
+p{padding-bottom: 0.7em;line-height: 1.5}
+a{text-decoration: none}
+address{padding: 3px 15px;font-style:normal}
+div#relax p{font-size: 120%}
+
+
+/*layout*/
+html{height: 100%; margin-bottom: 1px}
+html,body{margin:0;padding:0 0 20px}
+div#container{width: 550px;margin: 0 auto;text-align: left}
+div#header{margin:0 0 10px;padding: 0 0 5px}
+div#header h1{margin:0 5px;padding:60px 0 2px}
+div#header a{margin-left: 10px}
+div#sidebar{float: right;width: 150px}
+div#sidebar div{padding: 5px 0;margin-bottom: 5px}
+div#sidebar div#menu{margin: 0 5px}
+div#nav ul,div#nav li{margin:0;padding:0;list-style-type:none;line-height: 1.5}
+div#nav a{margin-left:5px;padding-left:10px}
+div#sidebar p{margin: 0 5px;padding:0}
+div#sidebar p+p{margin-top: 0.7em}
+form{margin: 5px 0;padding: 5px 0}
+form h3{margin-bottom: 10px}
+form div{padding: 5px 0}
+form input#find{width: 90px;margin-left:10px}
+div#content{width:395px;padding:5px 0}
+blockquote{float:left;display:inline;width: 200px;margin: 0 10px 5px 15px;padding: 5px 0}
+blockquote p{margin:0;padding: 0 5px;text-align: center}
+div#relax{margin: 0 15px 10px;padding: 5px 0}
+div#relax p, div#relax h2{margin: 0 5px}
+div#footer{clear: right;margin-top: 10px}
+
+/*colors*/
+body{background: #D6DEEC}
+div#header{background: #84B7FF}
+div#header h1{background: #657DA6}
+h1 a{color: #C1E6FF}
+h1 a:hover{color: #fff}
+h2{color: #f60}
+h3{color: #B02A36}
+div#nav{background: #95B3DE}
+div#nav a{background: url(bullet.jpg) no-repeat center left;color: #2660B1}
+div#nav a:hover{color: #FFF}
+div#sidenotes{background:#B1C0D5}
+form{background: #B4CEF7}
+div#content{background: #FFF}
+blockquote{background: #CDFFAA}
+div#relax{background: url(relax.jpg)}
+div#relax h2{color: #F7DEB5}
+div#relax p{color: #fff}
+div#footer{background: #CCC;color: #333}
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/tools.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/tools.css
new file mode 100644
index 0000000..351b103
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/tools.css
@@ -0,0 +1,68 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* clearing */
+ .stretch,
+ .clear {
+ clear:both;
+ height:1px;
+ margin:0;
+ padding:0;
+ font-size: 15px;
+ line-height: 1px;
+ }
+ .clearfix:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+ * html>body .clearfix {
+ display: inline-block;
+ width: 100%;
+ }
+
+ * html .clearfix {
+ /* Hides from IE-mac \*/
+ height: 1%;
+ /* End hide from IE-mac */
+ }
+/* end clearing */
+
+
+/* replace */
+ .replace {
+ display:block;
+
+ background-repeat: no-repeat;
+ background-position: left top;
+ background-color:transparent;
+ }
+ /* tidy these up */
+ .replace * {
+ text-indent: -10000px;
+ display:block;
+
+ background-repeat: no-repeat;
+ background-position: left top;
+ background-color:transparent;
+ }
+ .replace a {
+ text-indent:0;
+ }
+ .replace a span {
+ text-indent:-10000px;
+ }
+/* end replace */
+
+
+/* accessibility */
+ span.accesskey {
+ text-decoration:none;
+ }
+ .accessibility {
+ position: absolute;
+ top: -999em;
+ left: -999em;
+ }
+/* end accessibility */
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/typo.css b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/typo.css
new file mode 100644
index 0000000..349bd0b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/css/typo.css
@@ -0,0 +1,195 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* TYPOGRAPHY */
+ body {
+ text-align: left;
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size: 76%;
+ line-height: 1em;
+ color: #333;
+ background: White;
+ }
+ div {
+ font-size: 1em;
+ }
+ img {
+ border: 0;
+ }
+
+/* LINKS */
+ a,
+ a:link
+ a:active {
+ color: blue;
+ text-decoration: underline;
+ }
+ a:visited {
+ color: purple;
+ }
+ a:hover {
+ color: red;
+ text-decoration: none;
+ }
+/* END LINKS */
+
+/* HEADINGS */
+ h1 {
+ font-size: 2em;
+ line-height: 1.5em;
+ margin: 0 0 0.5em 0;
+ padding: 0;
+ color: black;
+ }
+
+ h1.title {
+ font-style: italic;
+ font-weight: bold;
+ color: white;
+ }
+
+ h2 {
+ font-size: 1.5em;
+ line-height: 1.5em;
+ margin: 0 0 0.5em 0;
+ padding: 0;
+ color: black;
+ }
+ h3 {
+ font-size: 1.3em;
+ line-height: 1.3em;
+ margin: 0 0 0.5em 0;
+ padding:0;
+ color: black;
+ }
+ h4 {
+ font-size: 1.2em;
+ line-height: 1.3em;
+ margin: 0 0 0.25em 0;
+ padding: 0;
+ color: black;
+ }
+ h5 {
+ font-size: 1.1em;
+ line-height: 1.3em;
+ margin: 0 0 0.25em 0;
+ padding: 0;
+ color: black;
+ }
+ h6 {
+ font-size: 1em;
+ line-height: 1.3em;
+ margin: 0 0 0.25em 0;
+ padding: 0;
+ color: black;
+ }
+/* END HEADINGS */
+
+/* TEXT */
+ p {
+ font-size: 1em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ line-height:1.4em;
+ }
+
+ blockquote {
+ margin-left:10px;
+ margin-right:10px;
+ margin-top:0px;
+ margin-bottom:0px;
+ display: block;
+ font: italic large Verdana, Geneva, Arial, Helvetica, sans-serif;
+ color: #A9A9A9;
+ background-color:#CDFFAA;
+ }
+
+ blockquote p {
+ padding:5px;
+ margin: 0;
+ }
+
+ pre {
+ font-family: monospace;
+ font-size: 1.0em;
+ }
+ strong, b {
+ font-weight: bold;
+ }
+ em, i {
+ font-style:italic;
+ }
+ code {
+ font-family: "Courier New", Courier, monospace;
+ font-size: 1em;
+ white-space: pre;
+ }
+/* END TEXT */
+
+/* LISTS */
+ ul {
+ line-height:1.4em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ ul li {
+ margin: 0 0 0.25em 30px;
+ padding: 0;
+ }
+ ol {
+ font-size: 1.0em;
+ line-height: 1.4em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ ol li {
+ font-size: 1.0em;
+ margin: 0 0 0.25em 30px;
+ padding: 0;
+ }
+ dl {
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ line-height: 1.4em;
+ }
+ dl dt {
+ font-weight: bold;
+ margin: 0.25em 0 0.25em 0;
+ padding: 0;
+ }
+ dl dd {
+ margin: 0 0 0 30px;
+ padding: 0;
+ }
+/* END LISTS */
+
+
+/* TABLE */
+ table {
+ font-size: 1em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ table caption {
+ font-weight: bold;
+ margin: 0 0 0 0;
+ padding: 0 0 1.5em 0;
+ }
+ th {
+ font-weight: bold;
+ text-align: left;
+ }
+ td {
+ font-size: 1em;
+ }
+/* END TABLE */
+
+ hr {
+ display: none;
+ }
+ div.hr {
+ height: 1px;
+ margin: 1.5em 10px;
+ border-bottom: 1px dotted black;
+ }
+
+/* END TYPOGRAPHY */
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/base.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/base.gif
new file mode 100644
index 0000000..9ac0b11
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/base.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/cd.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/cd.gif
new file mode 100644
index 0000000..7503819
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/cd.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/empty.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/empty.gif
new file mode 100644
index 0000000..b5cf523
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/empty.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/folder.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/folder.gif
new file mode 100644
index 0000000..eb12976
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/folder.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/folderopen.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/folderopen.gif
new file mode 100644
index 0000000..c5c3110
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/folderopen.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/globe.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/globe.gif
new file mode 100644
index 0000000..57123d0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/globe.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/imgfolder.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/imgfolder.gif
new file mode 100644
index 0000000..e6d8803
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/imgfolder.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/join.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/join.gif
new file mode 100644
index 0000000..34dd476
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/join.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/joinbottom.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/joinbottom.gif
new file mode 100644
index 0000000..48b81c8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/joinbottom.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/line.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/line.gif
new file mode 100644
index 0000000..1a259ee
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/line.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/minus.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/minus.gif
new file mode 100644
index 0000000..3d212a9
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/minus.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/minusbottom.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/minusbottom.gif
new file mode 100644
index 0000000..dc3198b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/minusbottom.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/musicfolder.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/musicfolder.gif
new file mode 100644
index 0000000..f620789
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/musicfolder.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/nolines_minus.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/nolines_minus.gif
new file mode 100644
index 0000000..2592ac2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/nolines_minus.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/nolines_plus.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/nolines_plus.gif
new file mode 100644
index 0000000..f258ce2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/nolines_plus.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/page.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/page.gif
new file mode 100644
index 0000000..42d7318
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/page.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/plus.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/plus.gif
new file mode 100644
index 0000000..b2c9972
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/plus.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/plusbottom.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/plusbottom.gif
new file mode 100644
index 0000000..b5671d8
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/plusbottom.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/question.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/question.gif
new file mode 100644
index 0000000..dd4e685
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/question.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/trash.gif b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/trash.gif
new file mode 100644
index 0000000..cfa0f00
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/dtree/trash.gif
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/logo-small.png b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/logo-small.png
new file mode 100644
index 0000000..7437edd
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/logo-small.png
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/logo.png b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/logo.png
new file mode 100644
index 0000000..d77172a
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/images/logo.png
Binary files differ
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/index.jsp b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/index.jsp
new file mode 100644
index 0000000..b7cc989
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/index.jsp
@@ -0,0 +1,9 @@
+<html>
+<head>
+ <title>Start</title>
+ <meta http-equiv="refresh" content="1;URL=<%=request.getContextPath()%>/catalog/main.action">
+</head>
+<body>
+ Starting application
+</body>
+</html>
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/js/dtree.js b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/js/dtree.js
new file mode 100644
index 0000000..9c778b5
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/js/dtree.js
@@ -0,0 +1,348 @@
+/*--------------------------------------------------|
+| dTree 2.05 | www.destroydrop.com/javascript/tree/ |
+|---------------------------------------------------|
+| Copyright (c) 2002-2003 Geir Landr� |
+| |
+| This script can be used freely as long as all |
+| copyright messages are intact. |
+| |
+| Updated: 17.04.2003 |
+|--------------------------------------------------*/
+
+/* Copyright 2006 The Apache Software Foundation. */
+// Node object
+function Node(id, pid, name, url, title, target, icon, iconOpen, open) {
+ this.id = id;
+ this.pid = pid;
+ this.name = name;
+ this.url = url;
+ this.title = title;
+ this.target = target;
+ this.icon = icon;
+ this.iconOpen = iconOpen;
+ this._io = open || false;
+ this._is = false;
+ this._ls = false;
+ this._hc = false;
+ this._ai = 0;
+ this._p;
+};
+
+// Tree object
+function dTree(objName) {
+ this.config = {
+ target : null,
+ folderLinks : true,
+ useSelection : true,
+ useCookies : true,
+ useLines : true,
+ useIcons : true,
+ useStatusText : false,
+ closeSameLevel : false,
+ inOrder : false
+ }
+ this.icon = {
+ root : '/shopping-cart/images/dtree/base.gif',
+ folder : '/shopping-cart/images/dtree/folder.gif',
+ folderOpen : '/shopping-cart/images/dtree/folderopen.gif',
+ node : '/shopping-cart/images/dtree/page.gif',
+ empty : '/shopping-cart/images/dtree/empty.gif',
+ line : '/shopping-cart/images/dtree/line.gif',
+ join : '/shopping-cart/images/dtree/join.gif',
+ joinBottom : '/shopping-cart/images/dtree/joinbottom.gif',
+ plus : '/shopping-cart/images/dtree/plus.gif',
+ plusBottom : '/shopping-cart/images/dtree/plusbottom.gif',
+ minus : '/shopping-cart/images/dtree/minus.gif',
+ minusBottom : '/shopping-cart/images/dtree/minusbottom.gif',
+ nlPlus : '/shopping-cart/images/dtree/nolines_plus.gif',
+ nlMinus : '/shopping-cart/images/dtree/nolines_minus.gif'
+ };
+ this.obj = objName;
+ this.aNodes = [];
+ this.aIndent = [];
+ this.root = new Node(-1);
+ this.selectedNode = null;
+ this.selectedFound = false;
+ this.completed = false;
+};
+
+// Adds a new node to the node array
+dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open) {
+ this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, title, target, icon, iconOpen, open);
+};
+
+// Open/close all nodes
+dTree.prototype.openAll = function() {
+ this.oAll(true);
+};
+dTree.prototype.closeAll = function() {
+ this.oAll(false);
+};
+
+// Outputs the tree to the page
+dTree.prototype.toString = function() {
+ var str = '<div class="dtree">\n';
+ if (document.getElementById) {
+ if (this.config.useCookies) this.selectedNode = this.getSelected();
+ str += this.addNode(this.root);
+ } else str += 'Browser not supported.';
+ str += '</div>';
+ if (!this.selectedFound) this.selectedNode = null;
+ this.completed = true;
+ return str;
+};
+
+// Creates the tree structure
+dTree.prototype.addNode = function(pNode) {
+ var str = '';
+ var n=0;
+ if (this.config.inOrder) n = pNode._ai;
+ for (n; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].pid == pNode.id) {
+ var cn = this.aNodes[n];
+ cn._p = pNode;
+ cn._ai = n;
+ this.setCS(cn);
+ if (!cn.target && this.config.target) cn.target = this.config.target;
+ if (cn._hc && !cn._io && this.config.useCookies) cn._io = this.isOpen(cn.id);
+ if (!this.config.folderLinks && cn._hc) cn.url = null;
+ if (this.config.useSelection && cn.id == this.selectedNode && !this.selectedFound) {
+ cn._is = true;
+ this.selectedNode = n;
+ this.selectedFound = true;
+ }
+ str += this.node(cn, n);
+ if (cn._ls) break;
+ }
+ }
+ return str;
+};
+
+// Creates the node icon, url and text
+dTree.prototype.node = function(node, nodeId) {
+ var str = '<div class="dTreeNode">' + this.indent(node, nodeId);
+ if (this.config.useIcons) {
+ if (!node.icon) node.icon = (this.root.id == node.pid) ? this.icon.root : ((node._hc) ? this.icon.folder : this.icon.node);
+ if (!node.iconOpen) node.iconOpen = (node._hc) ? this.icon.folderOpen : this.icon.node;
+ if (this.root.id == node.pid) {
+ node.icon = this.icon.root;
+ node.iconOpen = this.icon.root;
+ }
+ str += '<img id="i' + this.obj + nodeId + '" src="' + ((node._io) ? node.iconOpen : node.icon) + '" alt="" />';
+ }
+ if (node.url) {
+ str += '<a id="s' + this.obj + nodeId + '" class="' + ((this.config.useSelection) ? ((node._is ? 'nodeSel' : 'node')) : 'node') + '" href="' + node.url + '"';
+ if (node.title) str += ' title="' + node.title + '"';
+ if (node.target) str += ' target="' + node.target + '"';
+ if (this.config.useStatusText) str += ' onmouseover="window.status=\'' + node.name + '\';return true;" onmouseout="window.status=\'\';return true;" ';
+ if (this.config.useSelection && ((node._hc && this.config.folderLinks) || !node._hc))
+ str += ' onclick="javascript: ' + this.obj + '.s(' + nodeId + ');"';
+ str += '>';
+ }
+ else if ((!this.config.folderLinks || !node.url) && node._hc && node.pid != this.root.id)
+ str += '<a href="javascript: ' + this.obj + '.o(' + nodeId + ');" class="node">';
+ str += node.name;
+ if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += '</a>';
+ str += '</div>';
+ if (node._hc) {
+ str += '<div id="d' + this.obj + nodeId + '" class="clip" style="display:' + ((this.root.id == node.pid || node._io) ? 'block' : 'none') + ';">';
+ str += this.addNode(node);
+ str += '</div>';
+ }
+ this.aIndent.pop();
+ return str;
+};
+
+// Adds the empty and line icons
+dTree.prototype.indent = function(node, nodeId) {
+ var str = '';
+ if (this.root.id != node.pid) {
+ for (var n=0; n<this.aIndent.length; n++)
+ str += '<img src="' + ( (this.aIndent[n] == 1 && this.config.useLines) ? this.icon.line : this.icon.empty ) + '" alt="" />';
+ (node._ls) ? this.aIndent.push(0) : this.aIndent.push(1);
+ if (node._hc) {
+ str += '<a href="javascript: ' + this.obj + '.o(' + nodeId + ');"><img id="j' + this.obj + nodeId + '" src="';
+ if (!this.config.useLines) str += (node._io) ? this.icon.nlMinus : this.icon.nlPlus;
+ else str += ( (node._io) ? ((node._ls && this.config.useLines) ? this.icon.minusBottom : this.icon.minus) : ((node._ls && this.config.useLines) ? this.icon.plusBottom : this.icon.plus ) );
+ str += '" alt="" /></a>';
+ } else str += '<img src="' + ( (this.config.useLines) ? ((node._ls) ? this.icon.joinBottom : this.icon.join ) : this.icon.empty) + '" alt="" />';
+ }
+ return str;
+};
+
+// Checks if a node has any children and if it is the last sibling
+dTree.prototype.setCS = function(node) {
+ var lastId;
+ for (var n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].pid == node.id) node._hc = true;
+ if (this.aNodes[n].pid == node.pid) lastId = this.aNodes[n].id;
+ }
+ if (lastId==node.id) node._ls = true;
+};
+
+// Returns the selected node
+dTree.prototype.getSelected = function() {
+ var sn = this.getCookie('cs' + this.obj);
+ return (sn) ? sn : null;
+};
+
+// Highlights the selected node
+dTree.prototype.s = function(id) {
+ if (!this.config.useSelection) return;
+ var cn = this.aNodes[id];
+ if (cn._hc && !this.config.folderLinks) return;
+ if (this.selectedNode != id) {
+ if (this.selectedNode || this.selectedNode==0) {
+ eOld = document.getElementById("s" + this.obj + this.selectedNode);
+ eOld.className = "node";
+ }
+ eNew = document.getElementById("s" + this.obj + id);
+ eNew.className = "nodeSel";
+ this.selectedNode = id;
+ if (this.config.useCookies) this.setCookie('cs' + this.obj, cn.id);
+ }
+};
+
+// Toggle Open or close
+dTree.prototype.o = function(id) {
+ var cn = this.aNodes[id];
+ this.nodeStatus(!cn._io, id, cn._ls);
+ cn._io = !cn._io;
+ if (this.config.closeSameLevel) this.closeLevel(cn);
+ if (this.config.useCookies) this.updateCookie();
+};
+
+// Open or close all nodes
+dTree.prototype.oAll = function(status) {
+ for (var n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n]._hc && this.aNodes[n].pid != this.root.id) {
+ this.nodeStatus(status, n, this.aNodes[n]._ls)
+ this.aNodes[n]._io = status;
+ }
+ }
+ if (this.config.useCookies) this.updateCookie();
+};
+
+// Opens the tree to a specific node
+dTree.prototype.openTo = function(nId, bSelect, bFirst) {
+ if (!bFirst) {
+ for (var n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].id == nId) {
+ nId=n;
+ break;
+ }
+ }
+ }
+ var cn=this.aNodes[nId];
+ if (cn.pid==this.root.id || !cn._p) return;
+ cn._io = true;
+ cn._is = bSelect;
+ if (this.completed && cn._hc) this.nodeStatus(true, cn._ai, cn._ls);
+ if (this.completed && bSelect) this.s(cn._ai);
+ else if (bSelect) this._sn=cn._ai;
+ this.openTo(cn._p._ai, false, true);
+};
+
+// Closes all nodes on the same level as certain node
+dTree.prototype.closeLevel = function(node) {
+ for (var n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].pid == node.pid && this.aNodes[n].id != node.id && this.aNodes[n]._hc) {
+ this.nodeStatus(false, n, this.aNodes[n]._ls);
+ this.aNodes[n]._io = false;
+ this.closeAllChildren(this.aNodes[n]);
+ }
+ }
+}
+
+// Closes all children of a node
+dTree.prototype.closeAllChildren = function(node) {
+ for (var n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n].pid == node.id && this.aNodes[n]._hc) {
+ if (this.aNodes[n]._io) this.nodeStatus(false, n, this.aNodes[n]._ls);
+ this.aNodes[n]._io = false;
+ this.closeAllChildren(this.aNodes[n]);
+ }
+ }
+}
+
+// Change the status of a node(open or closed)
+dTree.prototype.nodeStatus = function(status, id, bottom) {
+ eDiv = document.getElementById('d' + this.obj + id);
+ eJoin = document.getElementById('j' + this.obj + id);
+ if (this.config.useIcons) {
+ eIcon = document.getElementById('i' + this.obj + id);
+ eIcon.src = (status) ? this.aNodes[id].iconOpen : this.aNodes[id].icon;
+ }
+ eJoin.src = (this.config.useLines)?
+ ((status)?((bottom)?this.icon.minusBottom:this.icon.minus):((bottom)?this.icon.plusBottom:this.icon.plus)):
+ ((status)?this.icon.nlMinus:this.icon.nlPlus);
+ eDiv.style.display = (status) ? 'block': 'none';
+};
+
+
+// [Cookie] Clears a cookie
+dTree.prototype.clearCookie = function() {
+ var now = new Date();
+ var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
+ this.setCookie('co'+this.obj, 'cookieValue', yesterday);
+ this.setCookie('cs'+this.obj, 'cookieValue', yesterday);
+};
+
+// [Cookie] Sets value in a cookie
+dTree.prototype.setCookie = function(cookieName, cookieValue, expires, path, domain, secure) {
+ document.cookie =
+ escape(cookieName) + '=' + escape(cookieValue)
+ + (expires ? '; expires=' + expires.toGMTString() : '')
+ + (path ? '; path=' + path : '')
+ + (domain ? '; domain=' + domain : '')
+ + (secure ? '; secure' : '');
+};
+
+// [Cookie] Gets a value from a cookie
+dTree.prototype.getCookie = function(cookieName) {
+ var cookieValue = '';
+ var posName = document.cookie.indexOf(escape(cookieName) + '=');
+ if (posName != -1) {
+ var posValue = posName + (escape(cookieName) + '=').length;
+ var endPos = document.cookie.indexOf(';', posValue);
+ if (endPos != -1) cookieValue = unescape(document.cookie.substring(posValue, endPos));
+ else cookieValue = unescape(document.cookie.substring(posValue));
+ }
+ return (cookieValue);
+};
+
+// [Cookie] Returns ids of open nodes as a string
+dTree.prototype.updateCookie = function() {
+ var str = '';
+ for (var n=0; n<this.aNodes.length; n++) {
+ if (this.aNodes[n]._io && this.aNodes[n].pid != this.root.id) {
+ if (str) str += '.';
+ str += this.aNodes[n].id;
+ }
+ }
+ this.setCookie('co' + this.obj, str);
+};
+
+// [Cookie] Checks if a node id is in a cookie
+dTree.prototype.isOpen = function(id) {
+ var aOpen = this.getCookie('co' + this.obj).split('.');
+ for (var n=0; n<aOpen.length; n++)
+ if (aOpen[n] == id) return true;
+ return false;
+};
+
+// If Push and pop is not implemented by the browser
+if (!Array.prototype.push) {
+ Array.prototype.push = function array_push() {
+ for(var i=0;i<arguments.length;i++)
+ this[this.length]=arguments[i];
+ return this.length;
+ }
+};
+if (!Array.prototype.pop) {
+ Array.prototype.pop = function array_pop() {
+ lastElement = this[this.length-1];
+ this.length = Math.max(this.length-1,0);
+ return lastElement;
+ }
+};
diff --git a/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/js/nifty.js b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/js/nifty.js
new file mode 100644
index 0000000..ee6753e
--- /dev/null
+++ b/struts-sandbox/struts2/apps/shopping-cart/src/main/webapp/js/nifty.js
@@ -0,0 +1,174 @@
+function NiftyCheck(){
+if(!document.getElementById || !document.createElement)
+ return(false);
+isXHTML=/html\:/.test(document.getElementsByTagName('body')[0].nodeName);
+if(Array.prototype.push==null){Array.prototype.push=function(){
+ this[this.length]=arguments[0]; return(this.length);}}
+return(true);
+}
+
+function Rounded(selector,wich,bk,color,opt){
+var i,prefixt,prefixb,cn="r",ecolor="",edges=false,eclass="",b=false,t=false;
+
+if(color=="transparent"){
+ cn=cn+"x";
+ ecolor=bk;
+ bk="transparent";
+ }
+else if(opt && opt.indexOf("border")>=0){
+ var optar=opt.split(" ");
+ for(i=0;i<optar.length;i++)
+ if(optar[i].indexOf("#")>=0) ecolor=optar[i];
+ if(ecolor=="") ecolor="#666";
+ cn+="e";
+ edges=true;
+ }
+else if(opt && opt.indexOf("smooth")>=0){
+ cn+="a";
+ ecolor=Mix(bk,color);
+ }
+if(opt && opt.indexOf("small")>=0) cn+="s";
+prefixt=cn;
+prefixb=cn;
+if(wich.indexOf("all")>=0){t=true;b=true}
+else if(wich.indexOf("top")>=0) t="true";
+else if(wich.indexOf("tl")>=0){
+ t="true";
+ if(wich.indexOf("tr")<0) prefixt+="l";
+ }
+else if(wich.indexOf("tr")>=0){
+ t="true";
+ prefixt+="r";
+ }
+if(wich.indexOf("bottom")>=0) b=true;
+else if(wich.indexOf("bl")>=0){
+ b="true";
+ if(wich.indexOf("br")<0) prefixb+="l";
+ }
+else if(wich.indexOf("br")>=0){
+ b="true";
+ prefixb+="r";
+ }
+var v=getElementsBySelector(selector);
+var l=v.length;
+for(i=0;i<l;i++){
+ if(edges) AddBorder(v[i],ecolor);
+ if(t) AddTop(v[i],bk,color,ecolor,prefixt);
+ if(b) AddBottom(v[i],bk,color,ecolor,prefixb);
+ }
+}
+
+function AddBorder(el,bc){
+var i;
+if(!el.passed){
+ if(el.childNodes.length==1 && el.childNodes[0].nodeType==3){
+ var t=el.firstChild.nodeValue;
+ el.removeChild(el.lastChild);
+ var d=CreateEl("span");
+ d.style.display="block";
+ d.appendChild(document.createTextNode(t));
+ el.appendChild(d);
+ }
+ for(i=0;i<el.childNodes.length;i++){
+ if(el.childNodes[i].nodeType==1){
+ el.childNodes[i].style.borderLeft="1px solid "+bc;
+ el.childNodes[i].style.borderRight="1px solid "+bc;
+ }
+ }
+ }
+el.passed=true;
+}
+
+function AddTop(el,bk,color,bc,cn){
+var i,lim=4,d=CreateEl("b");
+
+if(cn.indexOf("s")>=0) lim=2;
+if(bc) d.className="artop";
+else d.className="rtop";
+d.style.backgroundColor=bk;
+for(i=1;i<=lim;i++){
+ var x=CreateEl("b");
+ x.className=cn + i;
+ x.style.backgroundColor=color;
+ if(bc) x.style.borderColor=bc;
+ d.appendChild(x);
+ }
+el.style.paddingTop=0;
+el.insertBefore(d,el.firstChild);
+}
+
+function AddBottom(el,bk,color,bc,cn){
+var i,lim=4,d=CreateEl("b");
+
+if(cn.indexOf("s")>=0) lim=2;
+if(bc) d.className="artop";
+else d.className="rtop";
+d.style.backgroundColor=bk;
+for(i=lim;i>0;i--){
+ var x=CreateEl("b");
+ x.className=cn + i;
+ x.style.backgroundColor=color;
+ if(bc) x.style.borderColor=bc;
+ d.appendChild(x);
+ }
+el.style.paddingBottom=0;
+el.appendChild(d);
+}
+
+function CreateEl(x){
+if(isXHTML) return(document.createElementNS('http://www.w3.org/1999/xhtml',x));
+else return(document.createElement(x));
+}
+
+function getElementsBySelector(selector){
+var i,selid="",selclass="",tag=selector,f,s=[],objlist=[];
+
+if(selector.indexOf(" ")>0){ //descendant selector like "tag#id tag"
+ s=selector.split(" ");
+ var fs=s[0].split("#");
+ if(fs.length==1) return(objlist);
+ f=document.getElementById(fs[1]);
+ if(f) return(f.getElementsByTagName(s[1]));
+ return(objlist);
+ }
+if(selector.indexOf("#")>0){ //id selector like "tag#id"
+ s=selector.split("#");
+ tag=s[0];
+ selid=s[1];
+ }
+if(selid!=""){
+ f=document.getElementById(selid);
+ if(f) objlist.push(f);
+ return(objlist);
+ }
+if(selector.indexOf(".")>0){ //class selector like "tag.class"
+ s=selector.split(".");
+ tag=s[0];
+ selclass=s[1];
+ }
+var v=document.getElementsByTagName(tag); // tag selector like "tag"
+if(selclass=="")
+ return(v);
+for(i=0;i<v.length;i++){
+ if(v[i].className.indexOf(selclass)>=0){
+ objlist.push(v[i]);
+ }
+ }
+return(objlist);
+}
+
+function Mix(c1,c2){
+var i,step1,step2,x,y,r=new Array(3);
+if(c1.length==4)step1=1;
+else step1=2;
+if(c2.length==4) step2=1;
+else step2=2;
+for(i=0;i<3;i++){
+ x=parseInt(c1.substr(1+step1*i,step1),16);
+ if(step1==1) x=16*x+x;
+ y=parseInt(c2.substr(1+step2*i,step2),16);
+ if(step2==1) y=16*y+y;
+ r[i]=Math.floor((x*50+y*50)/100);
+ }
+return("#"+r[0].toString(16)+r[1].toString(16)+r[2].toString(16));
+}
diff --git a/struts-sandbox/struts2/apps/starter/README.txt b/struts-sandbox/struts2/apps/starter/README.txt
new file mode 100644
index 0000000..71abfaf
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/README.txt
@@ -0,0 +1,10 @@
+README.txt - starter
+
+This is an "hello world" application that you can deploy and review, and
+perhaps use as the basis of your own application.
+
+For more on getting started with Struts, see
+
+* http://cwiki.apache.org/WW/home.html
+
+----------------------------------------------------------------------------
\ No newline at end of file
diff --git a/struts-sandbox/struts2/apps/starter/pom.xml b/struts-sandbox/struts2/apps/starter/pom.xml
new file mode 100644
index 0000000..683804b
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-apps</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-starter</artifactId>
+ <packaging>war</packaging>
+ <name>Starter Webapp</name>
+ <dependencies>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <version>6.0.0rc3</version>
+ <configuration>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-j2ee_1.4_spec</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/CounterBean.java b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/CounterBean.java
new file mode 100644
index 0000000..2254dca
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/CounterBean.java
@@ -0,0 +1,36 @@
+/*
+ * $Id: CounterBean.java 391220 2006-04-04 03:54:09Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.foo.example;
+
+/**
+ * <code>CounterBean</code>
+ *
+ * @author Rainer Hermanns
+ */
+public class CounterBean {
+
+ private static int count = 0;
+
+ public int getCount() {
+ return count;
+ }
+
+ public void increment() {
+ count++;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HelloMatrixAction-helloMatrixSubmit-validation.xml b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HelloMatrixAction-helloMatrixSubmit-validation.xml
new file mode 100644
index 0000000..93fe2d4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HelloMatrixAction-helloMatrixSubmit-validation.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+
+<validators>
+ <field name="hello">
+ <field-validator type="requiredstring">
+ <message>You must enter a name</message>
+ </field-validator>
+ </field>
+</validators>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HelloMatrixAction.java b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HelloMatrixAction.java
new file mode 100644
index 0000000..e6e8411
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HelloMatrixAction.java
@@ -0,0 +1,81 @@
+/*
+ * $Id: HelloMatrixAction.java 420385 2006-07-10 00:57:05Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.foo.example;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * <code>HelloMatrixAction</code>
+ *
+ * @author <a href="mailto:hermanns@aixcept.de">Rainer Hermanns</a>
+ * @version $Id: HelloMatrixAction.java 420385 2006-07-10 00:57:05Z mrdon $
+ */
+public class HelloMatrixAction extends ActionSupport {
+
+ /** Spring managed bean reference */
+ private CounterBean counterBean;
+
+ /**
+ * IoC setter for the spring managed CounterBean.
+ *
+ * @param counterBean
+ */
+ public void setCounterBean(CounterBean counterBean) {
+ this.counterBean = counterBean;
+ }
+
+ private String hello;
+ private String message;
+
+ public String getHello() {
+ return hello;
+ }
+
+ public void setHello(String hello) {
+ this.hello = hello;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public int getCount() {
+ return counterBean.getCount();
+ }
+
+ /**
+ * A default implementation that does nothing an returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+
+ /**
+ * Sample sayHello method.
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String sayHello() throws Exception {
+
+ message = "users already took the red pill...";
+ counterBean.increment();
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HomeAction.java b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HomeAction.java
new file mode 100644
index 0000000..253e702
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/java/com/foo/example/HomeAction.java
@@ -0,0 +1,37 @@
+/*
+ * $Id: HomeAction.java 420385 2006-07-10 00:57:05Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.foo.example;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * <code>HomeAction</code>
+ *
+ * @author Rainer Hermanns
+ */
+public class HomeAction extends ActionSupport {
+
+ /**
+ * A default implementation that does nothing an returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/struts-sandbox/struts2/apps/starter/src/main/resources/struts.properties b/struts-sandbox/struts2/apps/starter/src/main/resources/struts.properties
new file mode 100644
index 0000000..577de15
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/resources/struts.properties
@@ -0,0 +1,2 @@
+struts.devMode = true
+struts.enable.DynamicMethodInvocation = false
diff --git a/struts-sandbox/struts2/apps/starter/src/main/resources/struts.xml b/struts-sandbox/struts2/apps/starter/src/main/resources/struts.xml
new file mode 100644
index 0000000..461d039
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/resources/struts.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+ "http://struts.apache.org/dtds/struts-2.0.dtd">
+
+<struts>
+ <include file="struts-default.xml"/>
+
+ <package name="default" extends="struts-default">
+
+ <default-action-ref name="home" />
+
+ <action name="home" class="com.foo.example.HomeAction">
+ <result>/WEB-INF/pages/home.jsp</result>
+ </action>
+
+ <action name="helloMatrix" class="com.foo.example.HelloMatrixAction">
+ <result name="success">/WEB-INF/pages/hellomatrix.jsp</result>
+ </action>
+
+ <action name="helloMatrixSubmit" class="com.foo.example.HelloMatrixAction" method="sayHello">
+ <interceptor-ref name="validationWorkflowStack"/>
+ <result name="input">/WEB-INF/pages/hellomatrix.jsp</result>
+ <result name="error">/WEB-INF/pages/hellomatrix.jsp</result>
+ <result name="success" type="freemarker">/WEB-INF/pages/hellomatrix-success.ftl</result>
+ </action>
+
+ </package>
+</struts>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/applicationContext.xml b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 0000000..252ebb4
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+<beans default-autowire="autodetect">
+ <bean id="counterBean" class="com.foo.example.CounterBean" singleton="true" />
+ <!-- add your spring beans here -->
+</beans>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/hellomatrix-success.ftl b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/hellomatrix-success.ftl
new file mode 100644
index 0000000..69cb8b2
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/hellomatrix-success.ftl
@@ -0,0 +1,12 @@
+<html>
+ <head>
+ <title>Hello Matrix: Success</title>
+ </head>
+ <body>
+ <h1>${hello} just entered the matrix!</h1>
+
+ <p>
+ ${count} ${message}
+ </p>
+ </body>
+</html>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/hellomatrix.jsp b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/hellomatrix.jsp
new file mode 100644
index 0000000..378eaf0
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/hellomatrix.jsp
@@ -0,0 +1,20 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+<html>
+ <head>
+ <title>Enter the Matrix</title>
+ </head>
+ <body>
+ <h1>Enter the Matrix sample</h1>
+
+ <p>
+ <fieldset>
+ <legend>Matrix Form</legend>
+ <s:form name="helloWorldForm" action="helloMatrixSubmit">
+ <s:textfield name="hello" label="Enter your name" />
+ <s:submit />
+ </s:form>
+ </fieldset>
+ </p>
+ </body>
+</html>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/home.jsp b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/home.jsp
new file mode 100644
index 0000000..1b14ebf
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/pages/home.jsp
@@ -0,0 +1,20 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+<html>
+ <head>
+ <title>Welcome</title>
+ </head>
+ <body>
+ <h1>Welcome to the starter webapp</h1>
+
+ <p>
+ <fieldset>
+ <legend>Example action</legend>
+ <p>
+ <s:url id="helloURL" action="helloMatrix" />
+ <s:a href="%{helloURL}">Enter the matrix</s:a>
+ </p>
+ </fieldset>
+ </p>
+ </body>
+</html>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/web.xml b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..18f291c
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Acme Corp</display-name>
+
+ <!-- START SNIPPET: example -->
+ <filter>
+ <filter-name>action2</filter-name>
+ <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>action2</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <!-- END SNIPPET: example -->
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+
+ <!-- START SNIPPET: freemarkerSupport -->
+ <servlet>
+ <servlet-name>JspSupportServlet</servlet-name>
+ <servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <!-- END SNIPPET: freemarkerSupport -->
+
+ <welcome-file-list>
+ <welcome-file>index.jsp</welcome-file>
+ <welcome-file>default.jsp</welcome-file>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ <!-- START SNIPPET: taglib -->
+ <!--
+ This typically isn't required, as the taglib is included in struts-action-2.0.jar.
+ If you really need a taglib configuration within web.xml, copy struts/src/java/META-INF/taglib.tld
+ to the WEB-INF directory as tags.tld.
+ -->
+ <!--
+ <taglib>
+ <taglib-uri>tags</taglib-uri>
+ <taglib-location>/WEB-INF/tags.tld</taglib-location>
+ </taglib>
+ -->
+ <!-- END SNIPPET: taglib -->
+</web-app>
diff --git a/struts-sandbox/struts2/apps/starter/src/main/webapp/index.jsp b/struts-sandbox/struts2/apps/starter/src/main/webapp/index.jsp
new file mode 100644
index 0000000..b9efda6
--- /dev/null
+++ b/struts-sandbox/struts2/apps/starter/src/main/webapp/index.jsp
@@ -0,0 +1 @@
+<% response.sendRedirect(request.getContextPath() + "/home.action"); %>
diff --git a/struts-sandbox/struts2/legacy/pom.xml b/struts-sandbox/struts2/legacy/pom.xml
new file mode 100644
index 0000000..2ad99e2
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/pom.xml
@@ -0,0 +1,18 @@
+<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>
+ <groupId>org.apache.action2</groupId>
+ <artifactId>legacy</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <name>Maven Quick Start Archetype</name>
+ <url>http://maven.apache.org</url>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ActionFormResetInterceptor.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ActionFormResetInterceptor.java
new file mode 100644
index 0000000..c388d44
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ActionFormResetInterceptor.java
@@ -0,0 +1,51 @@
+/*
+ * $Id: Action.java 240373 2005-08-27 01:58:39Z jmitchell $
+ *
+ * Copyright 2000-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.action2.legacy;
+
+import com.opensymphony.xwork.interceptor.ModelDrivenInterceptor;
+import com.opensymphony.xwork.ActionInvocation;
+import com.opensymphony.xwork.interceptor.AroundInterceptor;
+import com.opensymphony.xwork.ObjectFactory;
+import com.opensymphony.webwork.ServletActionContext;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+
+/**
+ * Calls the reset() method on the ActionForm, if it exists.
+ */
+public class ActionFormResetInterceptor extends AroundInterceptor {
+
+ protected void after(ActionInvocation dispatcher, String result) throws Exception {
+ }
+
+ protected void before(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+
+ if (action instanceof ScopedModelDriven) {
+ ScopedModelDriven modelDriven = (ScopedModelDriven) action;
+ Object model = modelDriven.getModel();
+ if (model != null) {
+ ActionMapping mapping = StrutsFactory.getStrutsFactory().createActionMapping(invocation.getProxy().getConfig());
+ HttpServletRequest req = ServletActionContext.getRequest();
+ ((ActionForm)model).reset(mapping, req);
+ }
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ActionFormValidationInterceptor.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ActionFormValidationInterceptor.java
new file mode 100644
index 0000000..1efa890
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ActionFormValidationInterceptor.java
@@ -0,0 +1,55 @@
+/*
+ * $Id: Action.java 240373 2005-08-27 01:58:39Z jmitchell $
+ *
+ * Copyright 2000-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.action2.legacy;
+
+import com.opensymphony.xwork.interceptor.ModelDrivenInterceptor;
+import com.opensymphony.xwork.ActionInvocation;
+import com.opensymphony.xwork.interceptor.AroundInterceptor;
+import com.opensymphony.xwork.ObjectFactory;
+import com.opensymphony.webwork.ServletActionContext;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionError;
+
+/**
+ * Calls the validate() method on the ActionForm, if it exists. The errors are handled
+ * like regular XWork validation errors.
+ */
+public class ActionFormValidationInterceptor extends AroundInterceptor {
+
+ protected void after(ActionInvocation dispatcher, String result) throws Exception {
+ }
+
+ protected void before(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+
+ if (action instanceof ScopedModelDriven) {
+ ScopedModelDriven modelDriven = (ScopedModelDriven) action;
+ Object model = modelDriven.getModel();
+ if (model != null) {
+ ActionMapping mapping = StrutsFactory.getStrutsFactory().createActionMapping(invocation.getProxy().getConfig());
+ HttpServletRequest req = ServletActionContext.getRequest();
+ ActionErrors errors = ((ActionForm)model).validate(mapping, req);
+ StrutsFactory.getStrutsFactory().convertErrors(errors, action);
+ }
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/DynaBeanPropertyAccessor.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/DynaBeanPropertyAccessor.java
new file mode 100644
index 0000000..32864c5
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/DynaBeanPropertyAccessor.java
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.action2.legacy;
+
+import java.io.Serializable;
+import org.apache.commons.beanutils.DynaBean;
+import org.apache.commons.beanutils.DynaClass;
+import ognl.OgnlException;
+import ognl.PropertyAccessor;
+import java.util.Map;
+
+/**
+ * Provides access to DynaBean properties in OGNL
+ */
+public class DynaBeanPropertyAccessor implements PropertyAccessor {
+
+ public Object getProperty(Map context, Object target, Object name) throws OgnlException {
+
+ if (target instanceof DynaBean && name != null) {
+ DynaBean bean = (DynaBean)target;
+ DynaClass cls = bean.getDynaClass();
+ String key = name.toString();
+ if (cls.getDynaProperty(key) != null) {
+ return bean.get(key);
+ }
+ }
+ return null;
+ }
+
+ public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
+
+ if (target instanceof DynaBean && name != null) {
+ DynaBean bean = (DynaBean)target;
+ String key = name.toString();
+ bean.set(key, value);
+ }
+ }
+
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/LegacyObjectFactory.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/LegacyObjectFactory.java
new file mode 100755
index 0000000..26a5d09
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/LegacyObjectFactory.java
@@ -0,0 +1,67 @@
+/*
+ * $Id: Action.java 240373 2005-08-27 01:58:39Z jmitchell $
+ *
+ * Copyright 2000-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.action2.legacy;
+
+import com.opensymphony.webwork.config.Configuration;
+import com.opensymphony.webwork.util.ObjectFactoryInitializable;
+import com.opensymphony.webwork.util.ServletContextAware;
+import com.opensymphony.xwork.config.entities.*;
+import com.opensymphony.xwork.config.ConfigurationException;
+import com.opensymphony.xwork.ObjectFactory;
+import com.opensymphony.xwork.interceptor.Interceptor;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Adds support for interceptors that want the ServletContext
+ */
+public class LegacyObjectFactory extends ObjectFactory implements ObjectFactoryInitializable {
+ private static final Log log = LogFactory.getLog(LegacyObjectFactory.class);
+
+ private ServletContext servletContext;
+
+ public void init(ServletContext servletContext) {
+
+ log.info("Initializing legacy integration...");
+ this.servletContext = servletContext;
+ }
+
+ /**
+ * Builds an Interceptor from the InterceptorConfig and the Map of
+ * parameters from the interceptor reference. Implementations of this method
+ * should ensure that the Interceptor is parameterized with both the
+ * parameters from the Interceptor config and the interceptor ref Map (the
+ * interceptor ref params take precedence), and that the Interceptor.init()
+ * method is called on the Interceptor instance before it is returned.
+ *
+ * @param interceptorConfig the InterceptorConfig from the configuration
+ * @param interceptorRefParams a Map of params provided in the Interceptor reference in the
+ * Action mapping or InterceptorStack definition
+ */
+ public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException {
+ Interceptor interceptor = super.buildInterceptor(interceptorConfig, interceptorRefParams);
+ if (interceptor != null && interceptor instanceof ServletContextAware) {
+ ((ServletContextAware)interceptor).setServletContext(servletContext);
+ }
+ return interceptor;
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/PlugInInterceptor.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/PlugInInterceptor.java
new file mode 100755
index 0000000..a4fdb44
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/PlugInInterceptor.java
@@ -0,0 +1,101 @@
+/*
+ * $Id: Action.java 240373 2005-08-27 01:58:39Z jmitchell $
+ *
+ * Copyright 2000-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.action2.legacy;
+
+import com.opensymphony.xwork.interceptor.ModelDrivenInterceptor;
+import com.opensymphony.xwork.ActionInvocation;
+import com.opensymphony.xwork.interceptor.AroundInterceptor;
+import com.opensymphony.xwork.ObjectFactory;
+import com.opensymphony.xwork.util.OgnlUtil;
+import com.opensymphony.webwork.util.ServletContextAware;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.ServletContext;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.*;
+import org.apache.struts.config.*;
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.commons.logging.*;
+
+/**
+ * Supports Struts Action 1.x-style PlugIn classes by wrapping them in this
+ * no-op interceptor.
+ */
+public class PlugInInterceptor extends AroundInterceptor
+ implements ServletContextAware{
+
+ private String className;
+ private Map params = new HashMap();
+ private String modulePrefix;
+ private PlugIn plugin = null;
+ private static final Log LOG = LogFactory.getLog(PlugInInterceptor.class);
+
+ public void setClassName(String name) {
+ this.className = name;
+ }
+
+ public void setParams(Map params) {
+ this.params = params;
+ }
+
+ public Map getParams() {
+ return params;
+ }
+
+ // TODO: we should be able to find the package name/namespace during init time, but for now it's passed in as param.
+ public void setModulePrefix(String modulePrefix) {
+ this.modulePrefix = modulePrefix;
+ }
+
+ public void setServletContext(final ServletContext servletContext) {
+ ActionServlet servlet = new ActionServlet() {
+ public ServletContext getServletContext() {
+ return servletContext;
+ }
+ };
+
+ // Create a ModuleConfig based on the module prefix. This assumes that there is an existing XWork package
+ // configuration with the given module prefix.
+ ModuleConfig modConfig = StrutsFactory.getStrutsFactory().createModuleConfig(modulePrefix);
+
+ try {
+ plugin = (PlugIn) ObjectFactory.getObjectFactory().buildBean(className, null);
+ plugin.init(servlet, modConfig);
+ } catch (Exception ex) {
+ LOG.error("Unable to create or init plugin "+className, ex);
+ return;
+ }
+ if (params != null) {
+ OgnlUtil.setProperties(params, plugin);
+ }
+ }
+
+ public void destroy() {
+ plugin.destroy();
+ }
+
+ protected void after(ActionInvocation dispatcher, String result) throws Exception {
+ }
+
+ protected void before(ActionInvocation invocation) throws Exception {
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ScopedModelDriven.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ScopedModelDriven.java
new file mode 100644
index 0000000..debebbf
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ScopedModelDriven.java
@@ -0,0 +1,32 @@
+/*
+ * $Id$
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.action2.legacy;
+
+import com.opensymphony.xwork.ModelDriven;
+
+/**
+ * Adds the ability to set a model, probably retrieved from a given state.
+ */
+public interface ScopedModelDriven extends ModelDriven {
+
+ /**
+ * Sets the model
+ */
+ void setModel(Object model);
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ScopedModelDrivenInterceptor.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ScopedModelDrivenInterceptor.java
new file mode 100644
index 0000000..bcbd785
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/ScopedModelDrivenInterceptor.java
@@ -0,0 +1,70 @@
+/*
+ * $Id$
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.action2.legacy;
+
+import com.opensymphony.xwork.interceptor.ModelDrivenInterceptor;
+import com.opensymphony.xwork.ActionInvocation;
+import com.opensymphony.xwork.ActionContext;
+import com.opensymphony.xwork.ActionProxy;
+import com.opensymphony.xwork.config.entities.ActionConfig;
+import com.opensymphony.xwork.ObjectFactory;
+
+import java.util.Map;
+
+/**
+ * Retrieves the model class from the configured scope, then provides it
+ * to the Action.
+ */
+public class ScopedModelDrivenInterceptor extends ModelDrivenInterceptor {
+
+ protected void after(ActionInvocation dispatcher, String result) throws Exception {
+ }
+
+ protected void before(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+
+ if (action instanceof ScopedModelDriven) {
+ ScopedModelDriven modelDriven = (ScopedModelDriven) action;
+ ActionContext ctx = ActionContext.getContext();
+ ActionConfig config = invocation.getProxy().getConfig();
+ String scope = (String)config.getParams().get("modelScope");
+ String attr = (String)config.getParams().get("modelName");
+ String clsName = (String)config.getParams().get("modelClass");
+
+ Object model = resolveModel(ObjectFactory.getObjectFactory(), ctx.getSession(), clsName, scope, attr);
+ modelDriven.setModel(model);
+ }
+ super.before(invocation);
+ }
+
+ protected Object resolveModel(ObjectFactory factory, Map session, String className, String scope, String name) throws Exception {
+ Object model = null;
+ if ("session".equals(scope)) {
+ model = session.get(name);
+ if (model == null) {
+ model = factory.buildBean(className, null);
+ session.put(name, model);
+ }
+ } else {
+ model = factory.buildBean(className, null);
+ }
+ return model;
+ }
+
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/StrutsFactory.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/StrutsFactory.java
new file mode 100644
index 0000000..2e9d512
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/StrutsFactory.java
@@ -0,0 +1,150 @@
+/*
+ * $Id$
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.action2.legacy;
+
+import com.opensymphony.xwork.*;
+import com.opensymphony.xwork.config.entities.ActionConfig;
+import com.opensymphony.xwork.config.entities.ResultConfig;
+import com.opensymphony.xwork.config.entities.ExceptionMappingConfig;
+import org.apache.struts.action.*;
+import org.apache.struts.config.*;
+
+import java.util.Iterator;
+import java.util.Arrays;
+
+
+/**
+ * Provides conversion methods between the Struts Action 1.x and XWork
+ * classes.
+ */
+public class StrutsFactory {
+ private static StrutsFactory FACTORY = new StrutsFactory();
+
+ protected StrutsFactory() {
+ }
+
+ public static void setStrutsFactory(StrutsFactory factory) {
+ FACTORY = factory;
+ }
+
+ public static StrutsFactory getStrutsFactory() {
+ return FACTORY;
+ }
+
+ /**
+ * Create a Struts 1.x ModuleConfig based on an XWork package configuration.
+ *
+ * @param packageName the name of the XWork package configuration to wrap. This becomes the module prefix for the
+ * newly-created ModuleConfig.
+ * @return a wrapper Struts 1.x ModuleConfig.
+ */
+ public ModuleConfig createModuleConfig(String packageName) {
+ assert packageName != null;
+ return new WrapperModuleConfig(packageName);
+ }
+
+ /**
+ * Create a Struts 1.x ActionMapping from an XWork ActionConfig.
+ *
+ * @param cfg the XWork ActionConfig.
+ * @return a wrapper Struts 1.x ActionMapping.
+ */
+ public ActionMapping createActionMapping(ActionConfig cfg) {
+ assert cfg != null;
+ return new WrapperActionMapping(cfg);
+ }
+
+ /**
+ * Create a Struts 1.x ActionMapping from an XWork ActionConfig. This version provides an existing action path
+ * and ModuleConfig. Package-protected for now; may not need to be exposed publicly.
+ *
+ * @param cfg the XWork ActionConfig.
+ * @param actionPath the Struts 1.x-style action path ('/' + action-name).
+ * @param moduleConfig the Struts 1.x ModuleConfig that contains the ActionMapping.
+ * @return a wrapper Struts 1.x ActionMapping.
+ */
+ ActionMapping createActionMapping(ActionConfig cfg, String actionPath, ModuleConfig moduleConfig) {
+ assert cfg != null;
+ assert moduleConfig != null;
+ return new WrapperActionMapping(cfg, actionPath, moduleConfig);
+ }
+
+ /**
+ * Create a Struts 1.x ActionForward from an XWork ResultConfig.
+ *
+ * @param cfg the XWork ResultConfig.
+ * @return a wrapper Struts 1.x ActionMapping.
+ */
+ public ActionForward createActionForward(ResultConfig cfg) {
+ assert cfg != null;
+ return new WrapperActionForward(cfg);
+ }
+
+ /**
+ * Create a Struts 1.x ExceptionConfig from an XWork ExceptionMappingConfig.
+ *
+ * @param cfg the XWork ExceptionMappingConfig.
+ * @return a wrapper Struts 1.x ExceptionConfig.
+ */
+ public ExceptionConfig createExceptionConfig(ExceptionMappingConfig cfg) {
+ assert cfg != null;
+ return new WrapperExceptionConfig(cfg);
+ }
+
+ public void convertErrors(ActionErrors errors, Object action) {
+ ValidationAware vaction = null;
+ TextProvider text = null;
+
+ if (action instanceof ValidationAware) {
+ vaction = (ValidationAware)action;
+ }
+ if (action instanceof TextProvider) {
+ text = (TextProvider)action;
+ }
+
+ ActionMessage error = null;
+ String field = null;
+ String msg = null;
+ Object[] values = null;
+ for (Iterator i = errors.properties(); i.hasNext(); ) {
+ field = (String) i.next();
+ for (Iterator it = errors.get(field); it.hasNext(); ) {
+ error = (ActionMessage) it.next();
+ msg = error.getKey();
+ if (error.isResource() && text != null) {
+ values = error.getValues();
+ if (values != null) {
+ msg = text.getText(error.getKey(), Arrays.asList(values));
+ } else {
+ msg = text.getText(error.getKey());
+ }
+ }
+ if (vaction != null) {
+ if (field == errors.GLOBAL_MESSAGE) {
+ vaction.addActionError(msg);
+ } else {
+ vaction.addFieldError(field, msg);
+ }
+ } else {
+ // should do something here
+ }
+ }
+ }
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperActionForward.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperActionForward.java
new file mode 100644
index 0000000..8605965
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperActionForward.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.action2.legacy;
+
+import org.apache.struts.action.ActionForward;
+import com.opensymphony.xwork.config.entities.ResultConfig;
+
+/**
+ * Wrapper for a Struts 1.x ActionForward based on an XWork ResultConfig. Using a wrapper object
+ * allows us to be explicit about what is and isn't implemented.
+ */
+class WrapperActionForward extends ActionForward {
+
+ private ResultConfig delegate;
+
+ public WrapperActionForward(ResultConfig delegate) {
+ super(delegate.getName());
+ this.delegate = delegate;
+ freeze();
+ }
+
+ public String getName() {
+ return delegate.getName();
+ }
+
+ public String getPath() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getModule() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public boolean getRedirect() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String toString() {
+ return "wrapper -> " + delegate.toString();
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperActionMapping.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperActionMapping.java
new file mode 100644
index 0000000..80e22c7
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperActionMapping.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.action2.legacy;
+
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.config.ExceptionConfig;
+import org.apache.struts.config.ForwardConfig;
+import com.opensymphony.xwork.config.entities.ActionConfig;
+import com.opensymphony.xwork.config.entities.ResultConfig;
+import com.opensymphony.xwork.config.entities.ExceptionMappingConfig;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
+
+/**
+ * Wrapper for a Struts 1.x ActionMapping based on an XWork ActionConfig. Using a wrapper object
+ * allows us to be explicit about what is and isn't implemented.
+ */
+class WrapperActionMapping extends ActionMapping {
+
+ private ActionConfig delegate;
+ private String actionPath;
+
+ public WrapperActionMapping(ActionConfig delegate) {
+ this.delegate = delegate;
+ forwards = null;
+ exceptions = null;
+ }
+
+ public WrapperActionMapping(ActionConfig delegate, String actionPath, ModuleConfig moduleConfig) {
+ this(delegate);
+ this.moduleConfig = moduleConfig;
+ this.actionPath = actionPath;
+ }
+
+ /**
+ * Add Struts ForwardConfigs (from XWork ResultConfigs).
+ */
+ private void initActionForwards() {
+ if (forwards == null) {
+ forwards = new HashMap();
+ StrutsFactory strutsFactory = StrutsFactory.getStrutsFactory();
+ Map results = delegate.getResults();
+ for (Iterator i = results.entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ ActionForward wrapper = strutsFactory.createActionForward((ResultConfig) entry.getValue());
+ forwards.put(wrapper.getName(), wrapper);
+ }
+ }
+ }
+
+ /**
+ * Add XWork ExceptionConfigs (from XWork ExceptionMappingConfigs)
+ */
+ private void initExceptionConfigs() {
+ if (exceptions == null) {
+ exceptions = new HashMap();
+ StrutsFactory strutsFactory = StrutsFactory.getStrutsFactory();
+ List exceptionMappings = delegate.getExceptionMappings();
+ for (Iterator i = exceptionMappings.iterator(); i.hasNext();) {
+ ExceptionConfig wrapper = strutsFactory.createExceptionConfig((ExceptionMappingConfig) i.next());
+ exceptions.put(wrapper.getType(), wrapper);
+ }
+ }
+ }
+
+ public ActionForward findForward(String name) {
+ initActionForwards();
+ return super.findForward(name);
+ }
+
+ public String[] findForwards() {
+ initActionForwards();
+ return super.findForwards();
+ }
+
+ public ForwardConfig findForwardConfig(String name) {
+ initActionForwards();
+ return super.findForwardConfig(name);
+ }
+
+ public ForwardConfig[] findForwardConfigs() {
+ initActionForwards();
+ return super.findForwardConfigs();
+ }
+
+ public ExceptionConfig findExceptionConfig(String type) {
+ initExceptionConfigs();
+ return super.findExceptionConfig(type);
+ }
+
+ public ExceptionConfig[] findExceptionConfigs() {
+ initExceptionConfigs();
+ return super.findExceptionConfigs();
+ }
+
+ public ExceptionConfig findException(Class type) {
+ initExceptionConfigs();
+ return super.findException(type);
+ }
+
+ public ActionForward getInputForward() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public ModuleConfig getModuleConfig() {
+ if (moduleConfig == null) {
+ StrutsFactory strutsFactory = StrutsFactory.getStrutsFactory();
+ moduleConfig = strutsFactory.createModuleConfig(delegate.getPackageName());
+ }
+
+ return moduleConfig;
+ }
+
+ public void setModuleConfig(ModuleConfig moduleConfig) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getAttribute() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setAttribute(String attribute) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getForward() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setForward(String forward) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getInclude() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setInclude(String include) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getInput() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setInput(String input) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getMultipartClass() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setMultipartClass(String multipartClass) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getName() {
+ // Note: in Struts, this is a name reference to a form bean defined in the config file.
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setName(String name) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getParameter() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setParameter(String parameter) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getPath() {
+ return actionPath;
+ }
+
+ public void setPath(String path) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getPrefix() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setPrefix(String prefix) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getRoles() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setRoles(String roles) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String[] getRoleNames() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getScope() {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void setScope(String scope) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getSuffix() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setSuffix(String suffix) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getType() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setType(String type) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public boolean getUnknown() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setUnknown(boolean unknown) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public boolean getValidate() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setValidate(boolean validate) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeExceptionConfig(ExceptionConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeForwardConfig(ForwardConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addExceptionConfig(ExceptionConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addForwardConfig(ForwardConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String toString() {
+ return "wrapper -> " + delegate.toString();
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperExceptionConfig.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperExceptionConfig.java
new file mode 100644
index 0000000..4c5d266
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperExceptionConfig.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.action2.legacy;
+
+import com.opensymphony.xwork.config.entities.ExceptionMappingConfig;
+import org.apache.struts.config.ExceptionConfig;
+
+/**
+ * Wrapper for a Struts 1.x ExceptionConfig based on an XWork ExceptionMappingConfig. Using a
+ * wrapper object allows us to be explicit about what is and isn't implemented.
+ */
+class WrapperExceptionConfig extends ExceptionConfig {
+
+ private ExceptionMappingConfig delegate;
+
+ public WrapperExceptionConfig(ExceptionMappingConfig delegate) {
+ this.delegate = delegate;
+ freeze();
+ }
+
+ public String getBundle() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getHandler() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getKey() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getPath() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getScope() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public String getType() {
+ return delegate.getExceptionClassName();
+ }
+
+ public String toString() {
+ return "wrapper -> " + delegate.toString();
+ }
+}
diff --git a/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperModuleConfig.java b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperModuleConfig.java
new file mode 100644
index 0000000..8f7ee36
--- /dev/null
+++ b/struts-sandbox/struts2/legacy/src/main/java/org/apache/action2/legacy/WrapperModuleConfig.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.action2.legacy;
+
+import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.config.ControllerConfig;
+import org.apache.struts.config.DataSourceConfig;
+import org.apache.struts.config.ExceptionConfig;
+import org.apache.struts.config.FormBeanConfig;
+import org.apache.struts.config.ForwardConfig;
+import org.apache.struts.config.MessageResourcesConfig;
+import org.apache.struts.config.PlugInConfig;
+import org.apache.struts.config.ActionConfig;
+import com.opensymphony.xwork.config.ConfigurationManager;
+import com.opensymphony.xwork.config.entities.PackageConfig;
+import com.opensymphony.xwork.config.entities.ExceptionMappingConfig;
+import com.opensymphony.xwork.config.entities.ResultConfig;
+
+import java.util.Map;
+import java.util.Iterator;
+import java.util.HashMap;
+
+/**
+ * Wrapper for a Struts 1.x ModuleConfig based on an XWork PackageConfig. Using a wrapper object
+ * allows us to be explicit about what is and isn't implemented.
+ */
+class WrapperModuleConfig implements ModuleConfig {
+
+ private PackageConfig delegate;
+ private Map _actionMappings;
+ private Map _exceptionConfigs;
+ private Map _actionForwards;
+
+ public WrapperModuleConfig(String packageName) {
+ delegate = ConfigurationManager.getConfiguration().getPackageConfig(packageName);
+ }
+
+ /**
+ * Add Struts ActionMappings (from XWork ExceptionConfigs).
+ */
+ private void initActionMappings() {
+
+ if (_actionMappings == null) {
+ _actionMappings = new HashMap();
+ StrutsFactory strutsFactory = StrutsFactory.getStrutsFactory();
+ for (Iterator i = delegate.getActionConfigs().entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ String actionPath = '/' + (String) entry.getKey();
+ com.opensymphony.xwork.config.entities.ActionConfig actionConfig =
+ (com.opensymphony.xwork.config.entities.ActionConfig) entry.getValue();
+ _actionMappings.put(actionPath, strutsFactory.createActionMapping(actionConfig, actionPath, this));
+ }
+ }
+ }
+
+ /**
+ * Add Struts ExceptionConfigs (from XWork ExceptionMappingConfigs).
+ */
+ private void initExceptionConfigs() {
+ if (_exceptionConfigs == null) {
+ _exceptionConfigs = new HashMap();
+ StrutsFactory strutsFactory = StrutsFactory.getStrutsFactory();
+ for (Iterator i = delegate.getGlobalExceptionMappingConfigs().iterator(); i.hasNext();) {
+ ExceptionMappingConfig config = (ExceptionMappingConfig) i.next();
+ _exceptionConfigs.put(config.getExceptionClassName(), strutsFactory.createExceptionConfig(config));
+ }
+ }
+ }
+
+ /**
+ * Add Struts ActionForwards (from XWork ResultConfigs).
+ */
+ private void initActionForwards() {
+ if (_actionForwards == null) {
+ _actionForwards = new HashMap();
+ StrutsFactory strutsFactory = StrutsFactory.getStrutsFactory();
+ for (Iterator i = delegate.getGlobalResultConfigs().entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ String name = (String) entry.getKey();
+ ResultConfig config = (ResultConfig) entry.getValue();
+ _actionForwards.put(name, strutsFactory.createActionForward(config));
+ }
+ }
+ }
+
+ public String getPrefix() {
+ return delegate.getNamespace();
+ }
+
+ public void setPrefix(String prefix) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public boolean getConfigured() {
+ return true;
+ }
+
+ public ControllerConfig getControllerConfig() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setControllerConfig(ControllerConfig cc) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getActionFormBeanClass() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setActionFormBeanClass(String actionFormBeanClass) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getActionMappingClass() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setActionMappingClass(String actionMappingClass) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addActionConfig(ActionConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addDataSourceConfig(DataSourceConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addExceptionConfig(ExceptionConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addFormBeanConfig(FormBeanConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public String getActionForwardClass() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void setActionForwardClass(String actionForwardClass) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addForwardConfig(ForwardConfig config) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void addMessageResourcesConfig(MessageResourcesConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void addPlugInConfig(PlugInConfig plugInConfig) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public ActionConfig findActionConfig(String path) {
+ initActionMappings();
+ return (ActionConfig) _actionMappings.get(path);
+ }
+
+ public ActionConfig[] findActionConfigs() {
+ initActionMappings();
+ return (ActionConfig[]) _actionMappings.values().toArray(new ActionConfig[_actionMappings.size()]);
+ }
+
+ public DataSourceConfig findDataSourceConfig(String key) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public DataSourceConfig[] findDataSourceConfigs() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public ExceptionConfig findExceptionConfig(String type) {
+ initExceptionConfigs();
+ return (ExceptionConfig) _exceptionConfigs.get(type);
+ }
+
+ public ExceptionConfig[] findExceptionConfigs() {
+ initExceptionConfigs();
+ return (ExceptionConfig[]) _exceptionConfigs.values().toArray(new ExceptionConfig[_exceptionConfigs.size()]);
+ }
+
+ public FormBeanConfig findFormBeanConfig(String name) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public FormBeanConfig[] findFormBeanConfigs() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public ForwardConfig findForwardConfig(String name) {
+ initActionForwards();
+ return (ForwardConfig) _actionForwards.get(name);
+ }
+
+ public ForwardConfig[] findForwardConfigs() {
+ initActionForwards();
+ return (ForwardConfig[]) _actionForwards.values().toArray(new ForwardConfig[_actionForwards.size()]);
+ }
+
+ public MessageResourcesConfig findMessageResourcesConfig(String key) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public MessageResourcesConfig[] findMessageResourcesConfigs() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public PlugInConfig[] findPlugInConfigs() {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ public void freeze() {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeActionConfig(ActionConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeExceptionConfig(ExceptionConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeDataSourceConfig(DataSourceConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeFormBeanConfig(FormBeanConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeForwardConfig(ForwardConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+
+ public void removeMessageResourcesConfig(MessageResourcesConfig config) {
+ throw new UnsupportedOperationException("Not implemented - immutable");
+ }
+}
diff --git a/struts-sandbox/tag-doc/build.xml b/struts-sandbox/tag-doc/build.xml
new file mode 100644
index 0000000..c6e89c9
--- /dev/null
+++ b/struts-sandbox/tag-doc/build.xml
@@ -0,0 +1,86 @@
+<project name="TaglibDoc" default="compile" basedir=".">
+
+ <!-- Load local and user build preferences -->
+ <property file="build.properties"/>
+ <property file="../../build.properties"/>
+ <property file="../../../build.properties"/>
+ <property file="${user.home}/build.properties"/>
+
+ <property name="src.dir" value="src"/>
+ <property name="classes.dir" value="classes"/>
+ <property name="dist.dir" value="dist"/>
+ <property name="dist.jar" value="${dist.dir}/taglib-docs.jar"/>
+ <property name="java.dir" value="${src.dir}/java"/>
+ <property name="resources.dir" value="${src.dir}/resources"/>
+ <property name="target.dir" value="target"/>
+ <property name="taglibdoc.dir" value="${target.dir}/taglibdoc"/>
+ <property name="taglibreport.dir" value="${target.dir}/taglibreport"/>
+
+ <!-- This is the doc directoy relative to the jakarta-struts directory from here -->
+ <property name="struts.doc.dir" value="../../doc"/>
+ <property name="xml.dir" value="${struts.doc.dir}/userGuide"/>
+
+ <!-- Compilation Classpath -->
+ <path id="compile.classpath">
+ <pathelement location="${classes.dir}"/>
+ <pathelement location="${ant.jar}"/>
+ </path>
+
+ <target name="init">
+ <mkdir dir="${classes.dir}"/>
+ <mkdir dir="${dist.dir}"/>
+ </target>
+
+ <target name="compile" depends="init">
+ <javac srcdir="${java.dir}"
+ destdir="${classes.dir}" >
+ <classpath refid="compile.classpath"/>
+ </javac>
+ </target>
+
+ <target name="dist" depends="compile">
+ <copy todir="${classes.dir}/resources">
+ <fileset dir="${resources.dir}"/>
+ </copy>
+ <jar jarfile="${dist.jar}"
+ basedir="${classes.dir}"
+ includes="**"
+ />
+ </target>
+
+ <target name="taglibdoc" depends="dist">
+ <taskdef name="taglibdoc"
+ classname="org.apache.struts.taskdefs.TaglibDoc">
+ <classpath path="${dist.jar}"/>
+ </taskdef>
+
+ <taglibdoc destdir="${taglibdoc.dir}">
+ <fileset dir="${xml.dir}">
+ <include name="struts-*.xml"/>
+ </fileset>
+ </taglibdoc>
+ </target>
+
+ <target name="taglibreport" depends="dist">
+ <taskdef name="taglibreport"
+ classname="org.apache.struts.taskdefs.TaglibReport">
+ <classpath path="${dist.jar}"/>
+ </taskdef>
+
+ <taglibreport destdir="${taglibreport.dir}">
+ <fileset dir="${xml.dir}">
+ <include name="struts-*.xml"/>
+ </fileset>
+ </taglibreport>
+ </target>
+
+ <target name="clean">
+ <delete dir="${classes.dir}"/>
+ <delete dir="${dist.dir}"/>
+ <delete dir="${taglibdoc.dir}"/>
+ <delete dir="${taglibreport.dir}"/>
+ </target>
+
+ <target name="generate-reports" depends="taglibdoc, taglibreport"/>
+
+</project>
diff --git a/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/EnhMatchingTask.java b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/EnhMatchingTask.java
new file mode 100644
index 0000000..69cc1a4
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/EnhMatchingTask.java
@@ -0,0 +1,87 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.taskdefs;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.taskdefs.MatchingTask;
+import org.apache.tools.ant.types.FileSet;
+
+/**
+ * ENHanced-MatchingTask - enhances the MatchingTask by allowing
+ * the subclasses to act as a FileSet container as well as allowing
+ * the implicit FileSet.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public abstract class EnhMatchingTask extends MatchingTask {
+ /** Base directory for implicit FileSet */
+ protected File dir;
+ /** List of embeded filesets */
+ protected List filesets = new ArrayList();
+
+ /**
+ * Set the base directory for the implicit FileSet
+ * @param base directory for implicit FileSet
+ */
+ public void setDir(File dir) {
+ this.dir = dir;
+ }
+ /**
+ * Adds an embeded FileSet for this task.
+ * @param the FileSet to add
+ */
+ public void addFileset(FileSet fileset) {
+ filesets.add(fileset);
+ }
+
+ /**
+ * Returns the combined list of Files, from both the
+ * implicit and embeded FileSets.
+ * @return list of File objects
+ */
+ protected List getFiles() {
+ List files = new ArrayList();
+ if (dir != null) {
+ fileset.setDir(dir);
+ files.addAll(getFiles(fileset));
+ }
+ Iterator iter = filesets.iterator();
+ while (iter.hasNext()) {
+ files.addAll(getFiles((FileSet) iter.next()));
+ }
+ return files;
+ }
+ private List getFiles(FileSet fs) {
+ List files = new ArrayList();
+ DirectoryScanner ds = fs.getDirectoryScanner(fs.getProject());
+ File dir = ds.getBasedir();
+ String[] filenames = ds.getIncludedFiles();
+ for (int i = 0; i < filenames.length; i++) {
+ File file = new File(dir, filenames[i]);
+ files.add(file);
+ }
+ return files;
+ }
+}
\ No newline at end of file
diff --git a/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/TaglibDoc.java b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/TaglibDoc.java
new file mode 100644
index 0000000..99077f1
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/TaglibDoc.java
@@ -0,0 +1,240 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.taskdefs;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tools.ant.BuildException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Given a list of files compatible with the Tag-Library
+ * Descriptor (TLD) format, generates a JavaDoc like
+ * documentation for each Tag-Library.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TaglibDoc extends EnhMatchingTask {
+ private File destdir;
+ /**
+ * Sets the destination directory for the generated documents.
+ * @param destdir The destination directory
+ */
+ public void setDestdir(File destdir) {
+ this.destdir = destdir;
+ }
+ /**
+ * Called by the Ant runtime. Needs to have the mandatory attribute
+ * 'destdir' set before calling this.
+ */
+ public void execute() throws BuildException {
+ validate();
+ handleFiles(getFiles());
+ }
+ private void validate() throws BuildException {
+ if (destdir == null) {
+ throw new BuildException("Need to specify the 'destdir' attribute");
+ }
+ if (!destdir.exists() || !destdir.isDirectory()) {
+ if (!destdir.mkdirs()) {
+ throw new BuildException("Could not create the specified destdir");
+ }
+ }
+ }
+
+ /**
+ * Creates the following set of documents:<BR/>
+ * <PRE>
+ * DestDir
+ * |- index.html (the frames based index page)
+ * |- overview-frame.html (list of all tag-libraries)
+ * |- all-tags.html (list of all tags)
+ * |- XXX (one directory per tag library)
+ * | |- taglib-frame.html (list of all tags in this library)
+ * | |- taglib-summary.html (summary of this library)
+ * | |- YYY.html (one file per Tag)
+ * | |- ...
+ * |- ...
+ * </PRE>
+ * @param files input files in TLD format.
+ */
+ public void handleFiles(List files) {
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.newDocument();
+ Element overviewRoot =
+ Util.addChildElement(doc, "overview-frame", null);
+ doc = db.newDocument();
+ Element allTagsRoot = Util.addChildElement(doc, "all-tags", null);
+
+ Iterator iter = files.iterator();
+ while (iter.hasNext()) {
+ File file = (File) iter.next();
+ if (!file.exists() || !file.canRead()) {
+ continue;
+ }
+ Document xmlDoc = handleFile(file);
+ if (xmlDoc != null) {
+ String shortname =
+ Util.getElementValue(
+ xmlDoc.getDocumentElement(),
+ "body/taglib/shortname");
+ Util.addChildElement(overviewRoot, "shortname", shortname);
+
+ List tags =
+ Util.getElements(
+ xmlDoc.getDocumentElement(),
+ "body/taglib/tag");
+ Iterator tagIter = tags.iterator();
+ while (tagIter.hasNext()) {
+ Element tag = (Element) tagIter.next();
+ String tagname = Util.getElementValue(tag, "name");
+ tag = Util.addChildElement(allTagsRoot, "tag", null);
+ Util.addChildElement(tag, "name", tagname);
+ Util.addChildElement(tag, "taglib", shortname);
+ }
+ }
+ }
+
+ Source xml = new DOMSource(overviewRoot);
+ Source xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibdoc/index.xsl"));
+ Result out = new StreamResult(new File(destdir, "index.html"));
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+
+ xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibdoc/overview-frame.xsl"));
+ out = new StreamResult(new File(destdir, "overview-frame.html"));
+ t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+
+ xml = new DOMSource(allTagsRoot);
+ xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibdoc/all-tags.xsl"));
+ out = new StreamResult(new File(destdir, "all-tags.html"));
+ t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+
+ Util.copyFile(
+ "/resources/taglibdoc/stylesheet.css",
+ new File(destdir, "stylesheet.css"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ private Document handleFile(File file) {
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(file);
+ String shortname =
+ Util.getElementValue(
+ doc.getDocumentElement(),
+ "body/taglib/shortname");
+
+ File dir = new File(destdir, shortname);
+ dir.mkdir();
+
+ File taglibFrameHtml = new File(dir, "taglib-frame.html");
+ Source xml = new StreamSource(file);
+ Source xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibdoc/taglib-frame.xsl"));
+ Result out = new StreamResult(taglibFrameHtml);
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+
+ File taglibSummaryHtml = new File(dir, "taglib-summary.html");
+ xml = new StreamSource(file);
+ xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibdoc/taglib-summary.xsl"));
+ out = new StreamResult(taglibSummaryHtml);
+ t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+
+ List tags =
+ Util.getElements(doc.getDocumentElement(), "body/taglib/tag");
+ Iterator iter = tags.iterator();
+ xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibdoc/tag-frame.xsl"));
+ t = tf.newTransformer(xsl);
+ while (iter.hasNext()) {
+ Element tag = (Element) iter.next();
+ Util.addChildElement(tag, "taglib", shortname);
+ String tagname = Util.getElementValue(tag, "name");
+ File tagHtml = new File(dir, tagname + ".html");
+ xml = new DOMSource(tag);
+ out = new StreamResult(tagHtml);
+ t.transform(xml, out);
+ }
+
+ return doc;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * MAIN METHOD
+ */
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ System.out.println(
+ "Usage: java " + TaglibDoc.class.getName() + " <file list>");
+ System.exit(0);
+ }
+
+ File[] files = new File[args.length];
+ for (int i = 0; i < files.length; i++)
+ files[i] = new File(args[i]);
+ TaglibDoc td = new TaglibDoc();
+ td.handleFiles(Arrays.asList(files));
+
+ }
+}
diff --git a/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/TaglibReport.java b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/TaglibReport.java
new file mode 100644
index 0000000..d723506
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/TaglibReport.java
@@ -0,0 +1,209 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.taskdefs;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tools.ant.BuildException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Given a list of files compatible with the Tag-Library
+ * Descriptor (TLD) format, creates a matrix of Tags Vs
+ * Attributes for each Tag-Library.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TaglibReport extends EnhMatchingTask {
+ private File destdir;
+ /**
+ * Sets the destination directory for the generated documents.
+ * @param destdir The destination directory
+ */
+ public void setDestdir(File destdir) {
+ this.destdir = destdir;
+ }
+ /**
+ * Called by the Ant runtime. Needs to have the mandatory attribute
+ * 'destdir' set before calling this.
+ */
+ public void execute() throws BuildException {
+ validate();
+ handleFiles(getFiles());
+ }
+ private void validate() throws BuildException {
+ if (destdir == null) {
+ throw new BuildException("Need to specify the 'destdir' attribute");
+ }
+ if (!destdir.exists() || !destdir.isDirectory()) {
+ if (!destdir.mkdirs()) {
+ throw new BuildException("Could not create the specified destdir");
+ }
+ }
+ }
+
+ /**
+ * Creates the following set of documents:<BR/>
+ * <PRE>
+ * DestDir
+ * |- index.html (the frames based index page)
+ * |- overview-frame.html (menu of all tag-libraries)
+ * |- XXX-report.html (one file per tag-library)
+ * |- ...
+ * </PRE>
+ * @param files input files in TLD format.
+ */
+ public void handleFiles(List files) {
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.newDocument();
+ Element overviewRoot =
+ Util.addChildElement(doc, "overview-frame", null);
+
+ Iterator iter = files.iterator();
+ while (iter.hasNext()) {
+ File file = (File) iter.next();
+ if (!file.exists() || !file.canRead()) {
+ continue;
+ }
+ Document xmlDoc = handleFile(file);
+ if (xmlDoc != null) {
+ String shortname =
+ Util.getElementValue(
+ xmlDoc.getDocumentElement(),
+ "body/taglib/shortname");
+ Util.addChildElement(overviewRoot, "shortname", shortname);
+
+ File reportHtml =
+ new File(destdir, shortname + "-report.html");
+ Source xml = new DOMSource(xmlDoc);
+ Source xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibreport/taglib-report.xsl"));
+ Result out = new StreamResult(reportHtml);
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+ }
+ }
+
+ Source xml = new DOMSource(overviewRoot);
+ Source xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibreport/index.xsl"));
+ Result out = new StreamResult(new File(destdir, "index.html"));
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+
+ xsl =
+ new StreamSource(
+ this.getClass().getResourceAsStream(
+ "/resources/taglibreport/overview-frame.xsl"));
+ out = new StreamResult(new File(destdir, "overview-frame.html"));
+ t = tf.newTransformer(xsl);
+ t.transform(xml, out);
+
+ Util.copyFile(
+ "/resources/taglibreport/stylesheet.css",
+ new File(destdir, "stylesheet.css"));
+ Util.copyFile(
+ "/resources/taglibreport/xbPositionableElement.js",
+ new File(destdir, "xbPositionableElement.js"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ private Document handleFile(File file) {
+ try {
+ Set attrSet = new TreeSet();
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(file);
+
+ List tags =
+ Util.getElements(doc.getDocumentElement(), "body/taglib/tag");
+ Iterator iter = tags.iterator();
+ while (iter.hasNext()) {
+ Element tag = (Element) iter.next();
+ List attrList = Util.getElements(tag, "attribute");
+ Iterator attrIter = attrList.iterator();
+ while (attrIter.hasNext()) {
+ Element attribute = (Element) attrIter.next();
+ String name = Util.getElementValue(attribute, "name");
+ attrSet.add(name);
+ }
+ }
+
+ Element attributes =
+ Util.addChildElement(
+ doc.getDocumentElement(),
+ "attributes",
+ null);
+ iter = attrSet.iterator();
+ while (iter.hasNext()) {
+ String name = (String) iter.next();
+ Util.addChildElement(attributes, "attribute", name);
+ }
+
+ return doc;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * MAIN METHOD
+ */
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ System.out.println(
+ "Usage: java " + TaglibReport.class.getName() + " <file list>");
+ System.exit(0);
+ }
+
+ File[] files = new File[args.length];
+ for (int i = 0; i < files.length; i++)
+ files[i] = new File(args[i]);
+ TaglibDoc td = new TaglibDoc();
+ td.handleFiles(Arrays.asList(files));
+
+ }
+}
diff --git a/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/Util.java b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/Util.java
new file mode 100644
index 0000000..eb96c24
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/java/org/apache/struts/taskdefs/Util.java
@@ -0,0 +1,167 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.taskdefs;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * General purpose utility class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class Util {
+ /**
+ * Returns the list of named descendents. Allows the user
+ * to specify '/' separated path to the child element. e.g.
+ * 'a/b/c'. Note, that if 'a' has multiple child elements
+ * named 'b', the method will go to the first 'b' element,
+ * and return all child elements named 'c'. Returns an
+ * empty List if the path does not return any elements.
+ *
+ * @param elem The parent/context element
+ * @param path '/' separated path
+ * @return List of elements as per the path.
+ */
+ public static List getElements(Element elem, String path) {
+ List list = new ArrayList();
+ if (elem == null)
+ return list;
+
+ int ndx = path.indexOf("/");
+ if (ndx != -1) {
+ Element child = getElement(elem, path.substring(0, ndx));
+ return getElements(child, path.substring(ndx + 1));
+ }
+ NodeList nl = elem.getChildNodes();
+ for (int i = 0, len = nl.getLength(); i < len; i++) {
+ Node node = nl.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE
+ && node.getNodeName().equals(path)) {
+ list.add(node);
+ }
+ }
+ return list;
+ }
+ /**
+ * Returns the named descendent. Allows the user
+ * to specify '/' separated path to the child element. e.g.
+ * 'a/b/c'. Note, that in case of multiple children with the
+ * same name, the first child is returned. Returns a null, if
+ * the path does not map to any element.
+ *
+ * @param elem The parent/context element
+ * @param path '/' separated path
+ * @return Named element as per the path.
+ */
+ public static Element getElement(Element elem, String path) {
+ List elems = getElements(elem, path);
+ if (elems.size() == 0)
+ return null;
+ else
+ return (Element) elems.get(0);
+ }
+ /**
+ * Returns the text value of the named descendent. Allows the user
+ * to specify '/' separated path to the child element. e.g.
+ * 'a/b/c'. Note, that in case of multiple children with the
+ * same name, the first child is considered. The text value
+ * is determined by concatenating all the text children. Returns
+ * an empty String if node is not found.
+ *
+ * @param elem The parent/context element
+ * @param path '/' separated path
+ * @return Text value of the name descendent.
+ */
+ public static String getElementValue(Element elem, String path) {
+ Element child = getElement(elem, path);
+ if (child == null)
+ return "";
+
+ String ret = "";
+ NodeList nl = child.getChildNodes();
+ for (int i = 0, len = nl.getLength(); i < len; i++) {
+ Node node = nl.item(i);
+ if (node.getNodeType() == Node.TEXT_NODE)
+ ret += node.getNodeValue();
+ }
+ return ret;
+ }
+ /**
+ * Adds a Child element to the parent node. If the 'value' is
+ * not null, a Text node with the same value is appended to the
+ * Child.
+ * @param parent The parent node
+ * @param tag The child element name
+ * @param value Value of text node appended to the Child
+ * @return the newly added Child node.
+ */
+ public static Element addChildElement(
+ Node parent,
+ String tag,
+ String value) {
+ Document doc =
+ (parent.getNodeType() == Node.DOCUMENT_NODE)
+ ? (Document) parent
+ : parent.getOwnerDocument();
+ Element child = doc.createElement(tag);
+ if (value != null)
+ child.appendChild(doc.createTextNode(value));
+ parent.appendChild(child);
+ return child;
+ }
+
+ /**
+ * Copies a given resource from classpath to the destination file.
+ * Uses Util.class.getResourceAsStream(resPath) internally.
+ * @param resPath Path to the resource
+ * @param dstFile Destination file
+ * @return true, if the file is copied successfully.
+ */
+ public static boolean copyFile(String resPath, File dstFile) {
+ try {
+ BufferedInputStream bis =
+ new BufferedInputStream(
+ Util.class.getResourceAsStream(resPath));
+ FileOutputStream fos = new FileOutputStream(dstFile);
+ int offset = 0, len = 0;
+ byte[] buffer = new byte[2 * 1024];
+ while ((len = bis.read(buffer, 0, buffer.length)) != -1) {
+ fos.write(buffer, 0, len);
+ offset += len;
+ }
+ bis.close();
+ fos.flush();
+ fos.close();
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/struts-sandbox/tag-doc/src/resources/taglibdoc/all-tags.xsl b/struts-sandbox/tag-doc/src/resources/taglibdoc/all-tags.xsl
new file mode 100644
index 0000000..cd214d7
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibdoc/all-tags.xsl
@@ -0,0 +1,43 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style" />
+</HEAD>
+<BODY>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP="true">
+ <DIV CLASS="FrameHeading">
+ All Tags
+ </DIV>
+ <BR/>
+
+<xsl:for-each select="//tag">
+<xsl:sort select="name"/>
+ <xsl:element name="A">
+ <xsl:attribute name="TARGET">tagFrame</xsl:attribute>
+ <xsl:attribute name="HREF"><xsl:value-of select="taglib"/>/<xsl:value-of select="name"/>.html</xsl:attribute>
+ <xsl:attribute name="CLASS">FrameItem</xsl:attribute>
+ <xsl:value-of select="name" />
+ </xsl:element>
+ <BR/>
+</xsl:for-each>
+
+</TD>
+</TR>
+</TABLE>
+
+
+</BODY>
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibdoc/index.xsl b/struts-sandbox/tag-doc/src/resources/taglibdoc/index.xsl
new file mode 100644
index 0000000..716b5a4
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibdoc/index.xsl
@@ -0,0 +1,35 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <TITLE>Taglib Documentation</TITLE>
+</HEAD>
+<FRAMESET cols="20%,80%">
+ <FRAMESET rows="30%,70%">
+ <FRAME src="overview-frame.html" name="taglibListFrame"/>
+ <FRAME src="all-tags.html" name="taglibFrame"/>
+ </FRAMESET>
+ <FRAME src="" name="tagFrame"/>
+</FRAMESET>
+
+
+<NOFRAMES>
+ <H2>Frame Alert</H2>
+ <P/>
+ This document is designed to be viewed using the frames feature.
+ If you see this message, you are using a non-frame-capable web client.
+ <BR/>
+ Link to <A HREF="overview-frame.html">Non-frame version.</A>
+</NOFRAMES>
+
+
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibdoc/overview-frame.xsl b/struts-sandbox/tag-doc/src/resources/taglibdoc/overview-frame.xsl
new file mode 100644
index 0000000..da17e78
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibdoc/overview-frame.xsl
@@ -0,0 +1,47 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <TITLE>Taglib Documentation</TITLE>
+ <LINK REL="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style" />
+</HEAD>
+<BODY>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP="true">
+ <DIV>
+ <SPAN CLASS="FrameHeading">
+ TagLibs
+ </SPAN>
+  
+ (<A TARGET="taglibFrame" HREF="all-tags.html" CLASS="FrameItem">All Tags</A>)
+ </DIV>
+ <BR/>
+
+<xsl:for-each select="//shortname">
+<xsl:sort select="."/>
+ <xsl:element name="A">
+ <xsl:attribute name="TARGET">taglibFrame</xsl:attribute>
+ <xsl:attribute name="HREF"><xsl:value-of select="." />/taglib-frame.html</xsl:attribute>
+ <xsl:attribute name="CLASS">FrameItem</xsl:attribute>
+ <xsl:value-of select="." />
+ </xsl:element>
+ <BR/>
+</xsl:for-each>
+
+</TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibdoc/stylesheet.css b/struts-sandbox/tag-doc/src/resources/taglibdoc/stylesheet.css
new file mode 100644
index 0000000..b077f5f
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibdoc/stylesheet.css
@@ -0,0 +1,35 @@
+/* Javadoc style sheet */
+
+/* Page background color */
+body { background-color: #FFFFFF }
+
+.FrameHeading {
+ font-weight: bold;
+ font-size: large;
+ text-decoration: none;
+}
+.FrameItem {
+ text-decoration: none;
+}
+.FrameHeading:link, .FrameHeading:visited, .FrameItem:link, .FrameItem:visited {
+ color: blue;
+}
+.FrameHeading:hover, .FrameHeading:active, .FrameItem:hover, .FrameItem:active {
+ color: #CC3333;
+}
+
+.FrameTitle {
+ font-weight: bold;
+ font-size: large;
+ text-decoration: none;
+}
+
+.TableHeadingColor { background: #CCCCFF } /* Dark mauve */
+.TableRowColor { background: #FFFFFF } /* White */
+
+.TableRowTT { background: #FFCC99 } /* Reqd. RTExprValue */
+.TableRowTF { background: #FFCC99 } /* Reqd. !RTExprValue */
+.TableRowFT { background: #FFFFFF } /* !Reqd. RTExprValue */
+.TableRowFF { background: #FFFFFF } /* !Reqd. !RTExprValue */
+
+
diff --git a/struts-sandbox/tag-doc/src/resources/taglibdoc/tag-frame.xsl b/struts-sandbox/tag-doc/src/resources/taglibdoc/tag-frame.xsl
new file mode 100644
index 0000000..d3c4dd4
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibdoc/tag-frame.xsl
@@ -0,0 +1,130 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <LINK REL ="stylesheet" TYPE="text/css" HREF="../stylesheet.css" TITLE="Style" />
+</HEAD>
+<BODY>
+
+<!-- ======== START OF TAG DATA ======== -->
+<A NAME="_top"><!-- --></A>
+
+<SPAN CLASS="FrameTitle">
+ <xsl:value-of select="taglib"/>:<xsl:value-of select="name"/>
+</SPAN>
+    (
+<A HREF="#_description">description</A>
+)
+
+<P/>
+<!-- ========== ATTRIBUTE SUMMARY =========== -->
+<A NAME="attribute_summary"><!-- --></A>
+
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN="2">
+ <SPAN CLASS="FrameHeading">Attribute Summary</SPAN>
+</TD>
+</TR>
+
+<xsl:for-each select="attribute">
+<xsl:sort select="required" order="descending"/>
+<xsl:sort select="name" order="ascending"/>
+<xsl:element name="TR">
+ <xsl:attribute name="CLASS">TableRow<xsl:value-of select="substring(required,1,1)"/>
+ <xsl:value-of select="substring(rtexprvalue,1,1)"/>
+ </xsl:attribute>
+<TD ALIGN="right" VALIGN="top" WIDTH="10%"><FONT SIZE="-1">
+  <xsl:if test="rtexprvalue='true'"><CODE>RTExprValue</CODE></xsl:if>
+</FONT></TD>
+<TD>
+ <xsl:element name="A">
+ <xsl:attribute name="HREF">#<xsl:value-of select="name"/></xsl:attribute>
+ <B><CODE><xsl:value-of select="name"/></CODE></B>
+ </xsl:element>
+<BR/>
+          
+<xsl:value-of select="substring(info,1,80)"/>
+</TD>
+</xsl:element>
+</xsl:for-each>
+
+</TABLE>
+
+<P/>
+
+<!-- ============ ATTRIBUTE DETAIL ========== -->
+<A NAME="attribute_detail"><!-- --></A>
+
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN="1">
+ <SPAN CLASS="FrameHeading">Attribute Detail</SPAN>
+</TD>
+</TR>
+</TABLE>
+
+<xsl:for-each select="attribute">
+<xsl:sort select="required" order="descending"/>
+<xsl:sort select="name" order="ascending"/>
+<xsl:element name="A">
+ <xsl:attribute name="NAME"><xsl:value-of select="name"/></xsl:attribute>
+</xsl:element>
+<H3><xsl:value-of select="name"/></H3>
+<xsl:copy-of select="info"/>
+
+<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0">
+<TR>
+<TD><B>Required:</B>    </TD>
+<TD><xsl:value-of select="required"/></TD>
+</TR><TR>
+<TD><B>RTExprValue:</B>    </TD>
+<TD><xsl:value-of select="rtexprvalue"/></TD>
+</TR>
+</TABLE>
+<HR/>
+</xsl:for-each>
+
+<P/>
+<P/>
+
+<!-- ============ DESCRIPTION ========== -->
+<A NAME="_description"><!-- --></A>
+
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN="1">
+ <SPAN CLASS="FrameHeading">Description</SPAN>
+</TD>
+</TR>
+</TABLE>
+<P/>
+
+<xsl:value-of select="summary" />
+<P/>
+<xsl:copy-of select="info" />
+<P/>
+<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0">
+<TR>
+<TD><B>Tag Class:</B>    </TD>
+<TD><xsl:value-of select="tagclass"/></TD>
+</TR><TR>
+<TD><B>Tei Class:</B>    </TD>
+<TD><xsl:value-of select="teiclass"/></TD>
+</TR><TR>
+<TD><B>Body Content:</B>    </TD>
+<TD><xsl:value-of select="bodycontent"/></TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibdoc/taglib-frame.xsl b/struts-sandbox/tag-doc/src/resources/taglibdoc/taglib-frame.xsl
new file mode 100644
index 0000000..3233884
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibdoc/taglib-frame.xsl
@@ -0,0 +1,48 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <LINK REL ="stylesheet" TYPE="text/css" HREF="../stylesheet.css" TITLE="Style" />
+</HEAD>
+<BODY>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP="true">
+ <DIV>
+ <xsl:element name="A">
+ <xsl:attribute name="TARGET">tagFrame</xsl:attribute>
+ <xsl:attribute name="HREF">taglib-summary.html</xsl:attribute>
+ <xsl:attribute name="CLASS">FrameHeading</xsl:attribute>
+ <xsl:value-of select="//taglib/shortname" />
+ </xsl:element>
+ </DIV>
+ <BR/>
+
+<xsl:for-each select="//taglib/tag">
+<xsl:sort select="name"/>
+ <xsl:element name="A">
+ <xsl:attribute name="TARGET">tagFrame</xsl:attribute>
+ <xsl:attribute name="HREF"><xsl:value-of select="name" />.html</xsl:attribute>
+ <xsl:attribute name="CLASS">FrameItem</xsl:attribute>
+ <xsl:value-of select="name" />
+ </xsl:element>
+ <BR/>
+</xsl:for-each>
+
+</TD>
+</TR>
+</TABLE>
+
+
+</BODY>
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibdoc/taglib-summary.xsl b/struts-sandbox/tag-doc/src/resources/taglibdoc/taglib-summary.xsl
new file mode 100644
index 0000000..53dc4af
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibdoc/taglib-summary.xsl
@@ -0,0 +1,98 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <LINK REL ="stylesheet" TYPE="text/css" HREF="../stylesheet.css" TITLE="Style" />
+</HEAD>
+<BODY>
+
+<!-- ======== START OF TAG DATA ======== -->
+<A NAME="_top"><!-- --></A>
+
+<SPAN CLASS="FrameTitle">
+ <xsl:value-of select="//taglib/display-name" />
+</SPAN>
+    (
+<A HREF="#_description">description</A>
+)
+
+<P/>
+<!-- ========== TAG SUMMARY =========== -->
+<A NAME="tag_summary"><!-- --></A>
+
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN="2">
+ <SPAN CLASS="FrameHeading">Tag Summary</SPAN>
+</TD>
+</TR>
+
+<xsl:for-each select="//taglib/tag">
+<xsl:sort select="name" order="ascending"/>
+<xsl:element name="TR">
+ <xsl:attribute name="CLASS">TableRow</xsl:attribute>
+<TD VALIGN="top" WIDTH="10%">
+ <xsl:element name="A">
+ <xsl:attribute name="HREF"><xsl:value-of select="name"/>.html</xsl:attribute>
+ <B><CODE><xsl:value-of select="name"/></CODE></B>
+ </xsl:element>
+</TD>
+<TD>
+ <xsl:value-of select="summary"/>
+</TD>
+</xsl:element>
+</xsl:for-each>
+
+</TABLE>
+
+<P/>
+<P/>
+
+<!-- ============ DESCRIPTION ========== -->
+<A NAME="_description"><!-- --></A>
+
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN="1">
+ <SPAN CLASS="FrameHeading">Description</SPAN>
+</TD>
+</TR>
+</TABLE>
+<P/>
+
+<xsl:copy-of select="//taglib/info" />
+<P/>
+<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0">
+<TR>
+<TD><B>TagLib Version:</B>    </TD>
+<TD><xsl:value-of select="//taglib/tlibversion"/></TD>
+</TR><TR>
+<TD><B>JSP Version:</B>    </TD>
+<TD><xsl:value-of select="//taglib/jspversion"/></TD>
+</TR><TR>
+<TD><B>Short Name:</B>    </TD>
+<TD><xsl:value-of select="//taglib/shortname"/></TD>
+</TR><TR>
+<TD><B>URI:</B>    </TD>
+<TD>
+ <xsl:element name="A">
+ <xsl:attribute name="HREF">
+ <xsl:value-of select="//taglib/uri"/>
+ </xsl:attribute>
+ <xsl:value-of select="//taglib/uri"/>
+ </xsl:element>
+</TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibreport/index.xsl b/struts-sandbox/tag-doc/src/resources/taglibreport/index.xsl
new file mode 100644
index 0000000..ff0af2f
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibreport/index.xsl
@@ -0,0 +1,32 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <TITLE>Taglib Documentation</TITLE>
+</HEAD>
+<FRAMESET cols="100,*">
+ <FRAME src="overview-frame.html" name="taglibListFrame"/>
+ <FRAME src="" name="taglibFrame"/>
+</FRAMESET>
+
+
+<NOFRAMES>
+ <H2>Frame Alert</H2>
+ <P/>
+ This document is designed to be viewed using the frames feature.
+ If you see this message, you are using a non-frame-capable web client.
+ <BR/>
+ Link to <A HREF="overview-frame.html">Non-frame version.</A>
+</NOFRAMES>
+
+
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibreport/overview-frame.xsl b/struts-sandbox/tag-doc/src/resources/taglibreport/overview-frame.xsl
new file mode 100644
index 0000000..714997f
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibreport/overview-frame.xsl
@@ -0,0 +1,43 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <TITLE>Taglib Reports</TITLE>
+ <LINK REL="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style" />
+</HEAD>
+<BODY>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP="true">
+ <DIV CLASS="FrameHeading">
+ TagLibs
+ </DIV>
+ <BR/>
+
+<xsl:for-each select="//shortname">
+<xsl:sort select="."/>
+ <xsl:element name="A">
+ <xsl:attribute name="TARGET">taglibFrame</xsl:attribute>
+ <xsl:attribute name="HREF"><xsl:value-of select="." />-report.html</xsl:attribute>
+ <xsl:attribute name="CLASS">FrameItem</xsl:attribute>
+ <xsl:value-of select="." />
+ </xsl:element>
+ <BR/>
+</xsl:for-each>
+
+</TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibreport/stylesheet.css b/struts-sandbox/tag-doc/src/resources/taglibreport/stylesheet.css
new file mode 100644
index 0000000..b077f5f
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibreport/stylesheet.css
@@ -0,0 +1,35 @@
+/* Javadoc style sheet */
+
+/* Page background color */
+body { background-color: #FFFFFF }
+
+.FrameHeading {
+ font-weight: bold;
+ font-size: large;
+ text-decoration: none;
+}
+.FrameItem {
+ text-decoration: none;
+}
+.FrameHeading:link, .FrameHeading:visited, .FrameItem:link, .FrameItem:visited {
+ color: blue;
+}
+.FrameHeading:hover, .FrameHeading:active, .FrameItem:hover, .FrameItem:active {
+ color: #CC3333;
+}
+
+.FrameTitle {
+ font-weight: bold;
+ font-size: large;
+ text-decoration: none;
+}
+
+.TableHeadingColor { background: #CCCCFF } /* Dark mauve */
+.TableRowColor { background: #FFFFFF } /* White */
+
+.TableRowTT { background: #FFCC99 } /* Reqd. RTExprValue */
+.TableRowTF { background: #FFCC99 } /* Reqd. !RTExprValue */
+.TableRowFT { background: #FFFFFF } /* !Reqd. RTExprValue */
+.TableRowFF { background: #FFFFFF } /* !Reqd. !RTExprValue */
+
+
diff --git a/struts-sandbox/tag-doc/src/resources/taglibreport/taglib-report.xsl b/struts-sandbox/tag-doc/src/resources/taglibreport/taglib-report.xsl
new file mode 100644
index 0000000..58e9cb5
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibreport/taglib-report.xsl
@@ -0,0 +1,173 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output
+ method="html"
+ version="4.0"
+ omit-xml-declaration="yes"
+ indent="yes"
+/>
+
+<xsl:template match="*">
+<HTML>
+<HEAD>
+ <LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style" />
+ <STYLE TYPE="text/css">
+ #ATTR_HEADER {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ z-index: 1;
+ }
+ #TAG_HEADER {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ z-index: 2;
+ }
+ #TOP_LEFT {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ z-index: 3;
+ }
+ #DATA_TABLE {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ }
+ </STYLE>
+ <SCRIPT LANGUAGE="JavaScript" SRC="xbPositionableElement.js"/>
+ <SCRIPT LANGUAGE="JavaScript"><!--
+ var s0, s1, s2;
+ if (!document.layers) {
+ s0 = new xbPositionableElement('TOP_LEFT', 'left', 'top', 0, 0);
+ s1 = new xbPositionableElement('ATTR_HEADER', 'none', 'top', 0, 0);
+ s2 = new xbPositionableElement('TAG_HEADER', 'left', 'none', 0, 0);
+ }
+ function init() {
+ if (!document.layers) {
+ s0.start();
+ s1.start();
+ s2.start();
+ }
+ }
+ //--></SCRIPT>
+</HEAD>
+<BODY onLoad="init()">
+
+<!-- Data Table -->
+<DIV ID="DATA_TABLE">
+<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="0">
+<TR CLASS="TableHeadingColor">
+ <TD WIDTH="150" NOWRAP="true">
+ <DIV STYLE="width: 150px;"> </DIV>
+ </TD>
+ <TD WIDTH="75" NOWRAP="true">
+ <DIV> <B>bodyContent</B> </DIV>
+ </TD>
+<xsl:for-each select="//attributes/attribute">
+<xsl:sort select="."/>
+ <TD WIDTH="75" NOWRAP="true">
+ <DIV> <B><xsl:value-of select="."/></B> </DIV>
+ </TD>
+</xsl:for-each>
+</TR>
+<xsl:for-each select="//taglib/tag">
+<xsl:sort select="name"/>
+<TR>
+ <xsl:variable name="curr_tag" select="."/>
+ <TD CLASS="TableHeadingColor" WIDTH="150" NOWRAP="true">
+ <DIV STYLE="width: 150px; overflow: hidden;"> <B><xsl:value-of select="$curr_tag/name"/></B> </DIV>
+ </TD>
+ <TD WIDTH="75" NOWRAP="true">
+  <xsl:value-of select="$curr_tag/bodycontent"/> 
+ </TD>
+ <xsl:for-each select="//attributes/attribute">
+ <xsl:sort select="."/>
+ <xsl:variable name="curr_attr" select="."/>
+ <xsl:element name="TD">
+ <xsl:attribute name="WIDTH">75</xsl:attribute>
+ <xsl:attribute name="NOWRAP">true</xsl:attribute>
+ <xsl:for-each select="$curr_tag/attribute">
+ <xsl:sort select="name"/>
+ <xsl:if test="./name = $curr_attr">
+ <xsl:choose>
+ <xsl:when test="./required = 'true'">
+ <xsl:attribute name="BGCOLOR">#FF9933</xsl:attribute>
+  
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="BGCOLOR">#FFFF66</xsl:attribute>
+  
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="./rtexprvalue = 'true'">
+ RT
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+  
+ </xsl:element>
+ </xsl:for-each>
+</TR>
+</xsl:for-each>
+
+</TABLE>
+</DIV>
+
+<!-- Top Left Blank Cell -->
+<LAYER VISIBILITY="hide"><DIV ID="TOP_LEFT">
+<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="0">
+<TR CLASS="TableHeadingColor">
+ <TD WIDTH="150" NOWRAP="true">
+ <DIV STYLE="width: 150px;"> </DIV>
+ </TD>
+</TR>
+</TABLE>
+</DIV></LAYER>
+
+<!-- Attribute Header Table -->
+<LAYER VISIBILITY="hide"><DIV ID="ATTR_HEADER">
+<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="0">
+<TR CLASS="TableHeadingColor">
+ <TD WIDTH="150" NOWRAP="true">
+ <DIV STYLE="width: 150px;"> </DIV>
+ </TD>
+ <TD WIDTH="75" NOWRAP="true">
+ <DIV> <B>bodyContent</B> </DIV>
+ </TD>
+<xsl:for-each select="//attributes/attribute">
+<xsl:sort select="."/>
+ <TD WIDTH="75" NOWRAP="true">
+ <DIV> <B><xsl:value-of select="."/></B> </DIV>
+ </TD>
+</xsl:for-each>
+</TR>
+</TABLE>
+</DIV></LAYER>
+
+<!-- Tag Header Table -->
+<LAYER VISIBILITY="hide"><DIV ID="TAG_HEADER">
+<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="0">
+<TR CLASS="TableHeadingColor">
+ <TD WIDTH="150" NOWRAP="true">
+ <DIV STYLE="width: 150px;"> </DIV>
+ </TD>
+</TR>
+<xsl:for-each select="//taglib/tag">
+<xsl:sort select="name"/>
+<TR CLASS="TableHeadingColor">
+ <TD WIDTH="150" NOWRAP="true">
+ <DIV STYLE="width: 150px; overflow: hidden;"> <B><xsl:value-of select="./name"/></B> </DIV>
+ </TD>
+</TR>
+</xsl:for-each>
+</TABLE>
+</DIV></LAYER>
+
+
+</BODY>
+</HTML>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/struts-sandbox/tag-doc/src/resources/taglibreport/xbPositionableElement.js b/struts-sandbox/tag-doc/src/resources/taglibreport/xbPositionableElement.js
new file mode 100644
index 0000000..c1f4cb4
--- /dev/null
+++ b/struts-sandbox/tag-doc/src/resources/taglibreport/xbPositionableElement.js
@@ -0,0 +1,239 @@
+/*
+ * xbPositionableElement.js
+ * $Rev$ $Date$
+*/
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * 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 Netscape Cross Browser Positionable Element code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Doron Rosenberg <doron@netscape.com>
+ * Bob Clary <bclary@netscape.com>
+ *
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * xbPositionableElement -
+ * use DHMTL to position an element displaces (offsetX, offsetY)
+ * from a geometric position in the viewport.
+ *
+ */
+
+function xbPositionableElement(id, sideX, sideY, offsetX, offsetY)
+{
+ this.id = id;
+ this.name = 'xbPositionableElement_' + (++xbPositionableElement._name);
+ this.runId = null;
+ this.refreshInterval = 100;
+ this.div = null;
+
+ if (typeof(sideX) != 'string')
+ {
+ sideX = 'left'
+ }
+ else
+ {
+ sideX = sideX.toLowerCase();
+ }
+
+ if (typeof(sideY) != 'string')
+ {
+ sideY = 'top'
+ }
+ else
+ {
+ sideY = sideY.toLowerCase();
+ }
+
+ if (typeof(offsetX) != 'number')
+ {
+ offsetX = 0;
+ }
+
+ if (typeof(offsetY) != 'number')
+ {
+ offsetY = 0;
+ }
+
+ this.sideX = sideX;
+ this.sideY = sideY;
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+
+ window[this.name] = this;
+}
+
+xbPositionableElement._name = -1;
+
+xbPositionableElement.prototype.start = function ()
+{
+ this.stop();
+
+ // since start() should be called after the document has loaded, we can finally assign element
+ if (!this.div)
+ {
+ if (document.getElementById)
+ {
+ this.div = document.getElementById(this.id);
+ this.styleObj = this.div.style;
+ }
+ else if (document.layers)
+ {
+ this.div = document.layers[this.id];
+ this.styleObj = this.div;
+ }
+ else if (document.all)
+ {
+ this.div = document.all[this.id];
+ this.styleObj = this.div.style;
+ }
+
+ this.width = this._getInnerSize("width");
+ }
+
+ this._updatePosition();
+ this.runId = setTimeout(this.name + '.start()', this.refreshInterval);
+};
+
+xbPositionableElement.prototype.stop = function ()
+{
+ if (this.runId)
+ clearTimeout(this.runId);
+
+ this.runId = null;
+};
+
+xbPositionableElement.prototype._getInnerSize = function (propName)
+{
+ var val = 0;
+
+ if (document.layers)
+ {
+ // navigator 4
+ val = this.div.document[propName];
+ }
+ else if (typeof(this.div.style[propName]) == 'number')
+ {
+ // opera
+ // bug in Opera 6 width/offsetWidth. Use clientWidth
+ if (propName == 'width' && typeof(this.div.clientWidth) == 'number')
+ val = this.div.clientWidth;
+ else
+ val = this.styleObj[propName];
+ }
+ else
+ {
+ //mozilla and IE
+ switch (propName)
+ {
+ case 'height':
+ if (typeof(this.div.offsetHeight) == 'number')
+ val = this.div.offsetHeight;
+ if (val == 0)
+ val = this.height;
+ break;
+
+ case 'width':
+ if (typeof(this.div.offsetWidth) == 'number')
+ val = this.div.offsetWidth;
+ if (val == 0)
+ val = this.width;
+ break;
+ }
+ }
+ return val;
+};
+
+xbPositionableElement.prototype._getScrollOffset = function (propName)
+{
+ var rv = 0;
+
+ if (document.body && typeof(document.body.scrollTop) == 'number')
+ {
+ rv = document.body[propName=='top'?'scrollTop':'scrollLeft'];
+ }
+ else if (typeof(window.pageYOffset) == 'number')
+ {
+ rv = window[propName=='top'?'pageYOffset':'pageXOffset'];
+ }
+
+ return rv;
+};
+
+xbPositionableElement.prototype._updatePosition = function ()
+{
+ var windowHeight;
+ var windowWidth;
+ var x = 0;
+ var y = 0;
+
+ if (document.body && typeof(document.body.clientHeight) == 'number')
+ {
+ windowHeight = document.body.clientHeight;
+ windowWidth = document.body.clientWidth;
+ }
+ else if (typeof(window.innerHeight) == 'number')
+ {
+ windowHeight = window.innerHeight - 16;
+ windowWidth = window.innerWidth - 16;
+ }
+
+ // calculate the positions of the view port position
+ switch (this.sideX)
+ {
+ case 'left':
+ x = this._getScrollOffset('left');
+ break;
+
+ case 'center':
+ x = (windowWidth / 2) - (this._getInnerSize('width')/2) + this._getScrollOffset('left');
+ break;
+
+ case 'right':
+ x = windowWidth - this._getInnerSize('width') + this._getScrollOffset('left');
+ break;
+ }
+
+ switch (this.sideY)
+ {
+ case 'top':
+ y = this._getScrollOffset('top');
+ break;
+
+ case 'center':
+ y = (windowHeight / 2) - (this._getInnerSize('height') / 2) + this._getScrollOffset('top');
+ break;
+
+ case 'bottom':
+ y = windowHeight - this._getInnerSize('height') + this._getScrollOffset('top');
+ break;
+ }
+
+ if (typeof(this.styleObj.left) == 'number')
+ {
+ this.styleObj.left = (x + this.offsetX);
+ this.styleObj.top = (y + this.offsetY);
+ }
+ else
+ {
+ this.styleObj.left = (x + this.offsetX) + 'px';
+ this.styleObj.top = (y + this.offsetY) + 'px';
+ }
+};
+
diff --git a/struts-sandbox/tiles-documentation/project.xml b/struts-sandbox/tiles-documentation/project.xml
new file mode 100755
index 0000000..49c4db1
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/project.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+
+<project>
+ <extend>${basedir}/../project.xml</extend>
+ <artifactId>tiles-documentation</artifactId>
+ <name>Tiles documentation web application</name>
+ <package>org.apache.struts.webapp.tiles.*</package>
+
+ <description>Tiles documentation web application</description>
+ <shortDescription>Tiles webapp</shortDescription>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>struts</groupId>
+ <artifactId>struts-tiles</artifactId>
+ <version>1.3.0-dev</version>
+ <properties>
+ <war.bundle>true</war.bundle>
+ </properties>
+ </dependency>
+
+ <dependency>
+ <groupId>struts</groupId>
+ <artifactId>struts-taglib</artifactId>
+ <version>1.3.0-dev</version>
+ <properties>
+ <war.bundle>true</war.bundle>
+ </properties>
+ </dependency>
+
+ </dependencies>
+
+</project>
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/channel/ChannelFactorySet.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/channel/ChannelFactorySet.java
new file mode 100644
index 0000000..1fd2cbd
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/channel/ChannelFactorySet.java
@@ -0,0 +1,381 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.channel;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.tiles.DefinitionsFactoryException;
+import org.apache.struts.tiles.FactoryNotFoundException;
+import org.apache.struts.tiles.xmlDefinition.DefinitionsFactory;
+import org.apache.struts.tiles.xmlDefinition.FactorySet;
+import org.apache.struts.tiles.xmlDefinition.XmlDefinitionsSet;
+import org.apache.struts.tiles.xmlDefinition.XmlParser;
+import org.xml.sax.SAXException;
+
+/**
+ * Component Definitions factory.
+ * This implementation of Component Definitions factory allows i18n
+ * Component definitions factory allowing i18n definition.
+ * A definition is retrieved by its name, and using locale setted in appropriate
+ * session context. Definitions are defined in different files, one for each locale.
+ * A definition file is loaded using common name extended with locale code
+ * (ex : templateDefinitions_fr.xml). If no file is found under this name, use default
+ * file.
+ */
+public class ChannelFactorySet extends FactorySet {
+
+ private static final Log log = LogFactory.getLog(ChannelFactorySet.class);
+
+ /**
+ * Default name.
+ */
+ public static final String DEFAULT_DEFINITIONS_FILE_NAME =
+ "/WEB-INF/templateDefinitions.xml";
+
+ /**
+ * Config file parameter name.
+ */
+ public static final String DEFINITIONS_CONFIG_PARAMETER_NAME =
+ "definitions-config";
+
+ /**
+ * Config file parameter name.
+ */
+ public static final String FACTORY_SELECTOR_KEY =
+ "ChannelFactorySet.factorySelectorKey";
+
+ /**
+ * Default filenames extension.
+ */
+ public static final String FILENAME_EXTENSION = ".xml";
+
+ /**
+ * Default factory.
+ */
+ protected DefinitionsFactory defaultFactory = null;
+
+ /**
+ * Xml parser used.
+ */
+ protected XmlParser xmlParser = null;
+
+ /**
+ * Names of default file containing definition descriptions.
+ */
+ private String filename = null;
+
+ /**
+ * Collection of already loaded definitions set, referenced by their suffix.
+ */
+ private Map loaded = null;
+
+ /**
+ * Parameterless Constructor.
+ * Method initFactory must be called prior to any use of created factory.
+ */
+ public ChannelFactorySet() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ * Init the factory by reading appropriate configuration file.
+ * @throws FactoryNotFoundException Can't find factory configuration file.
+ */
+ public ChannelFactorySet(ServletContext servletContext, Map properties)
+ throws DefinitionsFactoryException {
+
+ initFactory(servletContext, properties);
+ }
+
+ /**
+ * Initialization method.
+ * Init the factory by reading appropriate configuration file.
+ * This method is called exactly once immediately after factory creation in
+ * case of internal creation (by DefinitionUtil).
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property passed to newly created factory. Map can contains
+ * more properties than requested.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ public void initFactory(ServletContext servletContext, Map properties)
+ throws DefinitionsFactoryException {
+
+ // read properties values
+ String proposedFilename =
+ (String) properties.get(DEFINITIONS_CONFIG_PARAMETER_NAME);
+
+ // Compute filenames to use
+ boolean isFileSpecified = true;
+ if (proposedFilename == null) {
+ proposedFilename = DEFAULT_DEFINITIONS_FILE_NAME;
+ isFileSpecified = false;
+ }
+
+ try {
+ initFactory(servletContext, proposedFilename);
+ return;
+
+ } catch (FileNotFoundException ex) {
+ // If a filename is specified, throw appropriate error.
+ if (isFileSpecified) {
+ throw new FactoryNotFoundException(
+ ex.getMessage()
+ + " : Can't find file '"
+ + proposedFilename
+ + "'");
+ }
+ }
+
+ }
+
+ /**
+ * Initialization method.
+ * Init the factory by reading appropriate configuration file.
+ * This method is called exactly once immediately after factory creation in
+ * case of internal creation (by DefinitionUtil).
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param proposedFilename File names, comma separated, to use as base file names.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ protected void initFactory(
+ ServletContext servletContext,
+ String proposedFilename)
+ throws DefinitionsFactoryException, FileNotFoundException {
+
+ filename = proposedFilename;
+ loaded = new HashMap();
+ defaultFactory = createDefaultFactory(servletContext);
+ }
+
+ /**
+ * Get default factory.
+ * @return Default factory
+ */
+ protected DefinitionsFactory getDefaultFactory() {
+ return defaultFactory;
+ }
+
+ /**
+ * Create default factory .
+ * @param servletContext Current servlet context. Used to open file.
+ * @return Created default definition factory.
+ * @throws DefinitionsFactoryException If an error occur while creating factory.
+ * @throws FileNotFoundException if factory can't be loaded from filenames.
+ */
+ protected DefinitionsFactory createDefaultFactory(ServletContext servletContext)
+ throws DefinitionsFactoryException, FileNotFoundException {
+
+ XmlDefinitionsSet rootXmlConfig = parseXmlKeyFile(servletContext, "", null);
+
+ if (rootXmlConfig == null) {
+ throw new FileNotFoundException();
+ }
+
+ rootXmlConfig.resolveInheritances();
+ return new DefinitionsFactory(rootXmlConfig);
+ }
+
+ /**
+ * Extract key that will be used to get the sub factory.
+ * @param name Name of requested definition
+ * @param request Current servlet request.
+ * @param servletContext Current servlet context
+ * @return the key or null if not found.
+ * @roseuid 3AF6F887018A
+ */
+ protected Object getDefinitionsFactoryKey(
+ String name,
+ ServletRequest request,
+ ServletContext servletContext) {
+ Object key = null;
+
+ HttpSession session = ((HttpServletRequest) request).getSession(false);
+ if (session != null) {
+ key = session.getAttribute(FACTORY_SELECTOR_KEY);
+ }
+
+ return key;
+ }
+
+ /**
+ * Create a factory for specified key.
+ * If creation failed, return default factory, and output an error message in
+ * console.
+ * @param key
+ * @return Definition factory for specified key.
+ * @throws DefinitionsFactoryException If an error occur while creating factory.
+ */
+ protected DefinitionsFactory createFactory(
+ Object key,
+ ServletRequest request,
+ ServletContext servletContext)
+ throws DefinitionsFactoryException {
+
+ if (key == null) {
+ return getDefaultFactory();
+ }
+
+ // Already loaded ?
+ DefinitionsFactory factory = (DefinitionsFactory) loaded.get(key);
+ if (factory != null) { // yes, stop loading
+ return factory;
+ }
+
+ // Try to load file associated to key. If fail, stop and return default factory.
+ XmlDefinitionsSet lastXmlFile =
+ parseXmlKeyFile(servletContext, "_" + (String) key, null);
+
+ if (lastXmlFile == null) {
+ log.warn(
+ "No definition factory associated to key '"
+ + key
+ + "'. Use default factory instead.");
+
+ factory = getDefaultFactory();
+ loaded.put(key, factory);
+ return factory;
+ }
+
+ // Parse default file, and add key file.
+ XmlDefinitionsSet rootXmlConfig = parseXmlKeyFile(servletContext, "", null);
+
+ rootXmlConfig.extend(lastXmlFile);
+ rootXmlConfig.resolveInheritances();
+
+ factory = new DefinitionsFactory(rootXmlConfig);
+ loaded.put(key, factory);
+
+ log.info(factory);
+
+ // return last available found !
+ return factory;
+ }
+
+ /**
+ * Parse files associated to postix if they exist.
+ * For each name in filenames, append postfix before file extension,
+ * then try to load the corresponding file.
+ * If file doesn't exist, try next one. Each file description is added to
+ * the XmlDefinitionsSet description.
+ * The XmlDefinitionsSet description is created only if there is a definition file.
+ * Inheritance is not resolved in the returned XmlDefinitionsSet.
+ * If no description file can be opened, and no definiion set is provided, return null.
+ * @param postfix Postfix to add to each description file.
+ * @param xmlDefinitions Definitions set to which definitions will be added. If null, a definitions
+ * set is created on request.
+ * @return XmlDefinitionsSet The definitions set created or passed as parameter.
+ * @throws DefinitionsFactoryException If an error happen during file parsing.
+ */
+ private XmlDefinitionsSet parseXmlKeyFile(
+ ServletContext servletContext,
+ String postfix,
+ XmlDefinitionsSet xmlDefinitions)
+ throws DefinitionsFactoryException {
+ if (postfix != null && postfix.length() == 0)
+ postfix = null;
+
+ String fullName = concatPostfix(filename, postfix);
+ return parseXmlFile(servletContext, fullName, xmlDefinitions);
+ }
+
+ /**
+ * Parse specified xml file and add definition to specified definitions set.
+ * This method is used to load several description files in one instances list.
+ * If filename exist and definition set is null, create a new set. Otherwise, return
+ * passed definition set (can be null).
+ * @param servletContext Current servlet context. Used to open file.
+ * @param filename Name of file to parse.
+ * @param xmlDefinitions Definitions set to which definitions will be added. If null, a definitions
+ * set is created on request.
+ * @return XmlDefinitionsSet The definitions set created or passed as parameter.
+ * @throws DefinitionsFactoryException If an error happen during file parsing.
+ */
+ private XmlDefinitionsSet parseXmlFile(
+ ServletContext servletContext,
+ String filename,
+ XmlDefinitionsSet xmlDefinitions)
+ throws DefinitionsFactoryException {
+
+ try {
+ log.debug("Trying to load '" + filename + "'.");
+
+ InputStream input = servletContext.getResourceAsStream(filename);
+ if (input == null) {
+ return xmlDefinitions;
+ }
+
+ xmlParser = new XmlParser();
+
+ // Check if definition set already exist.
+ if (xmlDefinitions == null) {
+ xmlDefinitions = new XmlDefinitionsSet();
+ }
+
+ xmlParser.parse(input, xmlDefinitions);
+
+ } catch (SAXException ex) {
+ log.debug("Error while parsing file '" + filename + "'.", ex);
+
+ throw new DefinitionsFactoryException(
+ "Error while parsing file '" + filename + "'. " + ex.getMessage(),
+ ex);
+
+ } catch (IOException ex) {
+ throw new DefinitionsFactoryException(
+ "IO Error while parsing file '" + filename + "'. " + ex.getMessage(),
+ ex);
+ }
+
+ return xmlDefinitions;
+ }
+
+ /**
+ * Concat postfix to the name. Take care of existing filename extension.
+ * Transform the given name "name.ext" to have "name" + "postfix" + "ext".
+ * If there is no ext, return "name" + "postfix".
+ */
+ private String concatPostfix(String name, String postfix) {
+ if (postfix == null) {
+ return name;
+ }
+
+ //postfix = "_" + postfix;
+ // Search file name extension.
+ // take care of Unix files starting with .
+ int dotIndex = name.lastIndexOf(".");
+ int lastNameStart = name.lastIndexOf(java.io.File.pathSeparator);
+ if (dotIndex < 1 || dotIndex < lastNameStart)
+ return name + postfix;
+
+ String ext = name.substring(dotIndex);
+ name = name.substring(0, dotIndex);
+ return name + postfix + ext;
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/channel/SelectChannelAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/channel/SelectChannelAction.java
new file mode 100644
index 0000000..08463c1
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/channel/SelectChannelAction.java
@@ -0,0 +1,71 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.channel;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+public final class SelectChannelAction extends Action {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Extract parameters we will need
+ String requested = (String)request.getParameter( "channel" );
+
+ if( requested == null )
+ return (mapping.findForward("failed"));
+
+ // set in session
+ HttpSession session = request.getSession(false);
+ if (session != null)
+ session.setAttribute(ChannelFactorySet.FACTORY_SELECTOR_KEY, requested);
+ System.out.println( "Set channel to '" + requested + "'" );
+ return (mapping.findForward("success"));
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dev1-1/ApplicationResources.properties b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dev1-1/ApplicationResources.properties
new file mode 100644
index 0000000..ce2a51b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dev1-1/ApplicationResources.properties
@@ -0,0 +1,68 @@
+button.cancel=Cancel
+button.confirm=Confirm
+button.reset=Reset
+button.save=Save
+change.message=Your password has expired. Please ask the system administrator to change it.
+change.try=Try Again
+change.title=Password Has Expired
+database.load=Cannot load database from {0}
+error.database.missing=<li>User database is missing, cannot validate logon credentials</li>
+error.fromAddress.format=<li>Invalid format for From Address</li>
+error.fromAddress.required=<li>From Address is required</li>
+error.fullName.required=<li>Full Name is required</li>
+error.host.required=<li>Mail Server is required</li>
+error.noSubscription=<li>No Subscription bean in user session</li>
+error.password.required=<li>Password is required</li>
+error.password2.required=<li>Confirmation password is required</li>
+error.password.match=<li>Password and confirmation password must match</li>
+error.password.mismatch=<li>Invalid username and/or password, please try again</li>
+error.replyToAddress.format=<li>Invalid format for Reply To Address</li>
+error.transaction.token=<li>Cannot submit this form out of order</li>
+error.type.invalid=<li>Server Type must be 'imap' or 'pop3'</li>
+error.type.required=<li>Server Type is required</li>
+error.username.required=<li>Username is required</li>
+error.username.unique=<li>That username is already in use - please select another</li>
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">Validation Error</font></h3>You must correct the following error(s) before proceeding:<ul>
+errors.ioException=I/O exception rendering error messages: {0}
+heading.autoConnect=Auto
+heading.subscriptions=Current Subscriptions
+heading.host=Host Name
+heading.user=User Name
+heading.type=Server Type
+heading.action=Action
+index.heading=MailReader Demonstration Application Options
+index.logon=Log on to the MailReader Demonstration Application
+index.registration=Register with the MailReader Demonstration Application
+index.title=MailReader Demonstration Application (Struts 1.1-dev)
+index.tour=A Walking Tour of the Example Application
+linkSubscription.io=I/O Error: {0}
+linkSubscription.noSubscription=No subscription under attribute {0}
+linkUser.io=I/O Error: {0}
+linkUser.noUser=No user under attribute {0}
+logon.title=MailReader Demonstration Application - Logon
+mainMenu.heading=Main Menu Options for
+mainMenu.logoff=Log off MailReader Demonstration Application
+mainMenu.registration=Edit your user registration profile
+mainMenu.title=MailReader Demonstration Application - Main Menu
+option.imap=IMAP Protocol
+option.pop3=POP3 Protocol
+prompt.autoConnect=Auto Connect:
+prompt.fromAddress=From Address:
+prompt.fullName=Full Name:
+prompt.mailHostname=Mail Server:
+prompt.mailPassword=Mail Password:
+prompt.mailServerType=Server Type:
+prompt.mailUsername=Mail Username:
+prompt.password=Password:
+prompt.password2=(Repeat) Password:
+prompt.replyToAddress=Reply To Address:
+prompt.username=Username:
+registration.addSubscription=Add
+registration.deleteSubscription=Delete
+registration.editSubscription=Edit
+registration.title.create=Register for the MailReader Demostration Application
+registration.title.edit=Edit Registration for the MailReader Demonstration Application
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dev1-1/ApplicationResources_ja.properties b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dev1-1/ApplicationResources_ja.properties
new file mode 100644
index 0000000..354c72d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dev1-1/ApplicationResources_ja.properties
@@ -0,0 +1,68 @@
+button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+button.confirm=\u78ba\u8a8d
+button.reset=\u30ea\u30bb\u30c3\u30c8
+button.save=\u4fdd\u5b58
+change.message=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u6709\u52b9\u671f\u9650\u304c\u904e\u304e\u307e\u3057\u305f\u3002\u30b7\u30b9\u30c6\u30e0\u7ba1\u7406\u8005\u306b\u304a\u554f\u3044\u5408\u308f\u305b\u4e0b\u3055\u3044\u3002
+change.try=\u3082\u3046\u4E00\u5EA6\u8A66\u3057\u3066\u304F\u3060\u3055\u3044
+change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
+database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
+error.database.missing=<li>\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093</li>
+error.fromAddress.format=<li>From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093</li>
+error.fromAddress.required=<li>From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044</li>
+error.fullName.required=<li>\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044</li>
+error.host.required=<li>\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044</li>
+error.noSubscription=<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u4e2d\u306bSubscription bean\u304c\u3042\u308a\u307e\u305b\u3093</li>
+error.password.required=<li>\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044</li>
+error.password2.required=<li>\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044</li>
+error.password.match=<li>\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093</li>
+error.password.mismatch=<li>\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044</li>
+error.replyToAddress.format=<li>\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093</li>
+error.transaction.token=<li>\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093</li>
+error.type.invalid=<li>\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093</li>
+error.type.required=<li>\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044</li>
+error.username.required=<li>\u30e6\u30fc\u30b6\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002</li>
+error.username.unique=<li>\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044</li>
+errors.footer=</ul><hr>
+errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:<ul>
+errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
+heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
+heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
+heading.host=\u30db\u30b9\u30c8\u540d
+heading.user=\u30e6\u30fc\u30b6\u540d
+heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
+heading.action=\u64cd\u4f5c
+index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
+index.logon=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.0-b1)
+index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
+linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
+linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
+linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+logon.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
+mainMenu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+mainMenu.logoff=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
+mainMenu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
+mainMenu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
+option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
+option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
+prompt.autoConnect=\u81ea\u52d5\u63a5\u7d9a:
+prompt.fromAddress=From\u30a2\u30c9\u30ec\u30b9:
+prompt.fullName=\u30d5\u30eb\u30cd\u30fc\u30e0:
+prompt.mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0:
+prompt.mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9:
+prompt.mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7:
+prompt.mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d:
+prompt.password=\u30d1\u30b9\u30ef\u30fc\u30c9:
+prompt.password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528):
+prompt.replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9:
+prompt.username=\u30e6\u30fc\u30b6\u540d:
+registration.addSubscription=\u65b0\u898f\u4f5c\u6210
+registration.deleteSubscription=\u524a\u9664
+registration.editSubscription=\u7de8\u96c6
+registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
+registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
+subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
+subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
+subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/PortalPrefsForm.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/PortalPrefsForm.java
new file mode 100644
index 0000000..5b059a6
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/PortalPrefsForm.java
@@ -0,0 +1,245 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.dynPortal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.struts.action.ActionForm;
+
+
+/**
+ */
+
+public final class PortalPrefsForm extends ActionForm {
+
+ /** Validate value */
+ protected String validate;
+ /** empty list used by reset */
+ protected String[] empty = {};
+ /** list of "remaining" choices */
+ protected String[] remaining = empty;
+ /** list of user columns */
+ protected List columns = new ArrayList();
+ /** list of user columns labels */
+ protected List columnLabels = new ArrayList();
+ /** list of columns selected by user */
+ protected List newCols = new ArrayList();
+
+ /** Choice list */
+ protected List choice;
+ /** Choice list labels */
+ protected List choiceLabels;
+ /** Is initialized ? */
+ protected boolean initialized = false;
+
+
+ /**
+ * Set col
+ */
+ public void setCol( int index, List col )
+ {
+ columns.set( index, col);
+ }
+
+ /**
+ * Add col
+ */
+ public void addCol( List col )
+ {
+ columns.add( col);
+ }
+
+ /**
+ * Get col Labels
+ */
+ public List getColLabels(int index)
+ {
+ return (List)columnLabels.get(index);
+ }
+
+ /**
+ * Set col Labels
+ */
+ public void setColLabels( int index, List col )
+ {
+ columnLabels.set( index, col);
+ }
+
+ /**
+ * Add col Labels
+ */
+ public void addColLabels( List col )
+ {
+ columnLabels.add( col);
+ }
+
+ /**
+ * Get col
+ */
+ public List getCol(int index)
+ {
+ return (List)columns.get(index);
+ }
+
+ /**
+ * Set col Labels
+ */
+ public void setNewCol( int index, String list[] )
+ {
+ // ensure capacity
+ while( index>=newCols.size())newCols.add(null);
+ newCols.set( index, list);
+ }
+
+ /**
+ * Get col
+ */
+ public String[] getNewCol(int index)
+ {
+ if(newCols==null || index>=newCols.size())
+ return null;
+ return (String[])newCols.get(index);
+ }
+
+ /**
+ * Get number of columns
+ */
+ public int getNumCol()
+ {
+ return newCols.size();
+ }
+
+ /**
+ * Set list1
+ */
+ public void setL1( String array[] )
+ {
+ setNewCol(1, array);
+ }
+ /**
+ * Set list1
+ */
+ public String[] getL1()
+ {
+ return getNewCol(1);
+ }
+
+ /**
+ * Set list1
+ */
+ public void setL0( String array[] )
+ {
+ setNewCol(0, array);
+ }
+ /**
+ * Set list1
+ */
+ public String[] getL0()
+ {
+ return getNewCol(0);
+ }
+ /**
+ * Set list1
+ */
+ public void setRemaining( String array[] )
+ {
+ remaining = array;
+ }
+ /**
+ * Set list1
+ */
+ public String[] getRemaining()
+ {
+ return remaining;
+ }
+
+
+ /**
+ * Set list1
+ */
+ public void setChoices( List list )
+ {
+ choice = list;
+ }
+ /**
+ * Set list1
+ */
+ public void setChoiceLabels( List list )
+ {
+ choiceLabels = list;
+ }
+ /**
+ * Set list1
+ */
+ public List getChoices()
+ {
+ return choice;
+ }
+ /**
+ * Set list1
+ */
+ public List getChoiceLabels()
+ {
+ return choiceLabels;
+ }
+
+ /**
+ * Is this form submitted ?
+ */
+ public boolean isSubmitted()
+ {
+ return validate != null;
+ }
+
+ /**
+ * Is this form submitted ?
+ */
+ public void setValidate( String value)
+ {
+ this.validate = value;
+ }
+
+ /**
+ * Reset properties
+ */
+ public void reset()
+ {
+ remaining = empty;
+ validate = null;
+ columns.clear();
+ columnLabels.clear();
+ newCols.clear();
+ }
+ /**
+ * Initialized flag
+ */
+ public boolean isInitialized()
+ {
+ return initialized;
+ }
+ /**
+ * Initialized flag
+ */
+ public void setInitialized( boolean isInitialized)
+ {
+ initialized = isInitialized;
+ }
+}
+
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/PortalSettings.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/PortalSettings.java
new file mode 100644
index 0000000..fde668b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/PortalSettings.java
@@ -0,0 +1,237 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.dynPortal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+ /**
+ * Objects of this class hold portal settings for one user.
+ */
+ public class PortalSettings
+ {
+ /** Number of columms*/
+ protected int numCols;
+ /** List of lists (one per column) */
+ protected List lists = new ArrayList();
+ /** Choices Tiles */
+ protected List choices = new ArrayList();
+ /** Choices Tiles labels */
+ protected List choiceLabels = new ArrayList();
+
+ /**
+ * Get label for specified Tile, identified by its key.
+ */
+ public String getLabel( Object key )
+ {
+ int index = choices.indexOf( key );
+ return (String)choiceLabels.get(index);
+ }
+
+ /**
+ * Get number of columns.
+ */
+ public int getNumCols()
+ {
+ return numCols;
+ }
+ /**
+ * Set number of columns
+ */
+ public void setNumCols( String numCols )
+ {
+ this.numCols = Integer.parseInt(numCols);
+ }
+ /**
+ * Set number of columns
+ */
+ public void setNumCols( int numCols )
+ {
+ this.numCols = numCols;
+ }
+ /**
+ * Get list at specified index
+ */
+ public List getListAt( int index )
+ {
+ return (List)lists.get(index);
+ }
+
+ /**
+ * Get labels for list at specified index.
+ */
+ public List getListLabelAt( int index )
+ {
+ List listLabels = new ArrayList();
+ List list = getListAt(index);
+
+ Iterator i = list.iterator();
+ while(i.hasNext())
+ {
+ Object key = i.next();
+ listLabels.add( getLabel(key) );
+ } // end loop
+ return listLabels;
+ }
+
+ /**
+ * Add a list without checking
+ */
+ public void addList( List list )
+ {
+ lists.add( list);
+ }
+
+ /**
+ * Set list of choices Tiles
+ */
+ public void setChoices( List list)
+ {
+ setChoices(list, list);
+ }
+
+ /**
+ * add list to list of choices Tiles
+ */
+ public void addChoices( List list)
+ {
+ addChoices( list, list);
+ }
+
+ /**
+ * Set list of choices Tiles
+ */
+ public void setChoices( List list, List labels)
+ {
+ // If no labels, use list keys
+ if( labels == null )
+ labels = list;
+ // Check sizes
+ if( list.size() != labels.size() )
+ {// error
+ System.out.println( "Error : list and labels size must be the same." );
+ }
+ this.choices = list;
+ choiceLabels = labels;
+ }
+
+ /**
+ * add list and labels to list of choices Tiles.
+ * If labels is null, use keys list as labels.
+ * @list list of choice keys to add
+ * @labels corresponding labels (list size must be the same as list).
+ */
+ public void addChoices( List list, List labels)
+ {
+ // If no labels, use list keys
+ if( labels == null )
+ labels = list;
+ // Check sizes
+ if(choices== null)
+ {
+ setChoices(list, labels);
+ return;
+ }
+
+ if( list.size() != labels.size() )
+ {// error
+ System.out.println( "Error : list and labels size must be the same." );
+ }
+ choices.addAll(list);
+ choiceLabels.addAll(labels);
+ }
+
+ /**
+ * Get list of choices Tiles
+ */
+ public List getChoices( )
+ {
+ return choices;
+ }
+
+ /**
+ * Set labels for choices Tiles.
+ */
+ public void setChoiceLabels( List list)
+ {
+ this.choiceLabels = list;
+ }
+ /**
+ * add list to list of choices Tiles
+ */
+ public void addChoiceLabels( List list)
+ {
+ if(choiceLabels== null)
+ {
+ setChoiceLabels(list);
+ return;
+ }
+ choiceLabels.addAll(list);
+ }
+ /**
+ * Get list of choices Tiles
+ */
+ public List getChoiceLabels( )
+ {
+ return choiceLabels;
+ }
+
+ /**
+ * Reset list at specified index, and fill it with keys from array.
+ * Keys are added only if they are in the choices list.
+ * Special keys are transformed in appropriate 'definition'.
+ * @index index of the list to add.
+ * @keys array of keys to initialize list.
+ */
+ public void resetListAt( int index, String keys[] )
+ {
+ List list = getListAt(index);
+ list.clear();
+ addListAt(index, keys);
+ }
+ /**
+ * Add keys from array to list at specified index.
+ * Keys are added only if they are in the choices list.
+ * Special keys are transformed in appropriate 'definition'.
+ * @index index of the list to add.
+ * @keys array of keys to add to list.
+ */
+ public void addListAt( int index, String keys[] )
+ {
+ // First, ensure capacity
+ while( index>lists.size()-1 ) lists.add(new ArrayList());
+
+ List list = getListAt(index);;
+ // add keys to list
+ for(int i=0;i<keys.length;i++)
+ {
+ String key = keys[i];
+ if( key.indexOf( '@' )>0 )
+ { // special key
+ }
+ if( choices.contains( key ) )
+ { // ok, add it
+ list.add( key );
+ }
+ } // end loop
+ lists.add( list);
+ }
+
+ }
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/RetrievePortalAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/RetrievePortalAction.java
new file mode 100644
index 0000000..81980d0
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/RetrievePortalAction.java
@@ -0,0 +1,126 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.dynPortal;
+
+import java.util.List;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+
+
+/**
+ * Implementation of <strong>Action</strong> that populates an instance of
+ * <code>SubscriptionForm</code> from the currently specified subscription.
+ *
+ */
+
+public final class RetrievePortalAction extends Action {
+
+ /** Name use to store settings in session context */
+ public static String USER_PORTAL_SETTINGS = "DynamicPortal.USER_PORTAL_SETTINGS";
+ /** Tile parameter name */
+ public static String PARAM_NUMCOLS = "numCols";
+ /** Tile parameter name */
+ public static String PARAM_LIST = "list";
+ /** Tile parameter name */
+ public static String PARAM_LIST_LABELS = "listLabels";
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+ System.out.println("Enter action RetrievePortalAction");
+ // Get current session.
+ HttpSession session = request.getSession();
+
+ // Try to retrieve tile context
+ ComponentContext context = ComponentContext.getContext( request );
+ if( context == null )
+ {
+ throw new ServletException( "This action must be called by a Tile, not directly" );
+ }
+
+ // Get user portal list from user context
+ PortalSettings settings = getSettings( context, session );
+
+ // Set parameters for tiles
+ context.putAttribute( "numCols", Integer.toString(settings.getNumCols()) );
+ for( int i=0; i<settings.getNumCols(); i++ )
+ context.putAttribute( "list"+i, settings.getListAt(i) );
+
+ System.out.println("Exit action RetrievePortalAction");
+ return (mapping.findForward("success"));
+ }
+
+ /**
+ * Retrieve user setting from session.
+ * If settings are not found, initialized them.
+ */
+ public static PortalSettings getSettings( ComponentContext context, HttpSession session )
+ {
+ // Get user portal list from user context
+ PortalSettings settings = (PortalSettings)session.getAttribute( USER_PORTAL_SETTINGS );
+
+ if( settings == null )
+ { // List doesn't exist, create it and initialize it from Tiles parameters
+ settings = new PortalSettings();
+ settings.setNumCols( (String)context.getAttribute( PARAM_NUMCOLS ) );
+ for( int i=0; i<settings.getNumCols(); i++ )
+ {
+ List col = (List)context.getAttribute( ((String)PARAM_LIST+i) );
+ List labels = (List)context.getAttribute( ((String)PARAM_LIST_LABELS+i) );
+ settings.addChoices( col, labels );
+ settings.addList( col );
+ } // end loop
+
+ // Save user settings in session
+ session.setAttribute( USER_PORTAL_SETTINGS, settings);
+ } // end if
+
+ return settings;
+ }
+
+
+}
+
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/SetPortalPrefsAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/SetPortalPrefsAction.java
new file mode 100644
index 0000000..95c5371
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/dynPortal/SetPortalPrefsAction.java
@@ -0,0 +1,113 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.dynPortal;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+
+
+/**
+ * Implementation of <strong>Action</strong> that populates an instance of
+ * <code>SubscriptionForm</code> from the currently specified subscription.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public final class SetPortalPrefsAction extends Action {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception
+ {
+ System.out.println("Enter action SetPortalPrefsAction");
+ HttpSession session = request.getSession();
+ PortalPrefsForm prefsForm = (PortalPrefsForm)form;
+
+ // Try to retrieve tile context
+ ComponentContext context = ComponentContext.getContext( request );
+ if( context == null )
+ {
+ throw new ServletException( "This action must be called by a Tile, not directly" );
+ }
+
+ // Get user portal list from user context
+ PortalSettings settings = RetrievePortalAction.getSettings( context, session );
+
+ if( prefsForm.isSubmitted() )
+ { // read arrays
+ System.out.println("form submitted");
+
+ // Set settings cols according to user choice
+ for( int i=0;i<prefsForm.getNumCol(); i++)
+ {
+ settings.resetListAt( i, prefsForm.getNewCol(i));
+ } // end loop
+
+
+ //settings.resetListAt( 0, prefsForm.getL0());
+ //settings.resetListAt( 1, prefsForm.getL1());
+ prefsForm.reset();
+ return (mapping.findForward("portal"));
+ }
+
+ // Set lists values to be shown
+ for( int i=0;i<settings.getNumCols(); i++ )
+ {
+ prefsForm.addCol(settings.getListAt(i) );
+ prefsForm.addColLabels(settings.getListLabelAt(i) );
+ } // end loop
+
+ prefsForm.setChoices(settings.getChoices() );
+ prefsForm.setChoiceLabels(settings.getChoiceLabels() );
+
+ System.out.println("Exit action SetPortalPrefsAction");
+ return (mapping.findForward("preferences"));
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/Address.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/Address.java
new file mode 100644
index 0000000..7c0e37c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/Address.java
@@ -0,0 +1,140 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.invoice;
+
+/**
+ * An address.
+ */
+public class Address
+{
+
+ /**
+ * Street part 1
+ */
+ private String street1;
+
+ /**
+ * Street part 2
+ */
+ private String street2;
+
+ /**
+ * City
+ */
+ private String city;
+
+ /**
+ * Country
+ */
+ private String country;
+
+ /**
+ * Zip Code
+ */
+ private String zipCode;
+
+ public Address()
+ {
+ }
+
+ /**
+* Access method for the street1 property.
+*
+* @return the current value of the street1 property
+ */
+ public String getStreet1() {
+ return street1;}
+
+ /**
+ * @return void
+* Sets the value of the street1 property.
+*
+* @param aStreet1 the new value of the street1 property
+ */
+ public void setStreet1(String aStreet1) {
+ street1 = aStreet1;}
+
+ /**
+* Access method for the street2 property.
+*
+* @return the current value of the street2 property
+ */
+ public String getStreet2() {
+ return street2;}
+
+ /**
+ * @return void
+* Sets the value of the street2 property.
+*
+* @param aStreet2 the new value of the street2 property
+ */
+ public void setStreet2(String aStreet2) {
+ street2 = aStreet2;}
+
+ /**
+* Access method for the city property.
+*
+* @return the current value of the city property
+ */
+ public String getCity() {
+ return city;}
+
+ /**
+ * @return void
+* Sets the value of the city property.
+*
+* @param aCity the new value of the city property
+ */
+ public void setCity(String aCity) {
+ city = aCity;}
+
+ /**
+* Access method for the country property.
+*
+* @return the current value of the country property
+ */
+ public String getCountry() {
+ return country;}
+
+ /**
+ * @return void
+* Sets the value of the country property.
+*
+* @param aCountry the new value of the country property
+ */
+ public void setCountry(String aCountry) {
+ country = aCountry;}
+
+ /**
+* Access method for the zipCode property.
+*
+* @return the current value of the zipCode property
+ */
+ public String getZipCode() {
+ return zipCode;}
+
+ /**
+ * @return void
+* Sets the value of the zipCode property.
+*
+* @param aZipCode the new value of the zipCode property
+ */
+ public void setZipCode(String aZipCode) {
+ zipCode = aZipCode;}
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/EditInvoiceAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/EditInvoiceAction.java
new file mode 100644
index 0000000..a0f2903
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/EditInvoiceAction.java
@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.webapp.tiles.invoice;
+
+import java.util.Locale;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+
+/**
+ * Implementation of <strong>Action</strong> that populates an instance of
+ * <code>SubscriptionForm</code> from the currently specified subscription.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public final class EditInvoiceAction extends Action {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Extract attributes we will need
+ Locale locale = getLocale(request);
+ HttpSession session = request.getSession();
+
+ //System.out.println( "action perform called" );
+ // Fill in nested classes
+ InvoiceForm invoice = (InvoiceForm)form;
+
+ //RequestUtils.populate( invoice.getBillAddress(), "billAddress.", null, request );
+ //RequestUtils.populate( invoice.getShippingAddress(), "shippingAddress.", null, request );
+ return (mapping.findForward("success"));
+
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/Invoice.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/Invoice.java
new file mode 100644
index 0000000..f47b3ad
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/Invoice.java
@@ -0,0 +1,143 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts.webapp.tiles.invoice;
+
+import org.apache.struts.action.ActionForm;
+
+/**
+ * An invoice.
+ */
+public class Invoice extends ActionForm
+{
+
+ /**
+ * Shipping address
+ */
+ private Address shippingAddress;
+
+ /**
+ * Bill address
+ */
+ private Address billAddress;
+
+ /**
+ * Invoice total amount
+ */
+ private double amount;
+
+ /**
+ * Customer firstname
+ */
+ private String firstname;
+
+ /**
+ * Customer last name
+ */
+ private String lastname;
+
+ public Invoice()
+ {
+ shippingAddress = new Address();
+ billAddress = new Address();
+ }
+
+ /**
+* Access method for the shippingAddress property.
+*
+* @return the current value of the shippingAddress property
+ */
+ public Address getShippingAddress() {
+ return shippingAddress;}
+
+ /**
+ * @return void
+* Sets the value of the shippingAddress property.
+*
+* @param aShippingAddress the new value of the shippingAddress property
+ */
+ public void setShippingAddress(Address aShippingAddress) {
+ shippingAddress = aShippingAddress;}
+
+ /**
+* Access method for the billAddress property.
+*
+* @return the current value of the billAddress property
+ */
+ public Address getBillAddress() {
+ return billAddress;}
+
+ /**
+ * @return void
+* Sets the value of the billAddress property.
+*
+* @param aBillAddress the new value of the billAddress property
+ */
+ public void setBillAddress(Address aBillAddress) {
+ billAddress = aBillAddress;}
+
+ /**
+* Access method for the amount property.
+*
+* @return the current value of the amount property
+ */
+ public double getAmount() {
+ return amount;}
+
+ /**
+ * @return void
+* Sets the value of the amount property.
+*
+* @param aAmount the new value of the amount property
+ */
+ public void setAmount(double aAmount) {
+ amount = aAmount;}
+
+ /**
+* Access method for the firstname property.
+*
+* @return the current value of the firstname property
+ */
+ public String getFirstname() {
+ return firstname;}
+
+ /**
+ * @return void
+* Sets the value of the firstname property.
+*
+* @param aFirstname the new value of the firstname property
+ */
+ public void setFirstname(String aFirstname) {
+ firstname = aFirstname;}
+
+ /**
+* Access method for the lastname property.
+*
+* @return the current value of the lastname property
+ */
+ public String getLastname() {
+ return lastname;}
+
+ /**
+ * @return void
+* Sets the value of the lastname property.
+*
+* @param aLastname the new value of the lastname property
+ */
+ public void setLastname(String aLastname) {
+ lastname = aLastname;}
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/InvoiceForm.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/InvoiceForm.java
new file mode 100644
index 0000000..608c6b3
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/invoice/InvoiceForm.java
@@ -0,0 +1,165 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.invoice;
+
+import org.apache.struts.action.ActionForm;
+
+
+/**
+ */
+
+public final class InvoiceForm extends ActionForm {
+
+ /**
+ * Shipping address
+ */
+ private Address shippingAddress;
+
+ /**
+ * Bill address
+ */
+ private Address billAddress;
+
+ /**
+ * Invoice total amount
+ */
+ private double amount;
+
+ /**
+ * Customer firstname
+ */
+ private String firstname;
+
+ /**
+ * Customer last name
+ */
+ private String lastname;
+
+ public InvoiceForm()
+ {
+ shippingAddress = new Address();
+ billAddress = new Address();
+ }
+
+ /**
+ * Access method for the shippingAddress property.
+ *
+ * @return the current value of the shippingAddress property
+ */
+ public Address getShippingAddress()
+ {
+ return shippingAddress;}
+
+ /**
+ * @return void
+ * Sets the value of the shippingAddress property.
+ *
+ * @param aShippingAddress the new value of the shippingAddress property
+ */
+ public void setShippingAddress(Address aShippingAddress)
+ {
+ shippingAddress = aShippingAddress;
+ }
+
+ /**
+ * Access method for the billAddress property.
+ *
+ * @return the current value of the billAddress property
+ */
+ public Address getBillAddress()
+ {
+ return billAddress;
+ }
+
+ /**
+ * @return void
+ * Sets the value of the billAddress property.
+ *
+ * @param aBillAddress the new value of the billAddress property
+ */
+ public void setBillAddress(Address aBillAddress)
+ {
+ billAddress = aBillAddress;
+ }
+
+ /**
+ * Access method for the amount property.
+ *
+ * @return the current value of the amount property
+ */
+ public double getAmount()
+ {
+ return amount;
+ }
+
+ /**
+ * @return void
+ * Sets the value of the amount property.
+ *
+ * @param aAmount the new value of the amount property
+ */
+ public void setAmount(double aAmount)
+ {
+ amount = aAmount;
+ }
+
+ /**
+ * Access method for the firstname property.
+ *
+ * @return the current value of the firstname property
+ */
+ public String getFirstname()
+ {
+ return firstname;
+ }
+
+ /**
+ * @return void
+ * Sets the value of the firstname property.
+ *
+ * @param aFirstname the new value of the firstname property
+ */
+ public void setFirstname(String aFirstname)
+ {
+ firstname = aFirstname;
+ }
+
+ /**
+ * Access method for the lastname property.
+ *
+ * @return the current value of the lastname property
+ */
+ public String getLastname()
+ {
+ return lastname;
+ }
+
+ /**
+ * @return void
+ * Sets the value of the lastname property.
+ *
+ * @param aLastname the new value of the lastname property
+ */
+ public void setLastname(String aLastname)
+ {
+ lastname = aLastname;
+ }
+
+}
+
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/lang/SelectLocaleAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/lang/SelectLocaleAction.java
new file mode 100644
index 0000000..2400dba
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/lang/SelectLocaleAction.java
@@ -0,0 +1,83 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.lang;
+
+import java.util.Locale;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.taglib.ComponentConstants;
+
+public final class SelectLocaleAction extends Action {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Extract parameters we will need
+ String requested = (String)request.getParameter( "language" );
+
+ if( requested == null )
+ return (mapping.findForward("failed"));
+ if( requested.equalsIgnoreCase( "FR" ) )
+ setLocale( request, Locale.FRANCE );
+ if( requested.equalsIgnoreCase( "UK" ) )
+ setLocale( request, Locale.UK );
+ if( requested.equalsIgnoreCase( "DE" ) )
+ setLocale( request, Locale.GERMAN );
+
+ //System.out.println( "action perform called" );
+ // Fill in nested classes
+ return (mapping.findForward("success"));
+ }
+
+ protected void setLocale( HttpServletRequest request, Locale locale )
+ {
+ HttpSession session = request.getSession(false);
+ if (session != null)
+ session.setAttribute(ComponentConstants.LOCALE_KEY, locale);
+
+ }
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/MenuSettings.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/MenuSettings.java
new file mode 100644
index 0000000..a56e1e9
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/MenuSettings.java
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+ /**
+ * Objects of this class hold menu settings for one user.
+ */
+ public class MenuSettings
+ {
+ /** List of items */
+ protected List items = new ArrayList();
+
+ /**
+ * Get list of items
+ */
+ public List getItems( )
+ {
+ return items;
+ }
+
+ /**
+ * Add an item to the list
+ */
+ public void addItem( Object item )
+ {
+ items.add( item );
+ }
+
+ /**
+ * Add all items to the list.
+ */
+ public void addItems( List list )
+ {
+ items.addAll( list );
+ }
+
+ /**
+ * Reset settings
+ */
+ public void reset()
+ {
+ items.clear();
+ }
+
+ public String toString()
+ {
+ return "items=" + items;
+ }
+ }
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/MenuSettingsForm.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/MenuSettingsForm.java
new file mode 100644
index 0000000..b62637f
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/MenuSettingsForm.java
@@ -0,0 +1,85 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import org.apache.struts.action.ActionForm;
+
+
+/**
+ * Action form used to read data from web page form.
+ */
+public final class MenuSettingsForm extends ActionForm {
+
+ /** Validate value */
+ protected String validate;
+ /** empty list used by reset */
+ protected String[] empty = {};
+ /** list of items selected by user */
+ protected String[] selected;
+
+ /**
+ * Set selected items
+ */
+ public void setSelected( String array[] )
+ {
+ selected = array;
+ }
+
+ /**
+ * Get selected items
+ */
+ public String[] getSelected()
+ {
+ return selected;
+ }
+
+ /**
+ * Get selected items
+ */
+ public String[] getSelectedChoices()
+ {
+ return empty;
+ }
+
+ /**
+ * Is this form submitted ?
+ */
+ public boolean isSubmitted()
+ {
+ return validate != null;
+ }
+
+ /**
+ * Is this form submitted ?
+ */
+ public void setValidate( String value)
+ {
+ this.validate = value;
+ }
+
+ /**
+ * Reset properties
+ */
+ public void reset()
+ {
+ selected = empty;
+ validate = null;
+ }
+}
+
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalCatalog.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalCatalog.java
new file mode 100644
index 0000000..95163d6
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalCatalog.java
@@ -0,0 +1,208 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * A catalog of available tiles for a portal.
+ * Tiles denote a local URL or a Tile definition name.
+ * To check : should be possible to put ComponentDefinition class also.
+ *
+ */
+public class PortalCatalog
+{
+ /** List of available Tiles */
+ protected List tiles = new ArrayList();
+ /** List of Tiles labels */
+ protected List tileLabels = new ArrayList();
+
+ /**
+ * Set list of tiles.
+ * Labels come from tiles names
+ * @param list list of tiles
+ */
+ public void setTiles( List list)
+ {
+ setTiles(list, list);
+ }
+
+ /**
+ * add list to list of available Tiles
+ * Labels come from tiles names
+ * @param list list of tiles
+ */
+ public void addTiles( List list)
+ {
+ addTiles( list, list);
+ }
+
+ /**
+ * Set list of available Tiles.
+ * Previous list is disguarded.
+ * @param list list of tiles
+ * @param labels corresponding labels. List size must be the same as list.
+ * If labels is null, use list of tiles.
+ * @throws ArrayIndexOutOfBoundsException if list and labels aren't the same size.
+ */
+ public void setTiles( List list, List labels)
+ throws ArrayIndexOutOfBoundsException
+ {
+ // If no labels, use list keys
+ if( labels == null )
+ labels = list;
+ // Check sizes
+ if( list.size() != labels.size() )
+ {// error
+ System.out.println( "Error : list and labels size must be the same." );
+ throw new java.lang.ArrayIndexOutOfBoundsException( "List of tiles and list of labels must be of the same size" );
+ }
+ this.tiles = list;
+ tileLabels = labels;
+ }
+
+ /**
+ * add list and labels to list of available Tiles.
+ * If labels is null, use keys list as labels.
+ * @list list of choice keys to add
+ * @param labels corresponding labels. List size must be the same as list.
+ * If labels is null, use list of tiles.
+ * @throws ArrayIndexOutOfBoundsException if list and labels aren't the same size.
+ */
+ public void addTiles( List list, List labels)
+ throws ArrayIndexOutOfBoundsException
+ {
+ // If no labels, use list keys
+ if( labels == null )
+ labels = list;
+ // Check sizes
+ if(tiles== null)
+ {
+ setTiles(list, labels);
+ return;
+ }
+
+ if( list.size() != labels.size() )
+ {// error
+ System.out.println( "Error : list and labels size must be the same." );
+ throw new java.lang.ArrayIndexOutOfBoundsException( "List of tiles and list of labels must be of the same size" );
+ }
+ tiles.addAll(list);
+ tileLabels.addAll(labels);
+ }
+
+ /**
+ * Get list of available Tiles
+ */
+ public List getTiles( )
+ {
+ return tiles;
+ }
+
+ /**
+ * Get list of labels for Tiles
+ */
+ public List getTilesLabels( )
+ {
+ return tileLabels;
+ }
+
+ /**
+ * Get label for specified Tile, identified by its key.
+ * @param key Tile key
+ */
+ public String getTileLabel( Object key )
+ {
+ int index = tiles.indexOf( key );
+ if(index==-1)
+ return null;
+ return (String)tileLabels.get(index);
+ }
+
+ /**
+ * Get list of labels for Tile keys
+ * @param keys List of keys to search for labels.
+ */
+ public List getTileLabels( List Keys )
+ {
+ List listLabels = new ArrayList();
+
+ Iterator i = Keys.iterator();
+ while(i.hasNext())
+ {
+ Object key = i.next();
+ listLabels.add( getTileLabel(key) );
+ } // end loop
+ return listLabels;
+ }
+
+ /**
+ * Get Tiles corresponding to keys.
+ * Keys are the one returned by the setting page. Keys are usually issue
+ * from values returned by getTiles().
+ * If a key isn't recognize, it is disguarded from the returned list.
+ * If a key correspond to a special key, appropriate 'definition' is created.
+ * Returned list contains tiles URL, definition name and definitions suitable
+ * as attribute of <tiles:insert >.
+ *
+ * @keys array of keys to add to list.
+ */
+ public List getTiles( String keys[] )
+ {
+ List list = new ArrayList();
+
+ // add keys to list
+ for(int i=0;i<keys.length;i++)
+ {
+ String key = keys[i];
+ if( key.indexOf( '@' )>0 )
+ { // special key
+ }
+ if( tiles.contains( key ) )
+ { // ok, add it
+ list.add( key );
+ }
+ } // end loop
+ return list;
+ }
+
+ /**
+ * Set labels for tiles Tiles.
+ */
+ protected void setTileLabels( List list)
+ {
+ this.tileLabels = list;
+ }
+ /**
+ * add list to list of tiles Tiles
+ */
+ protected void addTileLabels( List list)
+ {
+ if(tileLabels== null)
+ {
+ setTileLabels(list);
+ return;
+ }
+ tileLabels.addAll(list);
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalSettings.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalSettings.java
new file mode 100644
index 0000000..8f562fa
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalSettings.java
@@ -0,0 +1,100 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+ /**
+ * Objects of this class hold portal settings for one user.
+ */
+ public class PortalSettings
+ {
+ /** Number of columms*/
+ protected int numCols;
+ /** List of lists (one per column) */
+ protected List lists = new ArrayList();
+
+ /**
+ * Get number of columns.
+ */
+ public int getNumCols()
+ {
+ return numCols;
+ }
+ /**
+ * Set number of columns
+ */
+ public void setNumCols( String numCols )
+ {
+ setNumCols( Integer.parseInt(numCols) );
+ }
+ /**
+ * Set number of columns.
+ * Ensure capacity for internal list.
+ */
+ public void setNumCols( int numCols )
+ {
+ this.numCols = numCols;
+ }
+ /**
+ * Get list at specified index
+ */
+ public List getListAt( int index )
+ {
+ return (List)lists.get(index);
+ }
+
+ /**
+ * Add a list without checking
+ */
+ public void addList( List list )
+ {
+ lists.add( list);
+ }
+
+ /**
+ * Set list at specified index. Previous list is disguarded.
+ * Add empty list if necessary.
+ * Indexes go from 0 to numCols-1
+ * @param index index of the list to add.
+ * @param list list to set.
+ */
+ public void setListAt( int index, List list )
+ {
+ // First, ensure capacity
+ while( index>lists.size() ) lists.add(new ArrayList());
+ lists.add( index, list);
+ }
+
+ /**
+ * Reset settings
+ */
+ public void reset()
+ {
+ numCols = 0;
+ lists.clear();
+ }
+
+ public String toString()
+ {
+ return "colCount=" + numCols
+ + " , lists=" + lists;
+ }
+ }
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalSettingsForm.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalSettingsForm.java
new file mode 100644
index 0000000..964c19b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/PortalSettingsForm.java
@@ -0,0 +1,245 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.struts.action.ActionForm;
+
+
+/**
+ * Action form used to read data from web page form.
+ */
+public final class PortalSettingsForm extends ActionForm {
+
+ /** Validate value */
+ protected String validate;
+ /** empty list used by reset */
+ protected String[] empty = {};
+ /** list of "remaining" choices */
+ protected String[] remaining = empty;
+ /** list of user columns */
+ protected List columns = new ArrayList();
+ /** list of user columns labels */
+ protected List columnLabels = new ArrayList();
+ /** list of columns selected by user */
+ protected List newCols = new ArrayList();
+
+ /** Choice list */
+ protected List choice;
+ /** Choice list labels */
+ protected List choiceLabels;
+ /** Is initialized ? */
+ protected boolean initialized = false;
+
+
+ /**
+ * Set col
+ */
+ public void setCol( int index, List col )
+ {
+ columns.set( index, col);
+ }
+
+ /**
+ * Add col
+ */
+ public void addCol( List col )
+ {
+ columns.add( col);
+ }
+
+ /**
+ * Get col Labels
+ */
+ public List getColLabels(int index)
+ {
+ return (List)columnLabels.get(index);
+ }
+
+ /**
+ * Set col Labels
+ */
+ public void setColLabels( int index, List col )
+ {
+ columnLabels.set( index, col);
+ }
+
+ /**
+ * Add col Labels
+ */
+ public void addColLabels( List col )
+ {
+ columnLabels.add( col);
+ }
+
+ /**
+ * Get col
+ */
+ public List getCol(int index)
+ {
+ return (List)columns.get(index);
+ }
+
+ /**
+ * Set col Labels
+ */
+ public void setNewCol( int index, String list[] )
+ {
+ // ensure capacity
+ while( index>=newCols.size())newCols.add(null);
+ newCols.set( index, list);
+ }
+
+ /**
+ * Get col
+ */
+ public String[] getNewCol(int index)
+ {
+ if(newCols==null || index>=newCols.size())
+ return null;
+ return (String[])newCols.get(index);
+ }
+
+ /**
+ * Get number of columns
+ */
+ public int getNumCol()
+ {
+ return newCols.size();
+ }
+
+ /**
+ * Set list1
+ */
+ public void setL1( String array[] )
+ {
+ setNewCol(1, array);
+ }
+ /**
+ * Set list1
+ */
+ public String[] getL1()
+ {
+ return getNewCol(1);
+ }
+
+ /**
+ * Set list1
+ */
+ public void setL0( String array[] )
+ {
+ setNewCol(0, array);
+ }
+ /**
+ * Set list1
+ */
+ public String[] getL0()
+ {
+ return getNewCol(0);
+ }
+ /**
+ * Set list1
+ */
+ public void setRemaining( String array[] )
+ {
+ remaining = array;
+ }
+ /**
+ * Set list1
+ */
+ public String[] getRemaining()
+ {
+ return remaining;
+ }
+
+
+ /**
+ * Set list1
+ */
+ public void setChoices( List list )
+ {
+ choice = list;
+ }
+ /**
+ * Set list1
+ */
+ public void setChoiceLabels( List list )
+ {
+ choiceLabels = list;
+ }
+ /**
+ * Set list1
+ */
+ public List getChoices()
+ {
+ return choice;
+ }
+ /**
+ * Set list1
+ */
+ public List getChoiceLabels()
+ {
+ return choiceLabels;
+ }
+
+ /**
+ * Is this form submitted ?
+ */
+ public boolean isSubmitted()
+ {
+ return validate != null;
+ }
+
+ /**
+ * Is this form submitted ?
+ */
+ public void setValidate( String value)
+ {
+ this.validate = value;
+ }
+
+ /**
+ * Reset properties
+ */
+ public void reset()
+ {
+ remaining = empty;
+ validate = null;
+ columns.clear();
+ columnLabels.clear();
+ newCols.clear();
+ }
+ /**
+ * Initialized flag
+ */
+ public boolean isInitialized()
+ {
+ return initialized;
+ }
+ /**
+ * Initialized flag
+ */
+ public void setInitialized( boolean isInitialized)
+ {
+ initialized = isInitialized;
+ }
+}
+
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserMenuAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserMenuAction.java
new file mode 100644
index 0000000..6455cbf
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserMenuAction.java
@@ -0,0 +1,352 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.ComponentDefinition;
+import org.apache.struts.tiles.Controller;
+import org.apache.struts.tiles.DefinitionsUtil;
+import org.apache.struts.tiles.actions.TilesAction;
+import org.apache.struts.tiles.beans.MenuItem;
+
+/**
+ * This controller load user menu settings and put them in tile context.
+ * If menu settings are not defined for user, defined them based on tiles
+ * attributes used as default.
+ *
+ * This implementation extends Struts Action, and also define Tiles Controller interface.
+ * This allows to use it as well as a controller type or a controller url. If used
+ * as controller type, Struts Action functionality are not availables.
+ *
+ * Tiles input attributes :
+ * <ul>
+ * <li>title : menu title</li>
+ * <li>items : Menu entries used as default when user settings is created</li>
+ * <li>defaultChoice : Menus or menu entries porposed as choice to user</li>
+ * <li>storeUnderName : Store user settings under provided name in session context [optional]</li>
+ * <li></li>
+ * </ul>
+ * Tiles output attributes :
+ * <ul>
+ * <li>title : menu title</li>
+ * <li>items : Menu items to display</li>
+ * <li></li>
+ * </ul>
+ *
+ * @version $Rev$ $Date$
+ */
+public final class UserMenuAction extends TilesAction implements Controller {
+
+ /**
+ * Commons Logging instance.
+ */
+ private static Log log = LogFactory.getLog(UserMenuAction.class);
+
+ /**
+ * Tile attribute containing name used to store user settings in session
+ * context.
+ */
+ public static String USER_SETTINGS_NAME_ATTRIBUTE = "userSettingsName";
+
+ /**
+ * Default name used to store settings in session context.
+ */
+ public static String DEFAULT_USER_SETTINGS_NAME =
+ "tiles.examples.portal.USER_MENU_SETTINGS";
+
+ /**
+ * Default name used to store menu catalog in application scope.
+ */
+ public static String DEFAULT_MENU_CATALOG_NAME =
+ "tiles.examples.portal.MenuCatalog";
+
+ /**
+ * Tile attribute containing name used to store menu catalog in application
+ * scope.
+ */
+ public static String MENU_CATALOG_NAME_ATTRIBUTE = "catalogName";
+
+ /**
+ * Tile attribute containing name of the settings definition used to
+ * initialize catalog.
+ */
+ public static final String CATALOG_SETTING_ATTRIBUTE = "catalogSettings";
+
+ /**
+ * Tile attribute containing items to render.
+ */
+ public static String USER_ITEMS_ATTRIBUTE = "items";
+
+ /**
+ * Struts' action perform().
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ this.execute(
+ context,
+ request,
+ response,
+ getServlet().getServletContext());
+
+ return null;
+ }
+
+ /**
+ * Method associated to a tile and called immediately before tile is included.
+ * @param tileContext Current tile context.
+ * @param request Current request
+ * @param response Current response
+ * @param servletContext Current servlet context
+ */
+ public void perform(
+ ComponentContext context,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ServletContext servletContext)
+ throws ServletException, IOException {
+
+ log.debug("Enter action UserMenuAction");
+
+ // Load user settings from user context
+ MenuSettings settings = getUserSettings(request, context);
+
+ // Set parameters for rendering page
+ context.putAttribute(USER_ITEMS_ATTRIBUTE, settings.getItems());
+
+ log.debug("settings=" + settings);
+ log.debug("Exit action UserMenuAction");
+
+ }
+
+ /**
+ * Load user setting.
+ * This implementation load setting from user context.
+ * If settings are not found, initialized them from default items defined
+ * in Tile's context.
+ * If settings are not found, initialized them.
+ */
+ public static MenuSettings getUserSettings(
+ HttpServletRequest request,
+ ComponentContext context)
+ throws ServletException {
+
+ // Get current session.
+ HttpSession session = request.getSession();
+
+ // Retrieve attribute name used to store settings.
+ String userSettingsName =
+ (String) context.getAttribute(USER_SETTINGS_NAME_ATTRIBUTE);
+
+ if (userSettingsName == null) {
+ userSettingsName = DEFAULT_USER_SETTINGS_NAME;
+ }
+
+ // Get user list from user context
+ MenuSettings settings =
+ (MenuSettings) session.getAttribute(userSettingsName);
+
+ // If settings don't exist, create and initialize them
+ // Initialization is done from context attribute denoted by ITEMS
+ if (settings == null) {
+ // List doesn't exist, create it and initialize it from Tiles parameters
+ settings = new MenuSettings();
+ try {
+ settings.addItems(
+ (List) context.getAttribute(USER_ITEMS_ATTRIBUTE));
+ } catch (ClassCastException ex) {
+ throw new ServletException("Can't initialize user menu : default items must be a list of items");
+ }
+
+ // Save user settings in session
+ session.setAttribute(userSettingsName, settings);
+ }
+
+ return settings;
+ }
+
+ /**
+ * Get catalog of available menu entries.
+ * This implementation creates catalog list from the provided menu bar
+ * entries.
+ */
+ public static List getCatalog(
+ ComponentContext context,
+ HttpServletRequest request,
+ ServletContext servletContext)
+ throws ServletException {
+
+ // Retrieve name used to store catalog in application context.
+ // If not found, use default name
+ String catalogName =
+ (String) context.getAttribute(MENU_CATALOG_NAME_ATTRIBUTE);
+
+ if (catalogName == null) {
+ catalogName = DEFAULT_MENU_CATALOG_NAME;
+ }
+
+ // Get catalog from context
+ List catalog = (List) servletContext.getAttribute(catalogName);
+
+ // If not found, initialize it from provided default menu
+ if (catalog == null) {
+ Object menuBar = context.getAttribute(CATALOG_SETTING_ATTRIBUTE);
+ if (menuBar == null) {
+ throw new ServletException(
+ "Attribute '"
+ + CATALOG_SETTING_ATTRIBUTE
+ + "' must be set. It define entries used in catalog");
+ }
+
+ catalog = new ArrayList();
+ extractItems(catalog, menuBar, request, servletContext);
+ if (catalog.size() == 0) {
+ throw new ServletException("Can't initialize menu items catalog");
+ }
+
+ // save it for future use
+ servletContext.setAttribute(catalogName, catalog);
+ }
+
+ return catalog;
+ }
+
+ /**
+ * Extract menu items from passed object. Items are stored in
+ * <code>result</code> parameter.
+ * This method allows to create a list of menu entries from existing menus.
+ * Check object type class :
+ * <li>
+ * <ul>MenuItems : add it</ul>
+ * <ul>ComponentDefinition : get attribute items, or list if not found.
+ * Call ExtractItems with resulting attribute.
+ * </ul>
+ * <ul>List : iterate on list, and call ExtractItems for each element.
+ * </li>
+ * @param result result list (should be initialized)
+ * @param object object to add (MenuItems, Definition, ...)
+ * @param request current request
+ * @param servletContext current servlet context.
+ */
+ private static void extractItems(
+ List result,
+ Object object,
+ HttpServletRequest request,
+ ServletContext servletContext) {
+
+ log.debug("Extract menu item from '" + object + "'");
+
+ if (object instanceof String) { // definition name
+ try {
+ ComponentDefinition def =
+ DefinitionsUtil.getDefinition(
+ (String) object,
+ request,
+ servletContext);
+
+ extractItems(result, def, request, servletContext);
+
+ } catch (Exception ex) { // silently fail
+ }
+
+ } else if (object instanceof List) {
+ List list = (List) object;
+ Iterator iter = list.iterator();
+ while (iter.hasNext()) {
+ extractItems(result, iter.next(), request, servletContext);
+ }
+
+ } else if (object instanceof ComponentDefinition) {
+ ComponentDefinition definition = (ComponentDefinition) object;
+ Object attribute = definition.getAttribute("items");
+ if (attribute == null) {
+ attribute = definition.getAttribute("list");
+ }
+
+ if (attribute == null) {
+ return;
+ }
+
+ extractItems(result, attribute, request, servletContext);
+
+ } else if (object instanceof MenuItem) {
+ result.add(object);
+ }
+ }
+
+ /**
+ * @see org.apache.struts.tiles.Controller#execute(org.apache.struts.tiles.ComponentContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext)
+ */
+ public void execute(
+ ComponentContext tileContext,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ServletContext servletContext)
+ throws Exception {
+
+ log.debug("Enter action UserMenuAction");
+
+ // Load user settings from user context
+ MenuSettings settings = getUserSettings(request, tileContext);
+
+ // Set parameters for rendering page
+ tileContext.putAttribute(USER_ITEMS_ATTRIBUTE, settings.getItems());
+
+ log.debug("settings=" + settings);
+ log.debug("Exit action UserMenuAction");
+
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserMenuSettingsAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserMenuSettingsAction.java
new file mode 100644
index 0000000..b02c14a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserMenuSettingsAction.java
@@ -0,0 +1,166 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.actions.TilesAction;
+import org.apache.struts.tiles.beans.MenuItem;
+
+/**
+ * Tiles controller as Struts Action.
+ * This controller take a list of lists of MenuItems, and arrange them
+ * to be shown by appropriate jsp view.
+ * Create and set following attribute in Tile context :
+ * <ul>
+ * <li>names : list of names to display</li>
+ * <li>returnedValues : list of corresponding key, or values to return</li>
+ * <li>selecteds : list of boolean indicating whether or not a name is selected</li>
+ * </ul>
+ * Tiles input attributes :
+ * <ul>
+ * <li>title : menu title</li>
+ * <li>items : Menu entries used as default when user settings is created</li>
+ * <li>defaultChoice : Menus or menu entries porposed as choice to user</li>
+ * <li>storeUnderName : Store user settings under provided name in session context [optional]</li>
+ * <li></li>
+ * </ul>
+ * Tiles output attributes :
+ * <ul>
+ * <li>choiceItems : List of menu items proposed as a choice</li>
+ * <li>userItems : List of user actual menu items</li>
+ * </ul>
+ *
+ */
+public class UserMenuSettingsAction extends TilesAction {
+
+ /**
+ * Commons Logging instance.
+ */
+ private static Log log = LogFactory.getLog(UserMenuSettingsAction.class);
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ log.debug("Enter action UserMenuSettingsAction");
+
+ MenuSettingsForm actionForm = (MenuSettingsForm) form;
+
+ // Load user menu settings and available list of choices
+ MenuSettings settings = UserMenuAction.getUserSettings(request, context);
+ List catalog =
+ UserMenuAction.getCatalog(
+ context,
+ request,
+ getServlet().getServletContext());
+
+ // Check if form is submitted
+ // If true, read, check and store new values submitted by user.
+ if (actionForm.isSubmitted()) { // read arrays
+
+ log.debug("form submitted");
+
+ settings.reset();
+ settings.addItems(getItems(actionForm.getSelected(), catalog));
+
+ log.debug("settings : " + settings.toString());
+ actionForm.reset();
+
+ }
+
+ // Prepare data for view tile
+ context.putAttribute("userItems", settings.getItems());
+ context.putAttribute("catalog", catalog);
+
+ log.debug("Exit action UserMenuSettingsAction");
+ return null;
+ }
+
+ /**
+ * Check selected items, and return apppropriate list of items.
+ * For each item in selected list, check if it exist in catalog.
+ * Also check for double.
+ * @param selectedKey Key of selected items (generally, link url)
+ * @param catalog List of avalaible items to compare against.
+ */
+ protected static List getItems(String[] selectedKey, List catalog) {
+ List selectedList = java.util.Arrays.asList(selectedKey);
+ List result = new ArrayList(selectedList.size());
+
+ Iterator iter = selectedList.iterator();
+ while (iter.hasNext()) {
+ MenuItem item = getItem(iter.next(), catalog);
+ if (item != null) {
+ result.add(item);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get item by its key in list of choices
+ * @param key Key of selected items (generally, link url)
+ * @param catalog List of avalaible items to compare against.
+ * @return corresponding item or null if not found.
+ */
+ protected static MenuItem getItem(Object key, List catalog) {
+ Iterator iter = catalog.iterator();
+ while (iter.hasNext()) {
+ MenuItem item = (MenuItem) iter.next();
+ if (item.getLink().equals(key)) {
+ return item;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserPortalAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserPortalAction.java
new file mode 100644
index 0000000..931da4b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserPortalAction.java
@@ -0,0 +1,187 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.actions.TilesAction;
+
+/**
+ * This controller load user portal settings and put them in tile context.
+ * If portal settings are not defined for user, defined them based on tiles
+ * attributes used as default.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class UserPortalAction extends TilesAction {
+
+ /**
+ * Default name used to store settings in session context.
+ */
+ public static String DEFAULT_USER_SETTINGS_NAME =
+ "tiles.examples.portal.USER_PORTAL_SETTINGS";
+
+ /**
+ * Tile attribute containing number of columns in portal.
+ */
+ public static String NUMCOLS_ATTRIBUTE = "numCols";
+
+ /**
+ * Tile attribute containing list prefix name.
+ */
+ public static String LIST_ATTRIBUTE = "list";
+
+ /**
+ * Tile attribute containing list of labels prefix name.
+ */
+ public static String LIST_LABELS_ATTRIBUTE = "labels";
+
+ /**
+ * Tile attribute containing name used to store user settings in session
+ * context.
+ */
+ public static String USER_SETTINGS_NAME_ATTRIBUTE = "userSettingsName";
+
+ /**
+ * Name used to store portal catalog in application scope.
+ */
+ public static String PORTAL_CATALOG_NAME = "tiles.examples.portal.PortalCatalog";
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Get user portal list from user context
+ PortalSettings settings = getSettings(request, context);
+
+ // Set parameters for tiles
+ context.putAttribute("numCols", Integer.toString(settings.getNumCols()));
+
+ for (int i = 0; i < settings.getNumCols(); i++) {
+ context.putAttribute("list" + i, settings.getListAt(i));
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieve user setting from session.
+ * If settings are not found, initialized them.
+ */
+ public static PortalSettings getSettings(
+ HttpServletRequest request,
+ ComponentContext context) {
+
+ // Get current session.
+ HttpSession session = request.getSession();
+
+ // Retrieve user context id used to store settings
+ String userSettingsId =
+ (String) context.getAttribute(USER_SETTINGS_NAME_ATTRIBUTE);
+
+ if (userSettingsId == null) {
+ userSettingsId = DEFAULT_USER_SETTINGS_NAME;
+ }
+
+ // Get user portal list from user context
+ PortalSettings settings =
+ (PortalSettings) session.getAttribute(userSettingsId);
+
+ if (settings == null) {
+ // List doesn't exist, create it and initialize it from Tiles parameters
+ settings = new PortalSettings();
+ settings.setNumCols((String) context.getAttribute(NUMCOLS_ATTRIBUTE));
+
+ for (int i = 0; i < settings.getNumCols(); i++) {
+ List tiles =
+ (List) context.getAttribute(((String) LIST_ATTRIBUTE + i));
+
+ settings.setListAt(i, tiles);
+ }
+
+ // Save user settings in session
+ session.setAttribute(userSettingsId, settings);
+ }
+
+ return settings;
+ }
+
+ /**
+ * Retrieve portal choices object.
+ * Create it from default values if needed.
+ */
+ static public PortalCatalog getPortalCatalog(
+ ComponentContext context,
+ ServletContext servletContext) {
+
+ PortalCatalog catalog =
+ (PortalCatalog) servletContext.getAttribute(PORTAL_CATALOG_NAME);
+
+ if (catalog == null) { // Initialize catalog
+ catalog = new PortalCatalog();
+ int numCols =
+ Integer.parseInt((String) context.getAttribute(NUMCOLS_ATTRIBUTE));
+
+ for (int i = 0; i < numCols; i++) {
+ List tiles =
+ (List) context.getAttribute(((String) LIST_ATTRIBUTE + i));
+
+ List labels =
+ (List) context.getAttribute(
+ ((String) LIST_LABELS_ATTRIBUTE + i));
+
+ catalog.addTiles(tiles, labels);
+ }
+ servletContext.setAttribute(PORTAL_CATALOG_NAME, catalog);
+ }
+
+ return catalog;
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserPortalSettingsAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserPortalSettingsAction.java
new file mode 100644
index 0000000..5cde5f8
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/portal/UserPortalSettingsAction.java
@@ -0,0 +1,104 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.portal;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.actions.TilesAction;
+
+/**
+ * Implementation of <strong>Action</strong> that populates an instance of
+ * <code>SubscriptionForm</code> from the currently specified subscription.
+ *
+ * This action is used as controller for portal settings editor.
+ * It does folowing :
+ * <ul>
+ * <li>Load or create user portal settings</li>
+ * <li>Read web form, and set user portal setting accordingly</li>
+ * <li>Prepare portal editor needed attributes</li>
+ * <li></li>
+ * </ul>
+ *
+ * @version $Rev$ $Date$
+ */
+public final class UserPortalSettingsAction extends TilesAction {
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ PortalSettingsForm prefsForm = (PortalSettingsForm) form;
+
+ // Get user portal settings from user context
+ PortalSettings settings = UserPortalAction.getSettings(request, context);
+ PortalCatalog catalog =
+ UserPortalAction.getPortalCatalog(
+ context,
+ getServlet().getServletContext());
+
+ if (prefsForm.isSubmitted()) { // read arrays
+
+ // Set settings cols according to user choice
+ for (int i = 0; i < prefsForm.getNumCol(); i++) {
+ settings.setListAt(i, catalog.getTiles(prefsForm.getNewCol(i)));
+ }
+
+ prefsForm.reset();
+
+ }
+
+ // Set lists values to be shown
+ for (int i = 0; i < settings.getNumCols(); i++) {
+ prefsForm.addCol(settings.getListAt(i));
+ prefsForm.addColLabels(catalog.getTileLabels(settings.getListAt(i)));
+ }
+
+ prefsForm.setChoices(catalog.getTiles());
+ prefsForm.setChoiceLabels(catalog.getTilesLabels());
+
+ return null;
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/rssChannel/Channels.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/rssChannel/Channels.java
new file mode 100644
index 0000000..2f61206
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/rssChannel/Channels.java
@@ -0,0 +1,169 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.rssChannel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+//import org.apache.commons.digester.rss.Channel;
+//import org.apache.commons.digester.rss.RSSDigester;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionMessage;
+import org.apache.struts.action.ActionMessages;
+import org.apache.struts.tiles.ComponentContext;
+
+/**
+ * Read and parse RSS files found at on a given
+ * list in user request or session, save the Channel
+ * beans in request scope,and forward to "continue".
+ * @expects path={uri} on command line or as parameter property to ActionMapping.
+ * @expects an input page or error forwarding if exception digesting RSS
+ * @version $Rev$ $Date$
+ */
+public final class Channels extends Action {
+
+ /**
+ * Commons Logging instance.
+ */
+ private static Log log = LogFactory.getLog(Channels.class);
+
+ /**
+ * Tile attribute key for saving Channel bean
+ */
+ public static final String CHANNELS_KEY = "CHANNELS";
+
+ /**
+ * Tile attribute key for getting Channel urls list
+ */
+ public static final String CHANNEL_URLS_KEY = "urls";
+
+ /**
+ * Tile attribute key for getting Channel url attribute
+ */
+ public static final String CHANNEL_URL_KEY = "url";
+
+ /**
+ * Main process of class. Reads, parses
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ log.debug("Enter Rss Channel Action");
+
+ // Try to retrieve tile context
+ ComponentContext context = ComponentContext.getContext(request);
+ if (context == null) {
+ throw new ServletException("This action must be called by a Tile, not directly");
+ }
+
+ ActionMessages errors = new ActionMessages();
+
+ // -- Retrieve parameters --
+ // Urls can come from a list, or from a single attribute.
+
+ List channels = (List) context.getAttribute(CHANNEL_URLS_KEY);
+ if (channels == null) {
+ Object url = context.getAttribute(CHANNEL_URL_KEY);
+ channels = new ArrayList(1);
+ channels.add(url);
+ }
+
+ log.debug("urls count" + channels.size());
+
+ // -- Loop through channels --
+ ArrayList channelBeans = new ArrayList(channels.size());
+// try {
+// for (int i = 0; i < channels.size(); i++) {
+// RSSDigester digester = new RSSDigester();
+// String url = (String) channels.get(i);
+// // Add application path if needed
+// if (url.startsWith("/")) {
+// url = toFullUrl(request, url);
+// }
+//
+// log.debug("Channel url=" + url);
+//
+// Channel obj = (Channel) digester.parse(url);
+//
+// log.debug("Channel:" + obj);
+//
+// channelBeans.add(obj);
+// }
+// } catch (Throwable t) {
+// errors.add(
+// ActionMessages.GLOBAL_MESSAGE,
+// new ActionMessage("rss.access.error"));
+//
+// servlet.log(t.toString());
+// }
+
+ // -- Handle Errors ---
+ if (!errors.isEmpty()) {
+ this.saveErrors(request, errors);
+
+ if (mapping.getInput() != null) {
+ return new ActionForward(mapping.getInput());
+ }
+
+ // If no input page, use error forwarding
+
+ log.debug("Exit Rss Channel Action : error");
+
+ return mapping.findForward("error");
+ }
+
+ // -- Save Bean, and Continue ---
+
+ log.debug("Exit Rss Channel Action");
+
+ // Use Tile context to pass channels
+ context.putAttribute(CHANNELS_KEY, channelBeans);
+
+ return mapping.findForward("continue");
+ }
+
+ private String toFullUrl(HttpServletRequest request, String url) {
+ StringBuffer buff = new StringBuffer();
+
+ buff.append(request.getScheme()).append("://").append(
+ request.getServerName());
+
+ if (request.getServerPort() != 80) {
+ buff.append(":").append(request.getServerPort());
+ }
+
+ buff.append(request.getContextPath()).append(url);
+
+ return buff.toString();
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/rssChannel/RssChannelsAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/rssChannel/RssChannelsAction.java
new file mode 100644
index 0000000..4138cad
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/rssChannel/RssChannelsAction.java
@@ -0,0 +1,179 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.rssChannel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+//import org.apache.commons.digester.rss.Channel;
+//import org.apache.commons.digester.rss.RSSDigester;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionMessage;
+import org.apache.struts.action.ActionMessages;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.actions.TilesAction;
+
+/**
+ * Read and parse RSS files found at on a given
+ * list in Tile attribute, save the Channel
+ * beans in Tile attribute,and forward to "continue".
+ * Tiles input attributes :
+ * <ul>
+ * <li>urls : list of channel urls</li>
+ * <li>url : a channel url (if urls not use)</li>
+ * </ul>
+ * Tiles output attributes :
+ * <ul>
+ * <li>channels : List of Digester Channel beans</li>
+ * </ul>
+ *
+ * @version $Rev$ $Date$
+ */
+public final class RssChannelsAction extends TilesAction {
+
+ /**
+ * Commons Logging instance.
+ */
+ private static Log log = LogFactory.getLog(RssChannelsAction.class);
+
+ /**
+ * Tile attribute key for saving Channel bean
+ */
+ public static final String CHANNELS_KEY = "CHANNELS";
+
+ /**
+ * Tile attribute key for getting Channel urls list
+ */
+ public static final String CHANNEL_URLS_KEY = "urls";
+
+ /**
+ * Tile attribute key for getting Channel url attribute
+ */
+ public static final String CHANNEL_URL_KEY = "url";
+
+ /**
+ * Main process of class. Reads, parses
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ log.debug("Enter Rss Channel Action");
+
+ ActionMessages errors = new ActionMessages();
+
+ // -- Retrieve parameters --
+ // Urls can come from a list, or from a single attribute.
+
+ List channels = (List) context.getAttribute(CHANNEL_URLS_KEY);
+ if (channels == null) {
+ Object url = context.getAttribute(CHANNEL_URL_KEY);
+ channels = new ArrayList(1);
+ channels.add(url);
+ }
+
+ log.debug("urls count" + channels.size());
+
+ // -- Loop through channels --
+ List channelBeans = new ArrayList(channels.size());
+// try {
+// for (int i = 0; i < channels.size(); i++) {
+// RSSDigester digester = new RSSDigester();
+// String url = (String) channels.get(i);
+// // Add application path if needed
+// if (url.startsWith("/")) {
+// url = toFullUrl(request, url);
+// }
+//
+// log.debug("Channel url=" + url);
+//
+// Channel obj = (Channel) digester.parse(url);
+//
+// log.debug("Channel:" + obj);
+//
+// channelBeans.add(obj);
+// }
+//
+// } catch (Throwable t) {
+// errors.add(
+// ActionMessages.GLOBAL_MESSAGE,
+// new ActionMessage("rss.access.error"));
+//
+// servlet.log(t.toString());
+// }
+
+ // -- Handle Errors ---
+ if (!errors.isEmpty()) {
+ this.saveErrors(request, errors);
+ // If no input page, use error forwarding
+
+ log.debug("Exit Rss Channel Action : error");
+
+ return null;
+ }
+
+ // -- Save Bean, and Continue ---
+
+ log.debug("Exit Rss Channel Action");
+
+ // Use Tile context to pass channels
+ context.putAttribute(CHANNELS_KEY, channelBeans);
+
+ return null;
+ }
+
+ /**
+ * Compute Full local url from an url starting with "/".
+ */
+ private String toFullUrl(HttpServletRequest request, String url) {
+ StringBuffer buff = new StringBuffer();
+
+ buff.append(request.getScheme()).append("://").append(
+ request.getServerName());
+
+ if (request.getServerPort() != 80) {
+ buff.append(":").append(request.getServerPort());
+ }
+
+ buff.append(request.getContextPath()).append(url);
+
+ return buff.toString();
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/DefinitionCatalog.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/DefinitionCatalog.java
new file mode 100644
index 0000000..1909551
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/DefinitionCatalog.java
@@ -0,0 +1,172 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.skin;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.struts.tiles.ComponentDefinition;
+import org.apache.struts.tiles.DefinitionsFactoryException;
+import org.apache.struts.tiles.DefinitionsUtil;
+import org.apache.struts.tiles.FactoryNotFoundException;
+import org.apache.struts.tiles.NoSuchDefinitionException;
+
+/**
+ * A catalog of available definitions.
+ */
+public class DefinitionCatalog
+{
+ /** debug flag */
+ public static boolean debug = true;
+ /** Attribute carrying definition readable name */
+ public static final String LABEL_NAME_ATTRIBUTE = "skin.label";
+ /** Attribute carrying the list of definition names */
+ public static final String DEFINITION_LIST_ATTRIBUTE = "skin.list";
+
+ /**
+ * Map of skins, by their keys
+ */
+ private Map definitions = new HashMap();
+ /**
+ * Map of skins, by their keys
+ */
+ private ComponentDefinition defaultDefinition;
+
+ /**
+ * List of names
+ */
+ private List names = new ArrayList();
+
+ /**
+ * List of keys
+ */
+ private List keys = new ArrayList();
+
+ /**
+ * Constructor.
+ * Initialize catalog from definitions factory.
+ * @param HttpRequest request
+ * @param ServletContext context
+ * @throws FactoryNotFoundException, DefinitionsFactoryException
+ */
+ public DefinitionCatalog( String catalogName, HttpServletRequest request, ServletContext context)
+ throws FactoryNotFoundException, DefinitionsFactoryException
+ {
+ // Get definition containing list of definitions
+ ComponentDefinition catalogDef = DefinitionsUtil.getDefinition( catalogName, request, context);
+ if(debug)
+ System.out.println( "Got definition " + catalogDef );
+ // Get list of definition names
+ List list = (List)catalogDef.getAttribute( DEFINITION_LIST_ATTRIBUTE );
+ Iterator i = list.iterator();
+ while(i.hasNext() )
+ {
+ String name = (String)i.next();
+ System.out.println( "add " + name );
+ ComponentDefinition def = DefinitionsUtil.getDefinition(name, request, context);
+ if(def==null)
+ throw new NoSuchDefinitionException("Can't find definition '" + name + "'" );
+ add( name, def );
+ } // end loop
+ if(debug)
+ System.out.println( "Catalog initialized" );
+ }
+
+ /**
+ * Get definition identified by key.
+ * @param key
+ * @return Definition associated to key
+ */
+ public ComponentDefinition get(Object key)
+ {
+ if(key==null)
+ return getDefault();
+ return (ComponentDefinition)definitions.get(key);
+ }
+
+ /**
+ * Get definition identified by key.
+ * @param key
+ * @return Definition associated to key
+ */
+ public ComponentDefinition getDefault()
+ {
+ return defaultDefinition;
+ }
+
+ /**
+ * Return List of names of definitions presents in catalog.
+ * Names are user readable names. Returned list has the same order as list
+ * returned by getKeys.
+ * @return List
+ */
+ public List getNames()
+ {
+ return names;
+ }
+
+ /**
+ * Get list of keys of definitions present in catalog.
+ * A key is used to retrieve a skin from catalog.
+ * @return List
+ */
+ public List getKeys()
+ {
+ return keys;
+ }
+
+ /**
+ * Check if requested key is valid in catalog.
+ * Return null otherwise
+ * @return valid key or null
+ */
+ public String getKey( String key )
+ {
+ if( definitions.get(key) != null)
+ return key;
+
+ return null;
+ }
+
+ /**
+ * Add a skin definition
+ * @param definition
+ */
+ public void add(String key, ComponentDefinition definition)
+ {
+ // Intitialize default definition with first definition encountered
+ if( defaultDefinition == null )
+ {
+ defaultDefinition = definition;
+ }
+ // store definition
+ definitions.put( key , definition);
+ Object name = definition.getAttribute(LABEL_NAME_ATTRIBUTE);
+ if( name == null )
+ name = key;
+ names.add( name );
+ keys.add(key);
+ }
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSettingsAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSettingsAction.java
new file mode 100644
index 0000000..e5faa3d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSettingsAction.java
@@ -0,0 +1,99 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.skin;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.actions.TilesAction;
+
+/**
+ * Action used to set user skin.
+ */
+public class LayoutSettingsAction extends TilesAction
+{
+ /** debug flag */
+ public static boolean debug = true;
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ * This method should be implemented by subclasses.
+ *
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception
+ {
+ if(debug)
+ System.out.println("Enter action LayoutSettingAction");
+
+ LayoutSettingsForm actionForm = (LayoutSettingsForm)form;
+
+ // Load user menu settings and available list of choices
+ String selected = LayoutSwitchAction.getUserSetting( context, request );
+ if(selected==null)
+ selected = "default";
+ System.out.println("user setting retrieved");
+ DefinitionCatalog catalog = LayoutSwitchAction.getCatalog( context, request, getServlet().getServletContext() );
+ System.out.println("catalog retrieved");
+
+ // Check if form is submitted
+ // If true, read, check and store new values submitted by user.
+ if( actionForm.isSubmitted() )
+ { // read arrays
+ if(debug)
+ System.out.println("form submitted");
+ selected = catalog.getKey(actionForm.getSelected());
+ if(debug)
+ System.out.println( "key : " + selected );
+ LayoutSwitchAction.setUserSetting(context, request, selected );
+ if(debug)
+ System.out.println( "settings : " + selected );
+ actionForm.reset();
+ } // end if
+
+ // Prepare data for view tile
+ context.putAttribute( "selected", selected );
+ context.putAttribute( "catalog", catalog );
+
+ if(debug)
+ System.out.println("Exit action LayoutSettingAction");
+ return null;
+ }
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSettingsForm.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSettingsForm.java
new file mode 100644
index 0000000..50c3074
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSettingsForm.java
@@ -0,0 +1,81 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.skin;
+
+import org.apache.struts.action.ActionForm;
+
+/**
+ * Struts form
+ */
+public class LayoutSettingsForm extends ActionForm
+{
+
+ /** Validate value */
+ protected String validate;
+
+ /**
+ * User selected key value
+ */
+ private String selected;
+
+ /**
+ * Access method for the selectedKey property.
+ *
+ * @return the current value of the selectedKey property
+ */
+ public String getSelected()
+ {
+ return selected;
+ }
+
+ /**
+ * Sets the value of the selectedKey property.
+ *
+ * @param aSelectedKey the new value of the selectedKey property
+ */
+ public void setSelected(String aSelectedKey)
+ {
+ selected = aSelectedKey;
+ }
+ /**
+ * Is this form submitted ?
+ */
+ public boolean isSubmitted()
+ {
+ return validate != null;
+ }
+
+ /**
+ * Is this form submitted ?
+ */
+ public void setValidate( String value)
+ {
+ this.validate = value;
+ }
+
+ /**
+ * Reset properties
+ */
+ public void reset()
+ {
+ selected = null;
+ validate = null;
+ }
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSwitchAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSwitchAction.java
new file mode 100644
index 0000000..86e673c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/LayoutSwitchAction.java
@@ -0,0 +1,225 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.skin;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.ComponentDefinition;
+import org.apache.struts.tiles.DefinitionsFactoryException;
+import org.apache.struts.tiles.actions.TilesAction;
+
+ /**
+ * Customize layouts according to predefined "skin"
+ * A "skin" is a set of layouts used together to provide a consistent
+ * Look & Feel.
+ * This action is called when inserting a definition's layout. It replaces
+ * definition's layout by the one set in selected skin.
+ * the appropriate
+ * Available skins are stored in application context. They are initialized from
+ * a Tile definition.
+ * Currently selected skin is stored under user session, if any. Otherwise,
+ * the default skin is used.
+ * This action act for all layouts. A Tile's attribute (skinLayout) is used as a key to
+ * know which layouts is concerned.
+ */
+public class LayoutSwitchAction extends TilesAction
+{
+ /** debug flag */
+ public static boolean debug = true;
+ /** Tile's attribute containing layout key */
+ public static final String LAYOUT_ATTRIBUTE = "layout.attribute";
+ /** Tile attribute containing name used to store user settings in session context */
+ public static String USER_SETTINGS_NAME_ATTRIBUTE = "userSettingsName";
+ /** Default name used to store settings in session context */
+ public static String DEFAULT_USER_SETTINGS_NAME = "examples.tiles.skin.SELECTED_DEFINITION";
+
+ /** Name of catalog in application context */
+ public static final String CATALOG_NAME = "examples.tiles.skin.CATALOG_NAME";
+
+ /** Default name used to store menu catalog in application scope */
+ public static String DEFAULT_CATALOG_NAME = "tiles.examples.skin.layoutCatalog";
+ /** Tile attribute containing name used to store menu catalog in application scope */
+ public static String CATALOG_NAME_ATTRIBUTE = "catalogName";
+ /** Tile attribute containing name of the settings definition used to initialize catalog */
+ public static final String CATALOG_SETTING_ATTRIBUTE = "catalogSettings";
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ * This method should be implemented by subclasses.
+ *
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception
+ {
+ if(debug)
+ System.out.println( "EnterLayoutSwitchAction" );
+ // Get attribute value indicating which layout we want
+ String layoutKey = (String)context.getAttribute( LAYOUT_ATTRIBUTE );
+ if(layoutKey==null)
+ throw new ServletException( "Error - CustomSkinAction : attribute '"
+ + LAYOUT_ATTRIBUTE
+ + "' not found in Tile's attributes. Need it to select appropriate layout" );
+
+ // Get user current skin
+ ComponentDefinition definition = getCurrentDefinition( context, request, getServlet().getServletContext() );
+ // get requested layout from definition
+ String layout = (String)definition.getAttribute(layoutKey);
+ if(layout==null)
+ throw new ServletException( "Error - CustomSkinAction : no layout defined for key '"
+ + layoutKey
+ + "' in currently selected skin '"
+ + getUserSetting(context, request ) + "'." );
+ // set path to forward to
+ // Not very nice solution, need to improve it
+ /*
+ ComponentDefinition forwarDefinition = new ComponentDefinition( "", layout, new HashMap() );
+ DefinitionsUtil.setActionDefinition( request, forwarDefinition );
+ */
+ if(debug)
+ System.out.println( "Switch to : " + layout );
+ RequestDispatcher rd = getServlet().getServletContext().getRequestDispatcher( layout );
+ if(rd==null)
+ throw new ServletException( "LayoutSwitch error : Can't find layout '"
+ + layout + "'." );
+ rd.include(request, response);
+ if(debug)
+ System.out.println( "Exit LayoutSwitchAction" );
+ return null;
+ }
+
+ /**
+ * Retrieve key associated to user.
+ * This key denote a definition in catalog.
+ * Return user selected key, or "default" if none is set.
+ */
+ public static String getUserSetting( ComponentContext context, HttpServletRequest request )
+ {
+ HttpSession session = request.getSession( false );
+ if( session == null )
+ return null;
+
+ // Retrieve attribute name used to store settings.
+ String userSettingsName = (String)context.getAttribute( USER_SETTINGS_NAME_ATTRIBUTE );
+ if( userSettingsName == null )
+ userSettingsName = DEFAULT_USER_SETTINGS_NAME;
+
+ return (String)session.getAttribute(userSettingsName);
+ }
+
+ /**
+ * Set user setting value.
+ * This key denote a definition in catalog.
+ * Return user selected key, or "default" if none is set.
+ */
+ public static void setUserSetting( ComponentContext context, HttpServletRequest request, String setting )
+ {
+ HttpSession session = request.getSession();
+
+ // Retrieve attribute name used to store settings.
+ String userSettingsName = (String)context.getAttribute( USER_SETTINGS_NAME_ATTRIBUTE );
+ if( userSettingsName == null )
+ userSettingsName = DEFAULT_USER_SETTINGS_NAME;
+
+ session.setAttribute(userSettingsName, setting);
+ }
+
+ /**
+ * Get currently selected skin definition.
+ */
+ public static ComponentDefinition getCurrentDefinition( ComponentContext context, HttpServletRequest request, ServletContext servletContext )
+ throws ServletException
+ {
+ // Get selected key
+ String selected = getUserSetting(context, request);
+
+ DefinitionCatalog catalog = getCatalog( context, request, servletContext);
+ ComponentDefinition definition = (ComponentDefinition)catalog.get( selected );
+ if( definition == null )
+ definition = (ComponentDefinition)catalog.getDefault();
+
+ return definition;
+ }
+
+ /**
+ * Get catalog of available skins.
+ */
+ public static DefinitionCatalog getCatalog( ComponentContext context, HttpServletRequest request, ServletContext servletContext )
+ throws ServletException
+ {
+ // Retrieve name used to store catalog in application context.
+ // If not found, use default name
+ String catalogName = (String)context.getAttribute( CATALOG_NAME_ATTRIBUTE );
+ if(catalogName == null)
+ catalogName = DEFAULT_CATALOG_NAME;
+
+ if(debug)
+ System.out.println( "Catalog name=" + catalogName );
+ try
+ {
+ DefinitionCatalog catalog = (DefinitionCatalog)servletContext.getAttribute( catalogName );
+ if(catalog == null)
+ { // create catalog
+ if(debug)
+ System.out.println( "Create catalog" );
+ String catalogSettings = (String)context.getAttribute( CATALOG_SETTING_ATTRIBUTE );
+ if(catalogSettings == null)
+ throw new ServletException( "Error - CustomSkinAction : attribute '"
+ + CATALOG_SETTING_ATTRIBUTE
+ + "' not found in Tile's attributes. Need it to initialize catalog" );
+ catalog = new DefinitionCatalog( catalogSettings, request, servletContext );
+ if(debug)
+ System.out.println( "Catalog created" );
+ servletContext.setAttribute( catalogName, catalog );
+ } // end if
+ return catalog;
+ }
+ catch(DefinitionsFactoryException ex )
+ {
+ if(debug)
+ System.out.println( "Exception : " + ex.getMessage() );
+ throw new ServletException( ex.getMessage() );
+ }
+ }
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/SimpleSwitchLayoutAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/SimpleSwitchLayoutAction.java
new file mode 100644
index 0000000..424ea99
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/skin/SimpleSwitchLayoutAction.java
@@ -0,0 +1,186 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.skin;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.DefinitionsFactoryException;
+import org.apache.struts.tiles.actions.TilesAction;
+
+ /**
+ * Simple Switch Layout
+ */
+public class SimpleSwitchLayoutAction extends TilesAction
+{
+ /** debug flag */
+ public static boolean debug = true;
+ /** Tile's attribute containing layout key */
+ public static final String LAYOUT_ATTRIBUTE = "layout.attribute";
+ /** Tile attribute containing name used to store user settings in session context */
+ public static String USER_SETTINGS_NAME_ATTRIBUTE = "userSettingsName";
+ /** Default name used to store settings in session context */
+ public static String DEFAULT_USER_SETTINGS_NAME = "examples.tiles.skin.SELECTED_DEFINITION";
+
+ /** Name of catalog in application context */
+ public static final String CATALOG_NAME = "examples.tiles.skin.CATALOG_NAME";
+
+ /** Default name used to store menu catalog in application scope */
+ public static String DEFAULT_CATALOG_NAME = "tiles.examples.skin.layoutCatalog";
+ /** Tile attribute containing name used to store menu catalog in application scope */
+ public static String CATALOG_NAME_ATTRIBUTE = "catalogName";
+ /** Tile attribute containing name of the settings definition used to initialize catalog */
+ public static final String CATALOG_SETTING_ATTRIBUTE = "catalogSettings";
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ * This method should be implemented by subclasses.
+ *
+ * @param context The current Tile context, containing Tile attributes.
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ComponentContext context,
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception
+ {
+ if(debug)
+ System.out.println( "Enter SimpleSwitchLayoutAction" );
+
+ String layoutDir = "/layouts/";
+ String userSelection = getUserSetting( context, request );
+ //String layout = "classicLayout.jsp";
+ String layout = (String)context.getAttribute( LAYOUT_ATTRIBUTE );
+ if(layout==null)
+ throw new ServletException( "Attribute '" + LAYOUT_ATTRIBUTE + "' is required." );
+
+ String layoutPath = layoutDir+userSelection+ "/" + layout;
+
+ RequestDispatcher rd = getServlet().getServletContext().getRequestDispatcher( layoutPath );
+ if(rd==null)
+ {
+ layoutPath = layoutDir + layout;
+ rd = getServlet().getServletContext().getRequestDispatcher( layoutPath );
+ if(rd==null)
+ throw new ServletException( "SwitchLayout error : Can't find layout '"
+ + layoutPath + "'." );
+ }
+ rd.include(request, response);
+ if(debug)
+ System.out.println( "Exit SimpleSwitchLayoutAction" );
+ return null;
+ }
+
+ /**
+ * Retrieve key associated to user.
+ * This key denote a definition in catalog.
+ * Return user selected key, or "default" if none is set.
+ */
+ public static String getUserSetting( ComponentContext context, HttpServletRequest request )
+ {
+ HttpSession session = request.getSession( false );
+ if( session == null )
+ return null;
+
+ // Retrieve attribute name used to store settings.
+ String userSettingsName = (String)context.getAttribute( USER_SETTINGS_NAME_ATTRIBUTE );
+ if( userSettingsName == null )
+ userSettingsName = DEFAULT_USER_SETTINGS_NAME;
+
+ return (String)session.getAttribute(userSettingsName);
+ }
+
+ /**
+ * Set user setting value.
+ * This key denote a definition in catalog.
+ * Return user selected key, or "default" if none is set.
+ */
+ public static void setUserSetting( ComponentContext context, HttpServletRequest request, String setting )
+ {
+ HttpSession session = request.getSession();
+
+ // Retrieve attribute name used to store settings.
+ String userSettingsName = (String)context.getAttribute( USER_SETTINGS_NAME_ATTRIBUTE );
+ if( userSettingsName == null )
+ userSettingsName = DEFAULT_USER_SETTINGS_NAME;
+
+ session.setAttribute(userSettingsName, setting);
+ }
+
+ /**
+ * Get catalog of available skins.
+ */
+ public static DefinitionCatalog getCatalog( ComponentContext context, HttpServletRequest request, ServletContext servletContext )
+ throws ServletException
+ {
+ // Retrieve name used to store catalog in application context.
+ // If not found, use default name
+ String catalogName = (String)context.getAttribute( CATALOG_NAME_ATTRIBUTE );
+ if(catalogName == null)
+ catalogName = DEFAULT_CATALOG_NAME;
+
+ if(debug)
+ System.out.println( "Catalog name=" + catalogName );
+ try
+ {
+ DefinitionCatalog catalog = (DefinitionCatalog)servletContext.getAttribute( catalogName );
+ if(catalog == null)
+ { // create catalog
+ if(debug)
+ System.out.println( "Create catalog" );
+ String catalogSettings = (String)context.getAttribute( CATALOG_SETTING_ATTRIBUTE );
+ if(catalogSettings == null)
+ throw new ServletException( "Error - CustomSkinAction : attribute '"
+ + CATALOG_SETTING_ATTRIBUTE
+ + "' not found in Tile's attributes. Need it to initialize catalog" );
+ catalog = new DefinitionCatalog( catalogSettings, request, servletContext );
+ if(debug)
+ System.out.println( "Catalog created" );
+ servletContext.setAttribute( catalogName, catalog );
+ } // end if
+ return catalog;
+ }
+ catch(DefinitionsFactoryException ex )
+ {
+ if(debug)
+ System.out.println( "Exception : " + ex.getMessage() );
+ throw new ServletException( ex.getMessage() );
+ }
+ }
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/template/DynTemplateAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/template/DynTemplateAction.java
new file mode 100644
index 0000000..ce62bd5
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/template/DynTemplateAction.java
@@ -0,0 +1,78 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.template;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentDefinition;
+
+
+public final class DynTemplateAction extends Action {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ System.out.println( "Start dynamic definition" );
+ // Create template definition
+ ComponentDefinition definition = new ComponentDefinition();
+ String path = "/tutorial";
+ // set definition 'contents'
+ //definition.setTemplate( "/tutorial/basic/myFramesetLayout.jsp" );
+ definition.put( "title", "My first dynamic frameset page", true );
+ // using type="string" is the same as direct=true
+ definition.put( "header", path + "/common/header.jsp", "string", null );
+ definition.put( "footer", path + "/common/footer.jsp", true );
+ definition.put( "menu", path + "/basic/menu.jsp", true );
+ definition.put( "body", path + "/basic/helloBody.jsp", true );
+
+ System.out.println( "definition=" + definition );
+ // Save our definition as a bean :
+ request.setAttribute( "templateDefinition", definition );
+
+ return (mapping.findForward("success"));
+ }
+
+ }
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/NoForward.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/NoForward.java
new file mode 100644
index 0000000..26e470b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/NoForward.java
@@ -0,0 +1,85 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.test;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+
+
+/**
+ * Implementation of <strong>Action</strong> that create a TileContext in order
+ * to force the TilesRequestProcessor to do an include instead of a forward.
+ * The side effect is that request.getRequestURI will return the URL of the
+ * calling struts action instead of the URL of the tiles layout.
+ * See the jsp documentation to understand why.
+ * Usage:
+ * use this action in conjunction with an action declaration in struts config.
+ * The action declaration should have one "success" forward to a Tile.
+ * <pre>
+ * <action path="/showRequestURI"
+ * type="org.apache.struts.webapp.tiles.test.NoForward">
+ * <forward name="success" path="test.action.noforward"/>
+ * </action>
+ * </pre>
+ * @version $Rev$ $Date$
+ */
+
+public final class NoForward extends Action {
+
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ * @since Struts 1.1
+ */
+ public ActionForward execute(ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+ // Try to retrieve tile context
+ ComponentContext context = ComponentContext.getContext( request );
+ if( context == null )
+ { // Not found, create a context
+ // This context will be detected by the TilesRequestProcessor which will do an include
+ // instead of a forward.
+ ComponentContext tileContext = new ComponentContext( );
+ ComponentContext.setContext( tileContext, request);
+ }
+ return (mapping.findForward("success"));
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/TestActionTileAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/TestActionTileAction.java
new file mode 100644
index 0000000..6a772bc
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/TestActionTileAction.java
@@ -0,0 +1,120 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.test;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.ComponentDefinition;
+import org.apache.struts.tiles.DefinitionsFactoryException;
+import org.apache.struts.tiles.DefinitionsUtil;
+import org.apache.struts.tiles.FactoryNotFoundException;
+import org.apache.struts.tiles.NoSuchDefinitionException;
+
+
+/**
+ * Implementation of <strong>Action</strong> that populates an instance of
+ * <code>SubscriptionForm</code> from the currently specified subscription.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public final class TestActionTileAction extends Action {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ // Try to retrieve tile context
+ ComponentContext context = ComponentContext.getContext( request );
+ if( context == null )
+ {
+ request.setAttribute( "actionError", "Can't get component context.");
+ return (mapping.findForward("failure"));
+ }
+ // Get requested test from tile parameter
+ String param;
+
+ // Set a definition in this action
+ param = (String)context.getAttribute( "set-definition-name" );
+ if( param != null )
+ {
+ try
+ {
+ // Read definition from factory, but we can create it here.
+ ComponentDefinition definition = DefinitionsUtil.getDefinition( param, request, getServlet().getServletContext() );
+ //definition.putAttribute( "attributeName", "aValue" );
+ DefinitionsUtil.setActionDefinition( request, definition);
+ }
+ catch( FactoryNotFoundException ex )
+ {
+ request.setAttribute( "actionError", "Can't get definition factory.");
+ return (mapping.findForward("failure"));
+ }
+ catch( NoSuchDefinitionException ex )
+ {
+ request.setAttribute( "actionError", "Can't get definition '" + param +"'.");
+ return (mapping.findForward("failure"));
+ }
+ catch( DefinitionsFactoryException ex )
+ {
+ request.setAttribute( "actionError", "General error '" + ex.getMessage() +"'.");
+ return (mapping.findForward("failure"));
+ }
+ }
+
+ // Overload a parameter
+ param = (String)context.getAttribute( "set-attribute" );
+ if( param != null )
+ {
+ context.putAttribute( param, context.getAttribute( "set-attribute-value" ));
+ } // end if
+
+ return (mapping.findForward("success"));
+
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/TestTileController.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/TestTileController.java
new file mode 100644
index 0000000..352fc6a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/test/TestTileController.java
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.test;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.tiles.ComponentContext;
+import org.apache.struts.tiles.ControllerSupport;
+
+
+ /**
+ * Controller example.
+ * This controller modify title by adding "ok".
+ */
+public class TestTileController extends ControllerSupport
+{
+
+ public TestTileController()
+ {
+ }
+
+ /**
+ * Method associated to a tile and called when immediately before tile is included.
+ * @param tileContext Current tile context.
+ * @param request Current request
+ * @param response Current response
+ * @param servletContext Current servlet context
+ */
+ public void perform(ComponentContext tileContext,
+ HttpServletRequest request, HttpServletResponse response,
+ ServletContext servletContext)
+ throws ServletException, IOException
+ {
+ System.out.println( "Controller called" );
+
+
+ String title = (String)tileContext.getAttribute("title");
+ title += "- controller called";
+ tileContext.putAttribute( "title", title);
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/tutorial/ForwardExampleAction.java b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/tutorial/ForwardExampleAction.java
new file mode 100644
index 0000000..91b1b45
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/java/org/apache/struts/webapp/tiles/tutorial/ForwardExampleAction.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.webapp.tiles.tutorial;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+public class ForwardExampleAction extends Action {
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param actionForm The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception Exception if the application business logic throws
+ * an exception
+ */
+ public ActionForward execute(
+ ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+ String success = request.getParameter( "success" );
+ if( success != null )
+ return (mapping.findForward("success"));
+
+ return (mapping.findForward("failure"));
+ }
+
+ }
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-config.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-config.xml
new file mode 100644
index 0000000..9e50c8b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
+ "http://struts.apache.org/dtds/struts-config_1_2.dtd">
+<!--
+ This is the Struts configuration file for the
+ Tiles-documentation application
+-->
+
+
+<struts-config>
+
+ <!-- ========== Action Mapping Definitions =============================== -->
+ <action-mappings>
+
+ <!-- The standard administrative actions available with Tiles -->
+ <!-- These would be either omitted or protected by security constraints -->
+ <!-- in a real application deployment -->
+
+ <action path="/admin/tiles/reload"
+ type="org.apache.struts.tiles.actions.ReloadDefinitionsAction"/>
+ <action path="/admin/tiles/view"
+ type="org.apache.struts.tiles.actions.ViewDefinitionsAction"/>
+
+ </action-mappings>
+
+
+ <!-- ========== Request Processor Declaration =================== -->
+ <!-- The Tiles framework use a special request processor. YOU DON'T -->
+ <!-- NEED TO DECLARE IT yourself (The TilesPlugin do it for you), unless -->
+ <!-- you have created your own request processor. In this later case, -->
+ <!-- your request processor should extend the org.apache.struts.tiles.TilesRequestProcessor -->
+ <!-- and be declared here -->
+ <!-- <controller processorClass="your.RequestProcessor" /> -->
+
+ <!-- ========== Associated Messages Ressource settings =================== -->
+ <!-- Uncomment the following if your webserver complains about a missing resources. -->
+ <!-- This resource is not needed by Tiles or this example. It is just a trick to make -->
+ <!-- Struts happy with some web server. -->
+ <!-- <message-resources parameter="org.apache.struts.webapp.tiles.dev1-1.ApplicationResources" null="false" /> -->
+
+
+ <!-- ========== TilesPlugin settings ===================================== -->
+ <!-- You should declare this plugin if you want to use Tiles with an XML definition file. -->
+ <plug-in className="org.apache.struts.tiles.TilesPlugin" >
+
+ <!-- Path to XML definition file -->
+ <set-property property="definitions-config"
+ value="/WEB-INF/tiles-defs.xml" />
+ <!-- Set Module-awareness to true -->
+ <set-property property="moduleAware" value="true" />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-doc-config.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-doc-config.xml
new file mode 100644
index 0000000..69d56af
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-doc-config.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
+ "http://struts.apache.org/dtds/struts-config_1_2.dtd">
+<!--
+ This is the Struts configuration file for the example application,
+ using the proposed new syntax.
+
+ NOTE: You would only flesh out the details in the "form-bean"
+ declarations if you had a generator tool that used them to create
+ the corresponding Java classes for you. Otherwise, you would
+ need only the "form-bean" element itself, with the corresponding
+ "name" and "type" attributes.
+-->
+
+
+<struts-config>
+
+ <!-- ======================================================= -->
+ <!-- Tiles Documentation module -->
+ <!-- ======================================================= -->
+
+
+
+ <action-mappings/>
+
+
+ <!-- ========== Tiles plug-in setting settings =================== -->
+ <!-- Here we specified the tiles plug-in.
+ This plug-in register appropriate Request Processor -->
+ <!-- <controller processorClass="org.apache.struts.tiles.TilesRequestProcessor" /> -->
+
+ <!-- ========== Associated Messages Ressource settings =================== -->
+ <!-- Not used by tiles or this website, but needed due to a bug in actual Struts version -->
+ <message-resources parameter="org.apache.struts.webapp.tiles.dev1-1.ApplicationResources" null="false" />
+
+
+ <plug-in className="org.apache.struts.tiles.TilesPlugin" >
+ <set-property property="definitions-config"
+ value="/WEB-INF/tiles-defs.xml, /WEB-INF/tiles-doc-defs.xml" />
+ <set-property property="moduleAware" value="true" />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-examples-config.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-examples-config.xml
new file mode 100644
index 0000000..2843b81
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-examples-config.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
+ "http://struts.apache.org/dtds/struts-config_1_2.dtd">
+<!--
+ This is the Struts configuration file for the
+ Tiles-documentation "examples" application
+-->
+
+
+<struts-config>
+
+ <!-- ========== Form Bean Definitions ==================================== -->
+ <form-beans>
+
+ <!-- Logon form bean -->
+ <form-bean name="myPortalSettingsForm"
+ type="org.apache.struts.webapp.tiles.portal.PortalSettingsForm"/>
+ <!-- Menu settings form bean -->
+ <form-bean name="myMenuSettingsForm"
+ type="org.apache.struts.webapp.tiles.portal.MenuSettingsForm"/>
+ <!-- Skin settings form bean -->
+ <form-bean name="mySkinSettingsForm"
+ type="org.apache.struts.webapp.tiles.skin.LayoutSettingsForm"/>
+
+ </form-beans>
+
+
+ <!-- ========== Global Forward Definitions =============================== -->
+ <global-forwards>
+ <!-- Forward to error page -->
+ <forward name="failure" path="forward.example.failure.page"/>
+ </global-forwards>
+
+
+ <!-- ========== Action Mapping Definitions =============================== -->
+ <action-mappings>
+
+ <!-- ======================================================= -->
+ <!-- Examples Portal 1.1 actions -->
+ <!-- ======================================================= -->
+
+ <!-- Dynamic Portal user lists retrieving action -->
+ <action path="/myPortal"
+ type="org.apache.struts.webapp.tiles.portal.UserPortalAction">
+ </action>
+
+ <!-- Tiles Action associated to portal settings -->
+ <action path="/controller/myPortalSettings"
+ type="org.apache.struts.webapp.tiles.portal.UserPortalSettingsAction"
+ name="myPortalSettingsForm" >
+ </action>
+
+ <!-- Portal settings page entrance:
+ forward to appropriate page definition -->
+ <action path="/myPortalSettings"
+ type="org.apache.struts.actions.ForwardAction"
+ name="myPortalSettingsForm"
+ parameter="examples.portal.settings.page"/>
+
+ <!-- Tiles Action associated to Tile myMenuSettings -->
+ <action path="/controller/myMenuSettings"
+ type="org.apache.struts.webapp.tiles.portal.UserMenuSettingsAction"
+ name="myMenuSettingsForm" >
+ </action>
+
+ <!-- Menu Settings page entrance:
+ forward to appropriate page definition -->
+ <action path="/myMenuSettings"
+ type="org.apache.struts.actions.ForwardAction"
+ name="myMenuSettingsForm"
+ parameter="examples.userMenu.settings.page"/>
+
+ <!-- ======================================================= -->
+ <!-- Tiles 1.1 Skin Settings -->
+ <!-- ======================================================= -->
+
+ <!-- Skin Settings page entrance:
+ forward to appropriate page definition -->
+ <action path="/mySkinSettings"
+ type="org.apache.struts.actions.ForwardAction"
+ name="mySkinSettingsForm"
+ parameter="examples.skin.settings.page"/>
+
+ <action path="/controller/mySkinSettings"
+ type="org.apache.struts.webapp.tiles.skin.LayoutSettingsAction"
+ name="mySkinSettingsForm" >
+ </action>
+
+ <action path="/controller/layoutSwitch"
+ type="org.apache.struts.webapp.tiles.skin.LayoutSwitchAction" >
+ </action>
+
+ <!-- ======================================================= -->
+ <!-- Tiles 1.1 Rss Channel -->
+ <!-- ======================================================= -->
+ <action path="/controller/rssChannel"
+ type="org.apache.struts.webapp.tiles.rssChannel.RssChannelsAction">
+ </action>
+
+ <!-- ======================================================= -->
+ <!-- Test tabs with an action URL -->
+ <!-- ======================================================= -->
+ <action path="/tabs"
+ type="org.apache.struts.actions.ForwardAction"
+ parameter="examples.tabs.page"/>
+
+ </action-mappings>
+
+
+ <!-- ========== Request Processor Declaration =================== -->
+ <!-- The Tiles framework use a special request processor. YOU DON'T -->
+ <!-- NEED TO DECLARE IT yourself (The TilesPlugin do it for you), unless -->
+ <!-- you have created your own request processor. In this later case, -->
+ <!-- your request processor should extend the org.apache.struts.tiles.TilesRequestProcessor -->
+ <!-- and be declared here -->
+ <!-- <controller processorClass="your.RequestProcessor" /> -->
+
+ <!-- ========== Associated Messages Ressource settings =================== -->
+ <!-- Uncomment the following if your webserver complains about a missing resources. -->
+ <!-- This resource is not needed by Tiles or this example. It is just a trick to make -->
+ <!-- Struts happy with some web server. -->
+ <!-- <message-resources parameter="org.apache.struts.webapp.tiles.dev1-1.ApplicationResources" null="false" /> -->
+
+
+ <!-- ========== TilesPlugin settings ===================================== -->
+ <!-- You should declare this plugin if you want to use Tiles with an XML definition file. -->
+ <plug-in className="org.apache.struts.tiles.TilesPlugin" >
+ <!-- Path to XML definition files -->
+ <set-property property="definitions-config"
+ value="/WEB-INF/tiles-defs.xml,/WEB-INF/tiles-examples-defs.xml"/>
+ <!-- Set Module-awareness to true -->
+ <set-property property="moduleAware" value="true" />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-tests-config.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-tests-config.xml
new file mode 100644
index 0000000..5ec8e77
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-tests-config.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
+ "http://struts.apache.org/dtds/struts-config_1_2.dtd">
+<!--
+ This is the Struts configuration file for the example application,
+ using the proposed new syntax.
+
+ NOTE: You would only flesh out the details in the "form-bean"
+ declarations if you had a generator tool that used them to create
+ the corresponding Java classes for you. Otherwise, you would
+ need only the "form-bean" element itself, with the corresponding
+ "name" and "type" attributes.
+-->
+
+
+<struts-config>
+
+ <!-- ========== Action Mapping Definitions ============================== -->
+ <action-mappings>
+
+ <!-- Main page url entry.
+ This action is used to map an URL to an internal jsp.
+ A side effect is that the struts module is switched to the module
+ associated to this config file -->
+ <action path="/quickOverview"
+ type="org.apache.struts.actions.ForwardAction"
+ parameter="test.home.page"/>
+
+ <!-- ======================================================= -->
+ <!-- Test actions -->
+ <!-- ======================================================= -->
+
+ <!-- Test Struts action and Tiles integration -->
+ <action path="/testAction"
+ type="org.apache.struts.webapp.tiles.test.TestActionTileAction">
+ <forward name="success" path="test.struts.action"/>
+ <forward name="failure" path="test.struts.action.fail"/>
+ </action>
+
+ <!-- Test Struts Forwardintegration -->
+ <action path="/testForward"
+ type="org.apache.struts.webapp.tiles.test.TestActionTileAction"
+ forward="test.struts.action"/>
+
+ <!-- Test Struts action and Tiles integration -->
+ <action path="/testActionForwardJsp"
+ type="org.apache.struts.webapp.tiles.test.TestActionTileAction">
+ <forward name="success" path="/layout.jsp"/>
+ <forward name="failure" path="test.struts.action.fail"/>
+ </action>
+
+ <action path="/dispatch"
+ type="org.apache.struts.tiles.actions.DefinitionDispatcherAction"
+ parameter="def">
+ <forward name="success" path="anything" />
+ <forward name="error" path="anything" />
+ </action>
+
+ <!-- Test Struts action and Tiles integration -->
+ <action path="/showRequestURI"
+ type="org.apache.struts.webapp.tiles.test.NoForward">
+ <forward name="success" path="test.action.noforward"/>
+ </action>
+
+ <!-- The standard administrative actions available with Struts -->
+ <!-- These would be either omitted or protected by security -->
+ <!-- in a real application deployment -->
+ <action path="/admin/viewdef"
+ type="org.apache.struts.tiles.actions.ViewDefinitionsAction"/>
+ </action-mappings>
+
+
+ <!-- ========== Tiles plug-in setting settings =================== -->
+ <!-- Here we specified the tiles plug-in.
+ This plug-in register appropriate Request Processor -->
+ <!-- <controller processorClass="org.apache.struts.tiles.TilesRequestProcessor" /> -->
+
+ <!-- ========== Associated Messages Ressource settings =================== -->
+ <!-- Not used by tiles or this website, but needed due to a bug in actual Struts version -->
+ <message-resources parameter="org.apache.struts.webapp.tiles.dev1-1.ApplicationResources" null="false" />
+
+
+ <plug-in className="org.apache.struts.tiles.TilesPlugin" >
+ <set-property property="definitions-config"
+ value="/WEB-INF/tiles-defs.xml,
+ /WEB-INF/tiles-tests-defs.xml" />
+ <set-property property="moduleAware" value="true" />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-tutorial-config.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-tutorial-config.xml
new file mode 100644
index 0000000..7e7ed06
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/struts-tutorial-config.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!DOCTYPE struts-config PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
+ "http://struts.apache.org/dtds/struts-config_1_2.dtd">
+<!--
+ This is the Struts configuration file for the
+ Tiles-documentation "tutorial" application
+-->
+
+
+<struts-config>
+
+
+ <!-- ========== Form Bean Definitions ==================================== -->
+ <form-beans>
+
+ <!-- Logon form bean -->
+ <form-bean name="invoiceForm"
+ type="org.apache.struts.webapp.tiles.invoice.InvoiceForm"/>
+
+ <!-- Portal form bean -->
+ <form-bean name="portalPrefsForm"
+ type="org.apache.struts.webapp.tiles.dynPortal.PortalPrefsForm"/>
+ </form-beans>
+
+
+ <!-- ========== Global Forward Definitions =============================== -->
+ <global-forwards>
+ <!-- Forward to error page -->
+ <forward name="failure" path="forward.example.failure.page"/>
+ </global-forwards>
+
+
+ <!-- ========== Action Mapping Definitions =============================== -->
+ <action-mappings>
+
+ <!--
+ Main page URL entry.
+ This action is used to map an URL to an internal jsp.
+ A side effect is that the struts module is switched to the module
+ associated to this config file -->
+ <action path="/index"
+ type="org.apache.struts.actions.ForwardAction"
+ parameter="mainLayout"/>
+
+ <!-- Edit user registration -->
+ <action path="/forwardExampleAction"
+ type="org.apache.struts.webapp.tiles.tutorial.ForwardExampleAction">
+ <forward name="success" path="forward.example.success.page"/>
+ </action>
+
+ <!-- Edit invoice example -->
+ <action path="/lang"
+ type="org.apache.struts.webapp.tiles.lang.SelectLocaleAction">
+ <forward name="failure" path="/index.jsp"/>
+ <forward name="success" path="/index.jsp"/>
+ </action>
+
+ <!-- Dynamic template example -->
+ <action path="/dynTemplate"
+ type="org.apache.struts.webapp.tiles.template.DynTemplateAction">
+ <forward name="success" path="/dynFramesetPage.jsp"/>
+ </action>
+
+ <!-- Edit invoice example -->
+ <action path="/invoice/editInvoice"
+ type="org.apache.struts.webapp.tiles.invoice.EditInvoiceAction"
+ name="invoiceForm" >
+ <forward name="success" path="/invoice/index.jsp"/>
+ </action>
+
+ <!-- ======================================================= -->
+ <!-- Tutorial Dynamic portal actions -->
+ <!-- ======================================================= -->
+ <!-- Dynamic Portal user lists retrieving action -->
+ <action path="/actions/myPortal"
+ type="org.apache.struts.webapp.tiles.dynPortal.RetrievePortalAction">
+ <forward name="success" path="main.portal.body"/>
+ </action>
+
+ <!-- Dynamic Portal user lists set action:
+ -->
+ <action path="/actions/myPortalPrefs"
+ type="org.apache.struts.actions.ForwardAction"
+ name="portalPrefsForm"
+ parameter="myDynamicPortalPreferences"/>
+
+ <!-- Dynamic Portal user lists set tile-action -->
+ <action path="/actions/myPortalPrefs.tile"
+ type="org.apache.struts.webapp.tiles.dynPortal.SetPortalPrefsAction"
+ name="portalPrefsForm">
+ <forward name="preferences" path="/dynPortal/myPortalPrefTile.jsp"/>
+ <forward name="portal" path="dynamic.portal.body"/>
+ </action>
+
+ <!-- ======================================================= -->
+ <!-- Rss Channel -->
+ <!-- ======================================================= -->
+ <action path="/actions/rssChannel"
+ type="org.apache.struts.webapp.tiles.rssChannel.Channels">
+ <forward name="continue" path="/dynPortal/Channels.jsp"/>
+ <forward name="error" path="/dynPortal/Errors.jsp"/>
+ </action>
+
+ <!-- ======================================================= -->
+ <!-- test, to be removed -->
+ <!-- ======================================================= -->
+ <action path="/testAction"
+ type="org.apache.struts.webapp.tiles.lang.SelectLocaleAction">
+ <forward name="failure" path="/common/footer.jsp"/>
+ <forward name="success" path="/common/footer.jsp"/>
+ </action>
+
+ <action path="/testAction2"
+ type="org.apache.struts.webapp.tiles.tutorial.ForwardExampleAction">
+ <forward name="failure" path="forward.example.success.page"/>
+ <forward name="success" path="forward.example.success.page"/>
+ </action>
+
+ </action-mappings>
+
+ <!-- ========== Request Processor Declaration =================== -->
+ <!-- The Tiles framework use a special request processor. YOU DON'T -->
+ <!-- NEED TO DECLARE IT yourself (The TilesPlugin do it for you), unless -->
+ <!-- you have created your own request processor. In this later case, -->
+ <!-- your request processor should extend the org.apache.struts.tiles.TilesRequestProcessor -->
+ <!-- and be declared here -->
+ <!-- <controller processorClass="your.RequestProcessor" /> -->
+
+ <!-- ========== Associated Messages Ressource settings =================== -->
+ <!-- Uncomment the following if your webserver complains about a missing resources. -->
+ <!-- This resource is not needed by Tiles or this example. It is just a trick to make -->
+ <!-- Struts happy with some web server. -->
+ <!-- <message-resources parameter="org.apache.struts.webapp.tiles.dev1-1.ApplicationResources" null="false" /> -->
+
+
+ <!-- ========== TilesPlugin settings ===================================== -->
+ <!-- You should declare this plugin if you want to use Tiles with an XML definition file. -->
+ <plug-in className="org.apache.struts.tiles.TilesPlugin" >
+ <!-- Path to XML definition files -->
+ <set-property property="definitions-config"
+ value="/WEB-INF/tiles-defs.xml,
+ /WEB-INF/tiles-tutorial-defs.xml" />
+ <!-- Set Module-awareness to true -->
+ <set-property property="moduleAware" value="true" />
+ </plug-in>
+
+</struts-config>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-defs.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-defs.xml
new file mode 100644
index 0000000..8da5f98
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-defs.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
+ "http://struts.apache.org/dtds/tiles-config_1_1.dtd">
+
+<!--
+ Definitions for Tiles
+ This file contains definitions common to all Struts modules.
+ In particular, it contains the main layout and the common menus.
+ There is also the main page as a portal.
+-->
+
+<tiles-definitions>
+
+ <!-- ======================================================= -->
+ <!-- Master definition -->
+ <!-- ======================================================= -->
+
+ <!-- Doc index page description -->
+ <definition name="doc.mainLayout" path="/layout/classicLayout.jsp">
+ <put name="title" value="Tiles Library Documentation" />
+ <put name="header" value="/common/header.jsp" />
+ <put name="menu" value="doc.menu.main" />
+ <put name="footer" value="/common/footer.jsp" />
+ <put name="body" value="doc.portal.body" />
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Main page body definitions -->
+ <!-- ======================================================= -->
+
+ <definition name="doc.portal.body" path="/layout/columnsLayout.jsp">
+ <put name="numCols" value="2" />
+ <putList name="list0" >
+ <add value="/doc/portal/welcome.jsp" />
+ <add value="/doc/portal/features.jsp" />
+ <!--<add value="/doc/portal/todo.jsp" /> -->
+ <add value="/doc/portal/documentation.jsp" />
+ </putList>
+ <putList name="list1" >
+ <add value="/doc/portal/news.jsp" />
+ <add value="/doc/portal/download.jsp" />
+ <add value="/doc/portal/tilesCompsTemplates.jsp" />
+ <add value="/doc/portal/strutsIntegration.jsp" />
+ <add value="/doc/portal/comments.jsp" />
+ <add value="/doc/portal/revisions.jsp" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Menus definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Menu bar definition -->
+<definition name="doc.menu.main" path="/layouts/vboxLayout.jsp" >
+ <putList name="list" >
+ <add value="common.menu.home" />
+ <add value="common.menu.examples" />
+ <add value="common.menu.doc" />
+ <!-- <add value="common.menu.printer.friendly" /> -->
+ </putList>
+</definition>
+
+ <!-- The home menu definition -->
+<definition name="common.menu.home" path="/layouts/menu.jsp" >
+ <put name="title" value="Tiles" />
+ <putList name="items" >
+ <item value="Tiles Home" link="/index.jsp" />
+ </putList>
+</definition>
+
+ <!-- Printer friendly menu definition -->
+<definition name="common.menu.examples" path="/layouts/menu.jsp" >
+ <put name="title" value="Examples" />
+ <putList name="items" >
+ <item value="Home" link="/examples/index.jsp" />
+ </putList>
+</definition>
+
+ <!-- Documentation menu definition v1.1-->
+<definition name="common.menu.doc" path="/layouts/menu.jsp" >
+ <put name="title" value="Documentation" />
+ <putList name="items" >
+ <item value="Home" link="/doc/index.jsp" />
+ <item value="Live Examples" link="/examples/index.jsp" />
+ <item value="Quick overview" link="/test/quickOverview.jsp" />
+ <!--
+ <item value="Tutorial" link="/doc/tutorial.jsp" />
+ -->
+ <item value="Tutorial Live Examples" link="/tutorial/index.jsp" />
+ <!--
+ <item value="Tiles Tags" link="/doc/tilesTags.jsp" />
+ <item value="Download" link="/doc/download.jsp" />
+ <item value="Installation" link="/doc/installation.jsp" />
+ <item value="User Guide" link="/doc/userGuide.jsp" />
+ <item value="Javadoc" link="/api/index.html" />
+ <item value="Struts Home" link="http://www.apache.org"
+ icon="/images/struts-power.gif" />
+ -->
+ </putList>
+</definition>
+
+ <!-- Printer friendly menu definition -->
+<definition name="common.menu.printer.friendly" path="/layouts/menu.jsp" >
+ <put name="title" value="Printer Versions" />
+ <putList name="items" >
+ <item value="Quick Overview" link="/test/testAll.jsp" />
+ <item value="Tutorial" link="/doc/tutorialBody.html" />
+ <item value="User Guide" link="/doc/userGuideBody.html" />
+ <item value="Overview (old)" link="/doc/overviewBody.html" />
+ </putList>
+</definition>
+
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-doc-defs.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-doc-defs.xml
new file mode 100644
index 0000000..cb1a5ef
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-doc-defs.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
+ "http://struts.apache.org/dtds/tiles-config_1_1.dtd">
+
+<!-- Definitions for Tiles documentation -->
+
+<tiles-definitions>
+
+ <!-- ======================================================= -->
+ <!-- Master definition -->
+ <!-- ======================================================= -->
+
+ <!-- Doc index page description -->
+ <definition name="doc.mainLayout" path="/layout/classicLayout.jsp">
+ <put name="title" value="Tiles Library Documentation" />
+ <put name="header" value="/common/header.jsp" />
+ <put name="menu" value="doc.menu.main" />
+ <put name="footer" value="/common/footer.jsp" />
+ <put name="body" value="doc.portal.body" />
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Main page body definitions -->
+ <!-- ======================================================= -->
+
+ <definition name="doc.portal.body" path="/layout/columnsLayout.jsp">
+ <put name="numCols" value="2" />
+ <putList name="list0" >
+ <add value="/doc/portal/welcome.jsp" />
+ <add value="/doc/portal/features.jsp" />
+ <!--<add value="/doc/portal/todo.jsp" /> -->
+ <add value="/doc/portal/documentation.jsp" />
+ </putList>
+ <putList name="list1" >
+ <add value="/doc/portal/news.jsp" />
+ <add value="/doc/portal/download.jsp" />
+ <add value="/doc/portal/tilesCompsTemplates.jsp" />
+ <add value="/doc/portal/strutsIntegration.jsp" />
+ <add value="/doc/portal/comments.jsp" />
+ <add value="/doc/portal/revisions.jsp" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Menus definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Menu bar definition -->
+<definition name="doc.menu.main" path="/layout/vboxLayout.jsp" >
+ <putList name="componentsList" >
+ <add value="doc.menu.links" />
+ <add value="doc.menu.taglib.references" />
+ <add value="doc.menu.printer.friendly" />
+ <add value="doc.menu.old.documents" />
+ </putList>
+</definition>
+
+ <!-- Documentation menu definition v1.1-->
+<definition name="doc.menu.links" path="/layouts/menu.jsp" >
+ <put name="title" value="Documentation" />
+ <putList name="items" >
+ <item value="Home" link="/index.jsp" />
+ <item value="Live Examples (new)" link="/examples/index.jsp" />
+ <!--
+ <item> <value>Commented Examples</value>
+ <link>/examples/index.jsp</link>
+ <classtype>org.apache.struts.tiles.beans.SimpleMenuItem</classtype>
+ </item>
+ -->
+ <item value="Quick overview" link="/doc/quickOverview.jsp" />
+ <!--
+ <item value="Tutorial" link="/doc/tutorial.jsp" />
+ -->
+ <item value="Tutorial Live Examples" link="/tutorial/index.jsp" />
+ <item value="Download" link="/doc/download.jsp" />
+ <item value="Installation" link="/doc/installation.jsp" />
+ <item value="User Guide" link="/doc/userGuide.jsp" />
+ <item value="Javadoc" link="/api/index.html" />
+ <item value="Struts Home" link="http://www.apache.org" icon="/images/struts-power.gif"
+ classtype="org.apache.struts.tiles.beans.SimpleMenuItem" />
+ </putList>
+</definition>
+
+ <!-- Printer friendly menu definition -->
+<definition name="doc.menu.printer.friendly" path="/layouts/menu.jsp" >
+ <put name="title" value="Printer Versions" />
+ <putList name="items" >
+ <item value="Quick Overview" link="/test/testAll.jsp" />
+ <item value="Tutorial" link="/doc/tutorialBody.html" />
+ <item value="User Guide" link="/doc/userGuideBody.html" />
+ <item value="Overview (old)" link="/doc/overviewBody.html" />
+ </putList>
+</definition>
+
+ <!-- Taglib menu definition -->
+<definition name="doc.menu.taglib.references" path="/layouts/menu.jsp" >
+ <put name="title" value="Tag Library Reference" />
+ <putList name="items" >
+ <item value="Tiles Tags" link="/doc/tilesTags.jsp" />
+ <!-- <item value="Extension Tags (old)" link="/doc/extensionsTags.jsp" /> -->
+ </putList>
+</definition>
+
+ <!-- Oldies menu definition -->
+<definition name="doc.menu.old.documents" path="/layouts/menu.jsp" >
+ <put name="title" value="Old Documents" />
+ <putList name="items" >
+ <item value="Overview (old)" link="/doc/overview.jsp" />
+ </putList>
+</definition>
+
+
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-examples-defs.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-examples-defs.xml
new file mode 100644
index 0000000..2f35935
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-examples-defs.xml
@@ -0,0 +1,405 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
+ "http://struts.apache.org/dtds/tiles-config_1_1.dtd">
+
+<!-- Tiles definitions -->
+
+<tiles-definitions>
+
+ <!-- ======================================================= -->
+ <!-- Master layout -->
+ <!-- ======================================================= -->
+
+ <!-- Master layout and default tiles used by all pages -->
+ <definition name="examples.masterPage" path="/layouts/classicLayout.jsp">
+ <put name="title" value="Tiles 1.1 Examples" />
+ <put name="header" value="/examples/tiles/header.jsp" />
+ <put name="menu" value="examples.menu.bar" />
+ <put name="footer" value="/examples/tiles/footer.jsp" />
+ <put name="body" value="/examples/tiles/body.jsp" />
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Test complex definition construct -->
+ <!-- These definitions are not intended to be used. -->
+ <!-- They are included to stretch the Digester rules. -->
+ <!-- ======================================================= -->
+
+ <!-- Test nested list -->
+<definition name="test.nested.list" path="/layouts/vboxLayout.jsp" >
+ <putList name="list" >
+ <item value="item1" link="/examples/tabs.jsp"/>
+ <item value="item2" link="/examples/tabs.jsp"/>
+ <item value="item3" link="/examples/tabs.jsp"/>
+ <bean classtype="org.apache.struts.tiles.beans.SimpleMenuItem">
+ <set-property property="link" value="aLink1"/>
+ <set-property property="value" value="aValue1"/>
+ </bean>
+ <putList name="list" >
+ <item value="nested.item1" link="/examples/tabs.jsp"/>
+ <putList name="list" >
+ <item value="nested.nested.item1" link="/examples/tabs.jsp"/>
+ <item value="nested.nested.item2" link="/examples/tabs.jsp"/>
+ </putList>
+ <item value="nested.item2" link="/examples/tabs.jsp"/>
+ </putList>
+ </putList>
+</definition>
+
+ <!-- ======================================================= -->
+ <!-- Menu bar and submenus definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Menu bar definition -->
+ <!-- Some definitions come from other definition files (ex : doc.menu.*) -->
+<definition name="examples.menu.bar" path="/layouts/vboxLayout.jsp" >
+ <putList name="list" >
+ <add value="common.menu.home" />
+ <add value="examples.userMenu" />
+ <add value="examples.menu.links" />
+ <add value="common.menu.doc" />
+ <add value="examples.menu.settings" />
+ <add value="examples.menu.admin" />
+ </putList>
+</definition>
+
+ <!--
+ Menus common ancestor definition
+ This definition is used as common ancestor for menu definitions.
+ It allows to define common attributes in one place.
+ Actually, it only defines the layout used to render menus.
+ -->
+<definition name="examples.menu.root" path="/layouts/menu.jsp" >
+</definition>
+
+ <!--
+ User menu definition
+ This menu is customizable by user.
+ Definition only contains default items.
+ -->
+<definition name="examples.userMenu" extends="examples.menu.root"
+ controllerClass="org.apache.struts.webapp.tiles.portal.UserMenuAction" >
+ <put name="catalogSettings" value="examples.myMenu.catalog.settings"/>
+ <put name="catalogName" value="examples.portal.menuCatalog"/>
+ <put name="title" value="My Menu" />
+ <putList name="items" >
+ <item value="customize" link="/examples/myMenuSettings.jsp" />
+ </putList>
+</definition>
+
+ <!--
+ Menu bar definition used by customizable menu catalog
+ This definition declares available items in the user menu catalog.
+ -->
+<definition name="examples.myMenu.catalog.settings" >
+ <putList name="list" >
+ <add value="examples.userMenu" />
+ <add value="examples.menu.links" />
+ <add value="examples.menu.settings" />
+ <add value="examples.menu.admin" />
+ </putList>
+</definition>
+
+ <!-- Examples main menu definition -->
+<definition name="examples.menu.links" extends="examples.menu.root" >
+ <put name="title" value="Examples" />
+ <putList name="items" >
+ <item value="Examples Home" link="/examples/index.jsp" />
+ <item value="Portal" link="/examples/portal.jsp" />
+ <item value="my Portal" link="/examples/myPortal.jsp" />
+ <item value="my Portal Settings" link="/examples/myPortalSettings.jsp" />
+ <item value="my Menu Settings" link="/examples/myMenuSettings.jsp" />
+ <item value="Tabs (choosen pages)" link="/examples/tabs.jsp"/>
+ <item value="Tabs (Summaries)" link="/examples/summariesTabs.jsp" />
+ <item value="Rss Channels" link="/examples/rssChannels.jsp"/>
+ </putList>
+</definition>
+
+ <!-- Preferences menu definition -->
+<definition name="examples.menu.settings" extends="examples.menu.root" >
+ <put name="title" value="Preferences" />
+ <putList name="items" >
+ <item value="my Portal Settings" link="/examples/myPortalSettings.jsp"/>
+ <item value="my Menu Settings" link="/examples/myMenuSettings.jsp" />
+ <item value="my Layout Settings" link="/examples/skinSettings.jsp" />
+ </putList>
+</definition>
+
+ <!-- admin menu definition -->
+<definition name="examples.menu.admin" extends="examples.menu.root" >
+ <put name="title" value="Admin" />
+ <putList name="items" >
+ <item value="Reload" link="/admin/tiles/reload.do" />
+ </putList>
+</definition>
+
+ <!-- ======================================================= -->
+ <!-- Index portal page definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Index page -->
+ <definition name="examples.index.page" extends="examples.masterPage">
+ <put name="title" value="Tiles 1.1 Example Summaries" />
+ <put name="body" value="examples.index.portal.body" />
+ </definition>
+
+ <!-- Portal Body declaration-->
+ <definition name="examples.index.portal.body" path="/layouts/columnsLayout.jsp" >
+ <put name="numCols" value="2" />
+ <putList name="list0" >
+ <add value="/examples/tiles/portalSummary.jsp" />
+ <add value="/examples/tiles/myPortalSummary.jsp" />
+ <add value="/examples/tiles/rssChannelsSummary.jsp" />
+ <add value="/examples/tiles/myLayoutSummary.jsp" />
+ <add value="/examples/tiles/adminSummary.jsp" />
+ <add value="/examples/tiles/componentsSummary.jsp" />
+ </putList>
+ <putList name="list1" >
+ <add value="/examples/tiles/menuSummary.jsp" />
+ <add value="/examples/tiles/myMenuSummary.jsp" />
+ <add value="/examples/tiles/tabsSummary.jsp" />
+ <add value="/examples/tiles/i18nSummary.jsp" />
+ <add value="/examples/tiles/multiChannelsSummary.jsp" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Portal page definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Portal page -->
+ <definition name="examples.portal.page" extends="examples.masterPage">
+ <put name="title" value="Tiles 1.1 Portal" />
+ <put name="body" value="examples.portal.body" />
+ </definition>
+
+ <!-- Portal Body declaration-->
+ <definition name="examples.portal.body" path="/layouts/columnsLayout.jsp"
+ controllerUrl="/examples/myPortal.do" >
+ <put name="numCols" value="2" />
+ <putList name="list0" >
+ <add value="/examples/tiles/portal/login.jsp" />
+ <add value="/examples/tiles/portal/messages.jsp" />
+ <add value="/examples/tiles/portal/newsFeed.jsp" />
+ <!--<add value="examples.menu.bar" />-->
+
+ </putList>
+ <putList name="list1" >
+ <add value="/examples/tiles/portal/advert3.jsp" />
+ <add value="/examples/tiles/portal/stocks.jsp" />
+ <add value="/examples/tiles/portal/whatsNew.jsp" />
+ <add value="/examples/tiles/portal/advert2.jsp" />
+ </putList>
+ <!-- labels used by catalog [optional]-->
+ <putList name="labels0" >
+ <add value="Login" />
+ <add value="Your Messages" />
+ <add value="News Feed" />
+ <!--<add value="Menu Bar" />-->
+ </putList>
+ <putList name="labels1" >
+ <add value="Advert 3" />
+ <add value="Stock" />
+ <add value="What's new" />
+ <add value="Advert 2" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Portal settings page definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Portal settings page -->
+ <definition name="examples.portal.settings.page" extends="examples.masterPage">
+ <put name="title" value="Tiles 1.1 Portal Settings" />
+ <put name="body" value="examples.portal.settings.body" />
+ </definition>
+
+ <!-- Portal settings Body declaration-->
+ <!-- Extends portal body to provide the same default set of tiles -->
+ <definition name="examples.portal.settings.body"
+ path="/examples/tiles/myPortalSettings.jsp"
+ extends="examples.portal.body"
+ controllerUrl="/examples/controller/myPortalSettings.do" >
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Menu settings page definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Portal settings page -->
+ <definition name="examples.userMenu.settings.page" extends="examples.masterPage">
+ <put name="title" value="Tiles 1.1 My Menu Settings" />
+ <put name="body" value="examples.userMenu.settings.body" />
+ </definition>
+
+ <!-- Portal settings Body declaration-->
+ <!-- Extends user menu body to provide the same default parameters -->
+ <definition name="examples.userMenu.settings.body"
+ path="/examples/tiles/myMenuSettings.jsp"
+ extends="examples.userMenu"
+ controllerUrl="/examples/controller/myMenuSettings.do" >
+ <putList name="defaultChoice" >
+ <add value="examples.userMenu" />
+ <add value="portal.menu.links" />
+ <add value="portal.menu.preferences" />
+ <add value="doc.menu.taglib.references" />
+ <add value="doc.menu.printer.friendly" />
+ <add value="doc.menu.old.documents" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Tabs test page and definitions -->
+ <!-- ======================================================= -->
+
+ <!-- tabs page -->
+ <definition name="examples.tabs.page" extends="examples.masterPage">
+ <put name="title" value="Tiles 1.1 Tabs layout example" />
+ <put name="body" value="examples.tabs.body" />
+ </definition>
+
+ <!-- body using tabs -->
+ <definition name="examples.tabs.body" path="/layouts/tabsLayout.jsp" >
+ <put name="selectedIndex" value="0" />
+ <put name="parameterName" value="selected" />
+ <putList name="tabList" >
+ <item value="Doc Home" link="/index.jsp" />
+ <item value="Quick overview" link="/test/quickOverview.do" />
+ <!-- <item value="Tutorial" link="/doc/tutorial.jsp" /> -->
+ <item value="Examples Home" link="/examples/index.jsp" />
+ <item value="Tutorial Home" link="/tutorial/index.do" />
+ <item value="Login" link="/examples/tiles/portal/login.jsp" />
+ <item value="Messages" link="/examples/tiles/portal/messages.jsp" />
+ <item value="NewsFeed" link="/examples/tiles/portal/newsFeed.jsp" />
+ <item value="Stocks" link="/examples/tiles/portal/stocks.jsp" />
+ <item value="WhatsNew" link="/examples/tiles/portal/whatsNew.jsp" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Summaries in tabs -->
+ <!-- ======================================================= -->
+
+ <!-- tabs page -->
+ <definition name="examples.tabs.summaries.page" extends="examples.masterPage">
+ <put name="title" value="Tiles 1.1 Summaries in Tabs" />
+ <put name="body" value="examples.tabs.summaries.body" />
+ </definition>
+
+ <!-- body using tabs -->
+ <definition name="examples.tabs.summaries.body" path="/layouts/tabsLayout.jsp" >
+ <put name="selectedIndex" value="0" />
+ <put name="parameterName" value="selected" />
+ <putList name="tabList" >
+ <item value="Portal" link="/examples/tiles/portalSummary.jsp" />
+ <item value="my Portal" link="/examples/tiles/myPortalSummary.jsp"/>
+ <item value="Menu" link="/examples/tiles/menuSummary.jsp"/>
+ <item value="my Menu" link="/examples/tiles/myMenuSummary.jsp" />
+ <item value="Tabs" link="/examples/tiles/tabsSummary.jsp" />
+ <item value="Rss Channels" link="/examples/tiles/rssChannelsSummary.jsp" />
+ <item value="Admin" link="/examples/tiles/adminSummary.jsp" />
+ <item value="i18n" link="/examples/tiles/i18nSummary.jsp" />
+ <item value="Multi Channels" link="/examples/tiles/multiChannelsSummary.jsp" />
+ <item value="Components" link="/examples/tiles/componentsSummary.jsp" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Rss Channel definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Rss main page -->
+ <definition name="examples.rssChannels.page" extends="examples.masterPage">
+ <put name="title" value="Tiles 1.1 Rss Channels" />
+ <put name="body" value="examples.rssChannel.offline.body" />
+ </definition>
+
+ <!-- Rss channel body declaration-->
+ <!-- Example to use when connected (online)-->
+ <definition name="examples.rssChannel.body"
+ path="/examples/tiles/rssChannels.jsp"
+ controllerUrl="/examples/controller/rssChannel.do" >
+ <putList name="urls" >
+ <!--<add value="http://www.newsforge.com/newsforge.rss" /> -->
+ <add value="http://xmlhack.com/rss.php" />
+ <add value="http://lwn.net/headlines/rss" />
+ </putList>
+ </definition>
+
+ <!-- Rss channel body declaration-->
+ <!-- Example whith local feeds (offline)-->
+ <definition name="examples.rssChannel.offline.body"
+ path="/examples/tiles/rssChannels.jsp"
+ controllerUrl="/examples/controller/rssChannel.do" >
+ <putList name="urls" >
+ <add value="/examples/rssFeed/rss-example.xml" />
+ <add value="/examples/rssFeed/apacheweek-headlines.xml" />
+ </putList>
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Skin Settings definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Skin main page -->
+ <definition name="examples.skin.settings.page" extends="examples.customizable.layouts.root">
+ <put name="title" value="Tiles 1.1 Skin Setting" />
+ <put name="body" value="examples.skin.settings.body" />
+ </definition>
+
+ <!-- Skin body declaration-->
+ <definition name="examples.skin.settings.body"
+ path="/examples/tiles/mySkinSettings.jsp"
+ controllerUrl="/examples/controller/mySkinSettings.do" >
+ <put name="userSettingsName" value="tiles.examples.skin.user.settings" />
+ <!--<put name="catalogName" value="tiles.examples.skin.catalog" />-->
+ <put name="catalogSettings" value="examples.available.skins" />
+ </definition>
+
+ <!-- ======================================================= -->
+ <!-- Skins Definitions -->
+ <!-- ======================================================= -->
+
+
+ <!--
+ This definition is used as common ancestor for customible layouts definitions.
+ It allows to define common attributes in one place.
+ Actually, it defines names used by layout controller.
+ -->
+ <definition name="examples.customizable.layouts.root"
+ extends="examples.masterPage"
+ path="/examples/controller/layoutSwitch.do" >
+ <put name="userSettingsName" value="tiles.examples.skin.user.settings" />
+ <!--<put name="catalogName" value="tiles.examples.skin.catalog" />-->
+ <put name="catalogSettings" value="examples.available.skins" />
+ <put name="layout.attribute" value="page.layout" />
+ </definition>
+
+ <!-- Available skins -->
+ <definition name="examples.available.skins" >
+ <putList name="skin.list" >
+ <add value="examples.default.skin" />
+ <add value="examples.menuleft.skin" />
+ </putList>
+ </definition>
+
+ <!-- Default skin values -->
+ <definition name="examples.default.skin" >
+ <put name="skin.label" value="Default" />
+ <put name="page.layout" value="/layouts/classicLayout.jsp" />
+ <put name="menu.layout" value="/layouts/menu.jsp" />
+ <put name="menuBar.layout" value="/layouts/vboxLayout.jsp" />
+ </definition>
+
+ <!-- Default skin values -->
+ <definition name="examples.menuleft.skin" extends="examples.default.skin" >
+ <put name="skin.label" value="Left Menu" />
+ <put name="page.layout" value="/layouts/skin1/menuLeftLayout.jsp" />
+ <put name="menu.layout" value="/layouts/menu.jsp" />
+ </definition>
+
+
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tests-defs.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tests-defs.xml
new file mode 100644
index 0000000..3bf0431
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tests-defs.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
+ "http://struts.apache.org/dtds/tiles-config_1_1.dtd">
+
+<!-- Definitions for Tiles quick tests -->
+
+<tiles-definitions>
+
+ <!-- Test instances -->
+<definition name="test.home.page" extends="doc.mainLayout" >
+ <put name="title" value="Tiles: test page" />
+ <put name="body" value="/test/testAll.jsp" />
+</definition>
+
+ <!-- Test menu definition -->
+<definition name="test.menu.links" path="/layouts/menu.jsp" >
+ <put name="title" value="Tests" />
+ <putList name="items" >
+ <item value="All in one" link="/test/index.jsp" />
+ <item value="Basic" link="/test/testBasic.jsp" />
+ <item value="Ignore attribute" link="/test/testIgnore.jsp" />
+ <item value="Definition" link="/test/testDefinitions.jsp" />
+ <item value="Role" link="/test/testRole.jsp" />
+ <item value="Struts action" link="/test/testStrutsAction.jsp" />
+ <item value="Controller" link="/test/testController.jsp" />
+ </putList>
+</definition>
+
+ <!-- Test instances -->
+<definition name="test.layout.test1" path="/test/layout.jsp" >
+ <put name="title" value="Test definition from factory : basic" />
+ <put name="header" value="header.jsp" />
+ <put name="body" value="body.jsp" />
+</definition>
+
+ <!-- Test instances -->
+<definition name="test.layout.test2" path="/test/layout.jsp" >
+ <put name="title" value="Test definition from factory : specify types" type="string" />
+ <put name="header" value="header.jsp" type="page" />
+ <put name="body" value="body.jsp" type="page" />
+</definition>
+
+ <!-- Test instances -->
+<definition name="test.layout.test3" path="/test/layout.jsp" >
+ <put name="title" value="Test definition from factory : Test with a tag body (to do)" />
+ <put name="header" value="This is a header" direct="true"/>
+ <put name="body" value="body.jsp"/>
+</definition>
+
+ <!-- Test backward compatibility -->
+<definition name="test.layout.test4" path="/test/layout.jsp" >
+ <put name="title" value="Test definition from factory: backward compatibility"
+ direct="true"/>
+ <put name="header" value="header.jsp"/>
+ <put name="body" value="body.jsp" direct="false" />
+</definition>
+
+ <!-- Test Struts Action and Tiles integration -->
+<definition name="test.struts.action" path="/test/layout.jsp" >
+ <put name="title" value="Test Struts Action and Tiles integration: default title"
+ direct="true"/>
+ <put name="header" value="header.jsp"/>
+ <put name="body" value="body.jsp" direct="false" />
+</definition>
+
+ <!-- Test Struts Action and Tiles integration -->
+<definition name="test.struts.action.fail" path="/test/failpage.jsp" >
+ <put name="title" value="Test fail" direct="true" />
+</definition>
+
+ <!-- Test Tiles Controller -->
+ <definition name="test.struts.controller"
+ path="/test/layout.jsp"
+ controllerClass="org.apache.struts.webapp.tiles.test.TestTileController" >
+ <put name="title" value="Test Tile Controller : call to Controller" />
+ <put name="header" value="header.jsp"/>
+ <put name="body" value="body.jsp" />
+</definition>
+
+ <!-- Test body for put tag -->
+<definition name="test.body" path="/test/failpage.jsp" >
+ <put name="title" direct="true">first body : title</put>
+ <put name="body" direct="true">second body : body</put>
+</definition>
+
+ <!-- Test instances -->
+<definition name="test.action.noforward" path="/test/layout.jsp" >
+ <put name="title" value="Test Action with No Forward" />
+ <put name="header" value="header.jsp" />
+ <put name="body" value="showRequestUri.jsp" />
+</definition>
+
+
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs.xml
new file mode 100644
index 0000000..21b6d5f
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs.xml
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
+ "http://struts.apache.org/dtds/tiles-config_1_1.dtd">
+
+<!-- Definitions for Tiles tutorial -->
+
+<tiles-definitions>
+
+ <!-- Definition description -->
+ <definition name="myFirstDefinition" path="/tutorial/layout/classicLayout.jsp">
+ <put name="title" value="My First Definition Page" />
+ <!-- <put name="title" >My First Definition Page</put> -->
+ <put name="header" value="/tutorial/common/header.jsp" />
+ <put name="footer" value="/tutorial/common/footer.jsp" />
+ <put name="menu" value="/tutorial/common/menu.jsp" />
+ <put name="body" value="/tutorial/basic/helloBody.jsp" />
+ </definition>
+
+ <!-- Main Layout Definition description -->
+ <definition name="mainLayout" path="/tutorial/layout/classicLayout.jsp">
+ <put name="title" value="World Financial Online" />
+ <put name="header" value="/tutorial/common/header.jsp" />
+ <put name="footer" value="/tutorial/common/footer.jsp" />
+ <put name="menu" value="menu.main" />
+ <put name="body" value="main.portal.body" />
+ </definition>
+
+ <!-- Portal Body declaration-->
+ <definition name="main.portal.body" path="/layout/columnsLayout.jsp">
+ <put name="numCols" value="2" />
+ <putList name="list0" >
+ <add value="/tutorial/portal/login.jsp" />
+ <add value="/tutorial/portal/messages.jsp" />
+ <add value="/tutorial/portal/newsFeed.jsp" />
+ <add value="/tutorial/portal/advert2.jsp" />
+ </putList>
+ <putList name="list1" >
+ <add value="/tutorial/portal/advert3.jsp" />
+ <add value="/tutorial/portal/stocks.jsp" />
+ <add value="/tutorial/portal/whatsNew.jsp" />
+ <add value="/tutorial/portal/personalLinks.jsp" />
+ <add value="/tutorial/portal/search.jsp" />
+ </putList>
+ </definition>
+
+ <!-- Main menu definition -->
+<definition name="menu.main" path="/layout/vboxLayout.jsp" >
+ <putList name="componentsList" >
+ <add value="menu.logo" />
+ <add value="menu.documentation" />
+ <add value="menu.links" />
+ <add value="menu.lang" />
+ <add value="menu.src" />
+ </putList>
+</definition>
+
+ <!-- menu logo definition -->
+<definition name="menu.logo" path="/tutorial/common/menu/menuLogo.jsp" />
+
+ <!-- Documentation menu -->
+ <!-- Old style menu. Check module 'examples' for new style -->
+<definition name="menu.documentation" path="/common/submenu.jsp" >
+ <put name="title" value="Tiles" />
+ <putList name="items" >
+ <add value="Home" />
+ </putList>
+ <putList name="links" >
+ <add value="/index.jsp" />
+ </putList>
+</definition>
+
+ <!-- menu logo definition -->
+<definition name="menu.links" path="/common/submenu.jsp" >
+ <put name="title" value="Tutorial" />
+ <putList name="items" >
+ <add value="Home" />
+ <add value="Basic Page" />
+ <add value="First Portal" />
+ <add value="First Definition" />
+ <add value="Overloaded Definition" />
+ <add value="Extended Definition" />
+ <add value="Dynamic Portal" />
+ <add value="Dynamic Portal Prefs" />
+ <add value="Struts Forward" />
+ <add value="Definition Tag" />
+ <add value="Extended Definition Tag" />
+ <add value="Dynamic Definition" />
+ <add value="Frame Example" />
+ <add value="Invoice" />
+ </putList>
+ <putList name="links" >
+ <add value="/tutorial/index.jsp" />
+ <add value="/tutorial/basicPage.jsp" />
+ <add value="/tutorial/portalPage.jsp" />
+ <add value="/tutorial/firstDefinition.jsp" />
+ <add value="/tutorial/overloadDefinitionParameters.jsp" />
+ <add value="/tutorial/extendedDefinition.jsp" />
+ <add value="/tutorial/dynPortal/index.jsp" />
+ <add value="/tutorial/dynPortal/myPortalPrefs.jsp" />
+ <add value="/tutorial/strutsForward.jsp" />
+ <add value="/tutorial/definitionTag.jsp" />
+ <add value="/tutorial/extendedDefinitionTag.jsp" />
+ <add value="/tutorial/dynTemplate.do" />
+ <add value="/tutorial/basicFramesetPage.jsp" />
+ <add value="/tutorial/invoice/index.jsp" />
+ </putList>
+</definition>
+
+ <!-- Menu sources definition -->
+<definition name="menu.src" path="/tutorial/common/menuViewSrc.jsp" >
+ <putList name="list" >
+ <add value="/tutorial/index.jsp" />
+ <add value="/tutorial/basicPage.jsp" />
+ <add value="/tutorial/portalPage.jsp" />
+ <add value="/tutorial/firstDefinition.jsp" />
+ <add value="/tutorial/overloadDefinitionParameters.jsp" />
+ <add value="/tutorial/extendedDefinition.jsp" />
+ <add value="/tutorial/definitionTag.jsp" />
+ <add value="/tutorial/extendedDefinitionTag.jsp" />
+ <add value="/tutorial/basicFramesetPage.jsp" />
+ <add value="/tutorial/WEB-INF/templateDefinitions.xml" />
+
+ <add value="/tutorial/basic/myLayout.jsp" />
+ <add value="/tutorial/basic/hello.jsp" />
+ <add value="/tutorial/basic/menu.jsp" />
+ <add value="/tutorial/portal/portalBody.jsp" />
+
+ <add value="/tutorial/common/footer.jsp" />
+ <add value="/tutorial/common/menu.jsp" />
+ <add value="/tutorial/common/submenu.jsp" />
+ <add value="/tutorial/common/menuViewSrc.jsp" />
+ <add value="/tutorial/common/viewSrc.jsp" />
+ <add value="/tutorial/common/viewSrcBody.jsp" />
+
+ <add value="/tutorial/common/menu/menuLogo.jsp" />
+ <add value="/tutorial/common/menu/menuLinks.jsp" />
+ <add value="/tutorial/common/menu/menuSrc.jsp" />
+
+ <add value="/tutorial/layout/classicLayout.jsp" />
+ <add value="/tutorial/layout/columnsLayout.jsp" />
+ <add value="/tutorial/layout/vboxLayout.jsp" />
+
+ <add value="/tutorial/invoice/editAddress.jsp" />
+ <add value="/tutorial/invoice/editInvoice.jsp" />
+ <add value="/tutorial/invoice/index.jsp" />
+ </putList>
+</definition>
+
+ <!-- select language menu -->
+<definition name="menu.lang" path="/common/submenu.jsp" >
+ <put name="title" value="Language" />
+ <putList name="items" >
+ <add value="Français" />
+ <add value="English" />
+ <add value="Deutsch" />
+ </putList>
+ <putList name="links" >
+ <add value="/tutorial/lang.do?language=FR" />
+ <add value="/tutorial/lang.do?language=UK" />
+ <add value="/tutorial/lang.do?language=DE" />
+ </putList>
+</definition>
+
+ <!-- Extended definition example -->
+<definition name="extended.definition.example" extends="mainLayout" >
+ <put name="title" value="Extended Definition" />
+ <put name="body" value="/tutorial/portal/newsFeed.jsp" />
+</definition>
+
+ <!-- Struts forward definition example -->
+<definition name="forward.example.choice.page" extends="mainLayout" >
+ <put name="title" value="Struts Forward Test" />
+ <put name="body" value="/tutorial/forward/forwardBody.jsp" />
+</definition>
+
+ <!-- Struts forward definition example -->
+<definition name="forward.example.success.page" extends="mainLayout" >
+ <put name="title" value="Struts Forward to 'success'" />
+ <put name="body" value="/tutorial/forward/successBody.jsp" />
+</definition>
+
+ <!-- Struts forward definition example -->
+<definition name="forward.example.failure.page" extends="mainLayout" >
+ <put name="title" value="Struts Forward to 'failure'" />
+ <put name="body" value="/tutorial/forward/failureBody.jsp" />
+</definition>
+
+ <!-- ======================================================= -->
+ <!-- Rss Channels definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Dynamic portal main page (uses common layout) -->
+<definition name="rssChannelTile" path="/tutorial/actions/rssChannel.do" >
+ <putList name="urls" >
+ <!--
+ <add value="http://www.newsforge.com/newsforge.rss" />
+ -->
+ <add value="http://xmlhack.com/rss.php" />
+ <add value="http://lwn.net/headlines/rss" />
+ </putList>
+</definition>
+
+ <!-- Dynamic portal main page (uses common layout) -->
+<definition name="rssLocalChannelTile" path="/tutorial/actions/rssChannel.do" >
+ <putList name="urls" >
+ <add value="/examples/rssFeed/rss-example.xml" />
+ <add value="/examples/rssFeed/apacheweek-headlines.xml" />
+ </putList>
+</definition>
+
+ <!-- Dynamic portal main page (uses common layout) -->
+<definition name="test.rssChannel.page" extends="mainLayout" >
+ <put name="title" value="Rss Channel" />
+ <put name="body" value="rssChannelTile" />
+</definition>
+
+
+ <!-- ======================================================= -->
+ <!-- Dynamic portal definitions -->
+ <!-- ======================================================= -->
+
+ <!-- Dynamic portal body (Define default list) -->
+<definition name="dynamic.portal.body" path="/tutorial/actions/myPortal.do" >
+ <put name="numCols" value="2" />
+ <putList name="list0" >
+ <add value="/tutorial/portal/login.jsp" />
+ <add value="/tutorial/portal/messages.jsp" />
+ <add value="/tutorial/portal/newsFeed.jsp" />
+ <add value="/tutorial/portal/advert2.jsp" />
+ <add value="rssChannelTile" />
+ </putList>
+ <putList name="list1" >
+ <add value="/tutorial/portal/advert3.jsp" />
+ <add value="rssLocalChannelTile" />
+ <add value="/tutorial/portal/stocks.jsp" />
+ <add value="/tutorial/portal/whatsNew.jsp" />
+ <add value="/tutorial/portal/personalLinks.jsp" />
+ <add value="/tutorial/portal/search.jsp" />
+ </putList>
+</definition>
+
+ <!-- Dynamic portal main page (use common layout) -->
+<definition name="myDynamicPortal" extends="mainLayout" >
+ <put name="title" value="My Portal" />
+ <put name="body" value="dynamic.portal.body" />
+</definition>
+
+ <!-- Dynamic portal preferences page (use common layout) -->
+<definition name="myDynamicPortalPreferences" extends="mainLayout" >
+ <put name="title" value="My Portal Settings" />
+ <put name="body" value="dynamic.portal.prefs.body" />
+</definition>
+
+ <!-- Dynamic portal preferences body (extends portal.body to inherit default list) -->
+ <definition name="dynamic.portal.prefs.body"
+ path="/tutorial/actions/myPortalPrefs.tile.do"
+ extends="dynamic.portal.body">
+</definition>
+
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs_de.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs_de.xml
new file mode 100644
index 0000000..c80e774
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs_de.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
+ "http://struts.apache.org/dtds/tiles-config_1_1.dtd">
+
+<!-- Definitions for Tiles tutorial - German Version -->
+
+<tiles-definitions>
+
+ <!-- Main Layout Definition description -->
+ <definition name="mainLayout">
+ <put name="title" value="World Financial Online - Deutsche Version" />
+ <!--<put name="header" value="/tutorial/common/header.jsp"/>-->
+ <put name="footer" value="/tutorial/de/common/footer.jsp" />
+ <!--<put name="menu" value="menu.main"/>
+ <put name="body" value="main.portal.body"/>-->
+ </definition>
+
+ <!-- select language menu -->
+<definition name="menu.lang" path="/common/submenu.jsp" >
+ <put name="title" value="Sprache" />
+ <putList name="items" >
+ <add value="Englisch" />
+ <add value="Französisch" />
+ </putList>
+ <putList name="links" >
+ <add value="/tutorial/lang.do?language=UK" />
+ <add value="/tutorial/lang.do?language=FR" />
+ </putList>
+</definition>
+
+
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs_fr.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs_fr.xml
new file mode 100644
index 0000000..e4d082f
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/tiles-tutorial-defs_fr.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
+ "http://struts.apache.org/dtds/tiles-config_1_1.dtd">
+
+<!-- Definitions for Tiles tutorial - French Version -->
+
+<tiles-definitions>
+
+ <!-- Main Layout Definition description -->
+ <definition name="mainLayout" >
+ <put name="title" value="Le Monde Financier En Ligne" />
+ <!-- <put name="header" value="/tutorial/common/header.jsp" /> -->
+ <put name="footer" value="/tutorial/fr/common/footer.jsp" />
+ <!-- <put name="menu" value="menu.main" /> -->
+ <!-- <put name="body" value="main.portal.body" /> -->
+ </definition>
+
+ <!-- select language menu -->
+<definition name="menu.lang" path="/common/submenu.jsp" >
+ <put name="title" value="Langue" />
+ <putList name="items" >
+ <add value="English" />
+ <add value="Deutch" />
+ </putList>
+ <putList name="links" >
+ <add value="/tutorial/lang.do?language=UK" />
+ <add value="/tutorial/lang.do?language=DE" />
+ </putList>
+</definition>
+
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/web.xml b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5e4133d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/WEB-INF/web.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+ <display-name>Struts Tiles Documentation</display-name>
+
+ <!-- Action Servlet Configuration -->
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
+
+ <!--
+ Tiles config files are now declared with each TilesPlugin in struts-config.xml.
+ Declaring a tiles config file here makes it available to *all* TilesPlugins.
+ This is useful to have common declarations.
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles-defs.xml,/WEB-INF/tiles-tests-defs.xml,
+ /WEB-INF/tiles-tutorial-defs.xml,
+ /WEB-INF/tiles-examples-defs.xml</param-value>
+ </init-param>
+ -->
+
+ <init-param>
+ <param-name>config</param-name>
+ <param-value>/WEB-INF/struts-config.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>config/examples</param-name>
+ <param-value>/WEB-INF/struts-examples-config.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>config/test</param-name>
+ <param-value>/WEB-INF/struts-tests-config.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>config/tutorial</param-name>
+ <param-value>/WEB-INF/struts-tutorial-config.xml</param-value>
+ </init-param>
+ <!--
+ <init-param>
+ <param-name>config/doc</param-name>
+ <param-value>/WEB-INF/struts-doc-config.xml</param-value>
+ </init-param>
+ -->
+ <init-param>
+ <param-name>validate</param-name>
+ <param-value>true</param-value>
+ </init-param>
+
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <!-- Action Servlet Mapping -->
+ <servlet-mapping>
+ <servlet-name>action</servlet-name>
+ <url-pattern>*.do</url-pattern>
+ </servlet-mapping>
+
+
+ <!-- The Welcome File List -->
+ <welcome-file-list>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <!-- Security for role testing -->
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Protected Area</web-resource-name>
+ <!-- Define the context-relative URL(s) to be protected -->
+ <url-pattern>/test/testRole.jsp</url-pattern>
+ <!-- If you list HTTP methods, only those methods are protected -->
+ <http-method>DELETE</http-method>
+ <http-method>GET</http-method>
+ <http-method>POST</http-method>
+ <http-method>PUT</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <!-- Anyone with one of the listed roles may access this area -->
+ <role-name>tomcat</role-name>
+ <role-name>role1</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <!-- Default login configuration uses BASIC authentication -->
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>Example Basic Authentication Area</realm-name>
+ </login-config>
+
+ <!-- Define security roles used in this application -->
+ <security-role>
+ <role-name>role1</role-name>
+ </security-role>
+ <security-role>
+ <role-name>tomcat</role-name>
+ </security-role>
+
+</web-app>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/common/footer.jsp b/struts-sandbox/tiles-documentation/src/webapp/common/footer.jsp
new file mode 100644
index 0000000..b74414b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/common/footer.jsp
@@ -0,0 +1,10 @@
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<div align="center">
+ <font color="#023264" size="-1">
+ <em> Copyright © 2000-2004, The Apache Software Foundation </em>
+ <br>
+ <em> and Cedric Dumoulin </em>
+ </font>
+</div>
+<html:img page="/images/struts-power.gif" align="right" border="0"/>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/common/header.jsp b/struts-sandbox/tiles-documentation/src/webapp/common/header.jsp
new file mode 100644
index 0000000..236ce10
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/common/header.jsp
@@ -0,0 +1,3 @@
+<a href="http://www.apache.org"><img src="<%=request.getContextPath()%>/images/asf-logo.gif" align="left" border="0"></a>
+<a href="http://struts.apache.org"><img src="<%=request.getContextPath()%>/images/struts.gif" align="right" border="0"></a>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/common/submenu.jsp b/struts-sandbox/tiles-documentation/src/webapp/common/submenu.jsp
new file mode 100644
index 0000000..d05875c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/common/submenu.jsp
@@ -0,0 +1,78 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ page import="java.util.Iterator" %>
+
+
+<%-- Push component attributes in page context --%>
+<tiles:importAttribute />
+
+<table>
+<logic:present name="title">
+<tr>
+ <th colspan=2>
+ <div align="left"><strong><bean:write name="title"/></strong></div>
+ </th>
+</tr>
+</logic:present>
+
+<%-- Check if selected exist. --%>
+<logic:notPresent name="selected" >
+ <% pageContext.setAttribute( "selected", "" ); %>
+</logic:notPresent>
+
+<%-- Prepare the links list to be iterated --%>
+<bean:define id="links" name="links" type="java.util.List" scope="page" />
+<% Iterator i = links.iterator(); %>
+
+<%-- iterate on items list --%>
+<%-- Normally, we should write something like this :
+ <logic:iterate id="item" name="items" type="java.lang.String" >
+ But, Struts doesn't declare the TEI class for iterate, and
+ some web container deal badly with the declared variable.
+ So, we use what follow instead.
+ --%>
+<logic:iterate id="iterateItem" name="items" >
+<bean:define id="item" name="iterateItem" type="java.lang.String" scope="page" />
+
+
+<tr>
+ <td width="10" valign="top" ></td>
+ <td valign="top" >
+ <%-- check if selected --%>
+ <logic:notEqual name="selected" value="<%=item%>">
+ <% // Compute link value
+ String link = (String)i.next();
+ if(link.startsWith("/") )
+ link = request.getContextPath() + link;
+ %>
+ <font size="-1"><a href="<%=link%>"><%=item%></a></font>
+ </logic:notEqual>
+ <logic:equal name="selected" value="<%=item%>">
+ <font size="-1" color="fuchsia"><%=item%></font>
+ </logic:equal>
+ </td>
+</tr>
+</logic:iterate>
+
+</table>
+
+<%-- Following are some code example using this submenu
+<tiles:insert page="/common/submenu.jsp" flush="true">
+ <tiles:put name="title" value="Main Menu" />
+ <tiles:putList name="items" >
+ <tiles:add value="Home" />
+ <tiles:add value="Edit Customer" />
+ <tiles:add value="Invoice" />
+ </tiles:putList>
+ <tiles:putList name="links" >
+ <tiles:add value="index.jsp" />
+ <tiles:add value="invoice/index.jsp" />
+ <tiles:add value="invoice/index.jsp" />
+ </tiles:putList>
+</tiles:insert>
+
+<tiles:insert definition="mainSubMenu" flush="true">
+ <tiles:put name="selected" value="Home" />
+</tiles:insert>
+--%>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/common/viewSrcBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/common/viewSrcBody.jsp
new file mode 100644
index 0000000..39736ca
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/common/viewSrcBody.jsp
@@ -0,0 +1,38 @@
+<%@ page language="java" %>
+<%@ page errorPage="/common/viewSrcBodyError.jsp" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+
+<%-- Include requested resource file.
+ If file is not found, Exception is thrown, and catched by the errorPage
+ directive (see above). Error page show a message.
+--%>
+
+ <%-- Import component attributes, if any.
+ --%>
+
+
+<tiles:importAttribute/>
+
+<logic:notPresent name="srcPath" >
+ <logic:present parameter="src" >
+ <bean:parameter id="srcPath" name="src" />
+ </logic:present>
+</logic:notPresent>
+
+
+<logic:present name="srcPath" >
+<bean:define id="srcPathVar" name="srcPath" type="java.lang.String"/>
+<bean:resource id="src" name="<%=srcPathVar%>" />
+<strong>file '<%=srcPathVar%>'</strong>
+<br>
+<pre>
+<bean:write filter="true" name="src" scope="page"/>
+</pre>
+<br>
+</logic:present>
+
+<logic:notPresent name="srcPath" >
+No source specified !
+</logic:notPresent>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/compatibilityChanges.html b/struts-sandbox/tiles-documentation/src/webapp/doc/compatibilityChanges.html
new file mode 100644
index 0000000..7d85567
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/compatibilityChanges.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+ <title>Components : Backward Compatibility Changes</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+</head>
+
+<body>
+<h1 align="center">Backward Compatibility Changes </h1>
+
+
+<table border="2">
+ <tr>
+ <td>
+ <p align="center" style="text-align: center"><b>Deprecated</b></p></td>
+ <td>
+ <p align="center" style="text-align: center"><b>New usage</b></p></td></tr
+ >
+ <tr>
+ <td>
+ <include ></td>
+ <td>
+ <insert ></td></tr>
+ <tr>
+ <td>
+ <putAttribute ></td>
+ <td>
+ <getAsString ></td></tr>
+ <tr>
+ <td>
+ <getAttribute ></td>
+ <td>
+ <getAsString ></td></tr>
+ <tr>
+ <td>< instance= > <br />
+ (in tag <insert > or <include >)</td>
+ <td>
+ < definition= > <br />
+ (in tag <insert >)< </td></tr>
+ <tr>
+ <td>
+ <p align="left">Default definitions file name : </p>
+
+ <ul>
+ <li>
+ <div align="left">componentInstances.xml </div>
+ </li>
+ <li>
+ <div align="left">templateDefinitions.xml </div> </li></ul></td>
+ <td>
+ Several possibilities :
+ <ul>
+ <li>Keep same name and set it in xml-config.xml:
+</li></ul>
+ <div align="center">
+<table border="2">
+<tr>
+ <td>
+ <p>
+ <init-param><br />
+ <param-name><br />
+ definitions-config<br />
+ </param-name><br />
+ <param-value><br />
+ /WEB-
+ INF/templateDefinitions.xml<br />
+
+ </param-value><br />
+ </init-param></p>
+ </td>
+</tr>
+</table></div>
+ <ul>
+ <li>Change name to new default
+ (componentDefinitions.xml) </li></ul></td></tr>
+ <tr>
+ <td>
+ Components parameter names in web.xml:
+ <ul>
+ <li>instances-config </li>
+ <li>instances-debug </li></ul></td>
+ <td>
+
+ Use new names :
+ <ul>
+ <li>definitions-config </li>
+ <li>definitions-debug
+</li></ul></td></tr></table>
+To update your web site, replace all deprecated tags with new
+tags.
+<br />
+You can use replacement
+tools to search for <strong>:include </strong>to be replaced by
+<strong>:insert
+</strong>
+
+</body>
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/comps2Tiles.html b/struts-sandbox/tiles-documentation/src/webapp/doc/comps2Tiles.html
new file mode 100644
index 0000000..4a71367
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/comps2Tiles.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+ <title>Components : Backward Compatibility Changes</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+</head>
+
+<body>
+<h1 align="center">Components to Tiles <br />
+Migration Path</h1>
+
+<h2>In Webapps</h2>
+<ul>
+ <li>Put "tiles.tld" and "tiles.jar" in WEB-INF/</li>
+ <li>Replace all reference to 'components.tld' by 'tiles.tld' in *.jsp and *.xml files.</li>
+ <li>Replace old package name by new one wherever you use package name (don't forget web.xml and
+ struts-config.xml)
+ <ul>
+ <li>s1.struts.components --> org.apache.struts.tiles</li>
+ <li>s1.struts.example.component--> org.apache.struts.example.tiles</li>
+ <li>s1.struts.taglib.components --> org.apache.struts.taglib.tiles</li>
+ </ul>
+ </li>
+ </ul>
+
+<h2>In Java code</h2>
+<ul>
+ <li>If some of your java code use or extends old
+ Components classes, you need to rename imported classes :
+ <ul>
+ <li>s1.struts.components --> org.apache.struts.tiles</li>
+ <li>s1.struts.example.component--> org.apache.struts.example.tiles</li>
+ <li>s1.struts.taglib.components --> org.apache.struts.taglib.tiles</li>
+ </ul>
+ </li>
+</ul>
+
+<h2>Tips</h2>
+<ul>
+ <li>Jbuilder 5 have a tool called "package migration". You can define your own
+ set of migration name using previously defined rules.</li>
+ <li >Lot of tools (like HomeSite) have extended replace command.</li>
+</ul>
+
+<h2 >Very old component versions</h2>
+<p>If you use a very old component version, you also have to change some tags and names :</p>
+
+<table border="1" cellpadding="5" cellspacing="0">
+ <tr>
+ <td>
+ <p align="center" style="TEXT-ALIGN: center"><b>Deprecated</b></p></td>
+ <td>
+ <p align="center" style="TEXT-ALIGN: center"><b>New usage</b></p></td></tr>
+ <tr>
+ <td><include ></td>
+ <td><insert ></td></tr>
+ <tr>
+ <td><putAttribute ></td>
+ <td><getAsString ></td></tr>
+ <tr>
+ <td><getAttribute ></td>
+ <td><getAsString ></td></tr>
+ <tr>
+ <td>< instance= > <br />
+ (in tag <insert > or <include >)</td>
+ <td>
+ < definition= > <br />
+ (in tag <insert >)< </td></tr>
+ <tr>
+ <td>
+ <p>Default definitions file name : </p>
+ <ul>
+ <li>componentInstances.xml</li>
+ <li>templateDefinitions.xml</li>
+ </ul>
+ </td>
+ <td>
+ Several possibilities :
+ <ul>
+ <li>Keep same name and set it in xml-config.xml:
+ </li>
+ </ul>
+<pre>
+ <init-param>
+ <param-name>
+ definitions-config
+ </param-name>
+ <param-value>
+ /WEB-INF/templateDefinitions.xml
+ </param-value>
+ </init-param>
+</pre>
+ <ul>
+ <li>Change name to new default (componentDefinitions.xml)</li>
+ </ul></td></tr>
+ <tr>
+ <td>
+ Components parameter names in web.xml:
+ <ul>
+ <li>instances-config</li>
+ <li>instances-debug</li>
+ </ul>
+ </td>
+ <td>
+ Use new names :
+ <ul>
+ <li>definitions-config</li>
+ <li>definitions-debug</li>
+ </ul>
+ </td>
+ </tr>
+</table>
+<p>To update your web site, replace all deprecated tags with new tags.</p>
+<p>You can use replacement tools to search for <strong>:include </strong>to be
+replaced by <strong>:insert </strong></p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/download.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/download.jsp
new file mode 100644
index 0000000..f49b2f7
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/download.jsp
@@ -0,0 +1,6 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true">
+ <tiles:put name="body" value="/doc/portal/download.jsp" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/extensionsTags.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/extensionsTags.jsp
new file mode 100644
index 0000000..5567bfa
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/extensionsTags.jsp
@@ -0,0 +1,6 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true">
+ <tiles:put name="body" value="/doc/extensionsTags.html" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/index.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/index.jsp
new file mode 100644
index 0000000..acb2584
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/index.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/installation.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/installation.jsp
new file mode 100644
index 0000000..bce7803
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/installation.jsp
@@ -0,0 +1,6 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true">
+ <tiles:put name="body" value="/doc/installation.html" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/overview.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/overview.jsp
new file mode 100644
index 0000000..b9cc67b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/overview.jsp
@@ -0,0 +1,6 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true">
+ <tiles:put name="body" value="/doc/overviewBody.html" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/comments.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/comments.jsp
new file mode 100644
index 0000000..5c53429
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/comments.jsp
@@ -0,0 +1,15 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua"><font size="+1"><strong>Give Your Feedback
+ !</STRONG></FONT></TH></TR>
+<tr>
+<td>
+ <P align=center>
+ <FONT size=2>
+ This library is a alive. Feel free to give your feedback on it !
+ <br>
+ If you have any idea to improve it, let me know !
+ <br>Contact me at :
+ <br><A href="mailto:cedric@apache.org">cedric@apache.org</A>
+ <br>or <A href="mailto:cedric.dumoulin@lifl.fr">cedric.dumoulin@lifl.fr</A>
+ </FONT></P></TD></TR></TABLE>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/documentation.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/documentation.jsp
new file mode 100644
index 0000000..5f30018
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/documentation.jsp
@@ -0,0 +1,23 @@
+<table width="100%">
+<tr>
+<th bgColor=#00ffff ><font size="+1"><strong>Documentation</strong></font></th>
+</tr>
+ <TR>
+ <TD><A href="http://www.lifl.fr/~dumoulin/tiles/tilesAdvancedFeatures.pdf"><P align=center><FONT
+ size=2>tilesAdvancedFeatures.pdf (draft)</FONT></A></P></TD></TR>
+ <TR>
+ <TD><div align="center"><A href="<%=request.getContextPath()%>/api/index.html"><FONT
+ size=2>API</FONT></A></div></TD></TR>
+ <TR>
+ <TD><A href="http://www.manning.com/husted/index.html"><P align=center><FONT
+ size=2>Struts in Action (book)</FONT></A></P></TD></TR>
+ <TR>
+ <TD><A href="http://www-106.ibm.com/developerworks/java/library/j-strutstiles/?loc=j"><P align=center><FONT
+ size=2>Struts and Tiles aid component-based development (article)</FONT></A></P></TD></TR>
+ <TR>
+ <TD><A href="http://www.javaworld.com/javaworld/jw-01-2002/jw-0104-tilestrut.html"><P align=center><FONT
+ size=2> UI design with Tiles and Struts (article)</FONT></A></P></TD></TR>
+ <TR>
+ <TD><A href="http://www.amazon.com/exec/obidos/ASIN/0596003285/ref%3Dpd%5Fsims%5Fdp%5F%5F1/002-2697389-7971238"><P align=center><FONT
+ size=2>Programming Jakarta Struts by Chuck Cavaness (book)</FONT></A></P></TD></TR>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/download.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/download.jsp
new file mode 100644
index 0000000..6305500
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/download.jsp
@@ -0,0 +1,93 @@
+ <table width="100%">
+ <tr>
+ <th bgcolor="aqua">
+ <font size="+1"><strong>Download</strong></font>
+ </th></tr>
+ <tr>
+ <td>
+ <p></p>
+
+
+ <DIV align=center>
+ <div align="center">
+ <font size="2">Choose between binaries or sources distribution</font> </div>
+ <br>
+ <DIV align=center><FONT size=2>Latest build : @compilation-date@ </FONT></DIV>
+ <DIV align=center>
+
+
+ <table border="2">
+ <tr>
+ <td>
+ <p align="center">
+ <font color="#ff0000"><strong>Development</strong></font>
+ <br>
+ </p></td>
+ <td>
+ <p align="center">
+ <font size="2"><strong>binaries<br></strong>(src excluded)</font> </p></td>
+ <td>
+ <p align="center">
+ <font size="2"><strong>sources</strong></font> </p></td></tr>
+ <tr>
+ <td>
+ <div align="right">
+ <font size="2"><strong>Main site :<br></strong>(<a href=
+ "http://www.lifl.fr/~dumoulin/tiles">www.lifl.fr</a>)</font> </div></td>
+ <td>
+ <div align="left">
+ <a href=
+ "http://www.lifl.fr/~dumoulin/tiles/tiles.zip"><strong>
+ tiles.zip</strong></a> </div>
+ <div align="left">
+ <a href=
+ "http://www.lifl.fr/~dumoulin/tiles/tiles.tar.gz">
+ <strong>tiles.tar.gz</strong></a> </div></td>
+ <td>
+ <div align="left">
+ <a href=
+ "http://www.lifl.fr/~dumoulin/tiles/tiles-src.zip">
+ <font size=
+ "2"><strong>tiles-src.zip</strong></font></a> </div>
+ <div align="left">
+ <a href=
+ "http://www.lifl.fr/~dumoulin/tiles/tiles-src.tar.gz">
+ <strong><font size=
+ "2">tiles-src.tar.gz</font></strong></a>
+</div></td></tr>
+ <tr>
+ <td>
+ <div align="right">
+ <font size="2"><strong>Mirror
+ :</strong></font> </div>
+ <div align="right">
+ <font size="2">(<a href="http://www.geocities.com/cedricDumoulin/tiles">
+ www.geocities.com</a>)</font> </div></td>
+ <td>
+ <div align="left">
+ <a href=
+ "http://www.geocities.com/cedricdumoulin/tiles/tiles.zip">
+ <strong>tiles.zip</strong></a> </div>
+ <div align="left">
+ <strong><a href=
+ "http://www.geocities.com/cedricdumoulin/tiles/tiles.tar.gz">
+ tiles.tar.gz</a></strong> </div></td>
+ <td>
+ <div align="left">
+ <a href=
+ "http://www.geocities.com/cedricdumoulin/tiles/tiles-src.zip">
+ <font size=
+ "2"><strong>tiles-src.zip</strong></font></a> </div>
+ <div align="left">
+ <strong><a href=
+ "http://www.geocities.com/cedricdumoulin/tiles/tiles-src.tar.gz">
+ <font size=
+ "2">components-src.tar.gz</font></a></strong>
+ </div></td></tr>
+ </table></DIV>
+ <br>
+ <DIV align=center><FONT size=2><FONT size=2>
+ <EM><STRONG>Tiles </STRONG></EM>is also distributed with<STRONG> <EM>Struts 1.1 .
+ <BR>
+ </EM></STRONG>You can download it by downloading <A
+ href="http://struts.apache.org"><STRONG><EM>Struts</EM></STRONG></A><STRONG><EM>.</EM></STRONG></FONT></FONT></DIV></DIV></td></tr></table>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/features.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/features.jsp
new file mode 100644
index 0000000..12a30dd
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/features.jsp
@@ -0,0 +1,160 @@
+ <table width="100%">
+ <tr>
+ <th bgcolor="aqua">
+ <font size="+1"><strong>Tiles Library<br>
+ Features Overview</strong></font>
+ </th>
+ </tr>
+ <tr>
+ <td>
+ <p>
+ <font size="2"><strong><font size="2"><strong>Following is an
+ overview of what can be done with Tiles
+ :</strong></font></strong></font>
+ </p>
+ <ul>
+ <li>
+ <font size="2">Screen definitions</font>
+ <ul>
+ <li>
+ <font size="2">Create a screen by assembling
+ <strong><em>Tiles</em></strong> : header, footer,
+ menu, body</font>
+ </li>
+ <li>
+ <font size="2">Definitions can take place :</font>
+ <ul>
+ <li>
+ <font size="2">in a centralized xml
+ file</font>
+ </li>
+ <li>
+ <font size="2">directly in jsp page</font>
+ </li>
+ <li>
+ <font size="2">in struts action</font>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <font size="2">Definitions provide an inheritance
+ mechanism : a definition can extends another one,
+ and override parameters.</font>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <font size="2">Templating</font>
+ <ul>
+ <li>
+ <font size="2"><strong><em>Tiles</em></strong>
+ framework is entirely compatible with
+ <em>Templates</em> defined by David Geary and
+ implemented in Struts</font>
+ </li>
+ <li>
+ <font size="2">You can replace <em>Templates</em>
+ library by <strong><em>Tiles</em></strong>
+ one</font>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <font size="2">Layouts</font>
+ <ul>
+ <li>
+ <font size="2">Define common page layouts and reuse
+ them across your web site</font>
+ </li>
+ <li>
+ <font size="2">Define menu layouts, and use them by
+ passing lists of items and links</font>
+ </li>
+ <li>
+ <font size="2">Define portal layout, use it by
+ passing list of <strong><em>Tiles</em></strong>
+ (pages) to show</font>
+ </li>
+ <li>
+ <font size="2">Reuse existing layouts, or define
+ your owns</font>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <font size="2">Dynamic page building</font>
+ <ul>
+ <li>
+ <font size="2">Tiles are gather dynamically during
+ page reload. It is possible to change any attributes
+ : layout, list of Tiles in portal, list of menu
+ items, ...</font>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <font size="2">Reuse of <strong><em>Tiles</em></strong> /
+ Components</font>
+ <ul>
+ <li>
+ <font size="2">If well defined, a
+ <strong><em>Tile</em></strong> can be reused in
+ different location</font>
+ </li>
+ <li>
+ <font size="2">Dynamic attributes are used to
+ parameterized <em><strong>Tiles</strong></em></font>
+ </li>
+ <li>
+ <font size="2">It is possible to define library of
+ reusable <em><strong>Tiles</strong></em>.</font>
+ </li>
+ <li>
+ <font size="2">Build a page by assembling predefined
+ components, give them appropriate parameters</font>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <font size="2">Internationalization (i18n)</font>
+ </li>
+ <ul>
+ <li>
+ <font size="2">It is possible to load different tiles
+ according to Locale</font>
+ </li>
+ <li>
+ <font size="2">A mechanism similar to Java properties
+ files is used for definitions files : you can have one
+ definition file per Locale. The appropriate definition is
+ loaded according to current Locale</font>
+ </li>
+ </ul>
+ <li>
+ <font size="2">Multi-channels</font>
+ </li>
+ <ul>
+ <li>
+ <font size="2">It is possible to load different Tiles
+ according to a key stored in jsp session, or
+ anywhere.</font>
+ </li>
+
+ <li>
+ <font size="2">For example, key could be user provilege,
+ browser type, ...</font>
+ </li>
+
+ <li>
+ <font size="2">A mechanism similar to Java properties
+ files is used for definitions files : you can have one
+ definition file per key. The appropriate definition is
+ loaded according to the key.</font>
+ </li>
+ </ul>
+ </ul>
+ </td>
+ </tr>
+ </table>
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/images/portalOverview.gif b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/images/portalOverview.gif
new file mode 100644
index 0000000..4a768cc
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/images/portalOverview.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/news.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/news.jsp
new file mode 100644
index 0000000..3d22356
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/news.jsp
@@ -0,0 +1,77 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua"><font size="+1"><strong>News</strong></font></th></tr>
+<tr>
+<td>
+ <p><FONT size=2>03 Nov. 2002</FONT></P>
+ <P><STRONG><EM><FONT color=#ff0000>TilesPlugin module aware</FONT></EM></STRONG>
+ <br><FONT color=#000000 size=2>
+ The TilesPlugin for struts now create one separate definition factory for each struts module.
+ </FONT></P>
+
+ <p><FONT size=2>19 Jul. 2002</FONT></P>
+ <P><STRONG><EM><FONT color=#ff0000>Tiles is now in the main branch of
+ Struts1.1 distribution</FONT></EM></STRONG>
+ <br><FONT color=#000000 size=2>
+ A Tiles plug-in is available for Struts1.1.
+ </FONT></P>
+
+ <p><FONT size=2>22 May 2002</FONT></P>
+ <P><STRONG><EM><FONT color=#ff0000>Tiles Advanced Features Documentation (draft version)</FONT></EM></STRONG>
+ <br><FONT color=#000000 size=2>
+ <a href="http://www.lifl.fr/~dumoulin/tiles/tilesAdvancedFeatures.pdf" />tilesAdvancedFeatures.pdf</a>
+ </FONT></P>
+
+ <P><STRONG><EM><FONT color=#ff0000>Tiles-blank Applications</FONT></EM></STRONG>
+ <br><FONT color=#000000 size=2>
+ Different <code>tiles-blanc.war</code> files are now provided to help starting new project using Tiles.
+ <ul>
+ <li><code>tiles-blank.war</code> - Tiles without Struts</li>
+ <li><code>tiles-blank-struts1.1.war</code> - Tiles with Struts1.1</li>
+ <li><code>tiles-blank-struts1.0.war</code> - Tiles with latest stable Struts1.0.x</li>
+ </ul>
+ </FONT></P>
+
+ <P><FONT color=#ff0000><EM><STRONG>Article on Tiles and Struts</STRONG></EM></FONT>
+ <br><FONT color=#000000 size=2>
+ An article on using Tiles and Struts is available at :
+ <br>
+ <a href="http://www.javaworld.com/javaworld/jw-01-2002/jw-0104-tilestrut.html" >http://www.javaworld.com/javaworld/jw-01-2002/jw-0104-tilestrut.html</a>
+ </FONT></P>
+ <P><FONT color=#ff0000><EM><STRONG>Dynamic Layout</STRONG></EM></FONT>
+ <br><FONT color=#000000 size=2>
+ Dynamic layouts allow a user to customize a site L&F. Check the example to see how to proceed with Tiles.
+ </FONT></P>
+ <P><FONT color=#ff0000><EM><STRONG>New Layout : Tabs</STRONG></EM></FONT>
+ <br><FONT color=#000000 size=2>
+ The new tabs layout allows to build easily tabs like page : specify which
+ body you want in which tabs, and that all !
+ </FONT></P>
+ <P><FONT color=#ff0000><EM><STRONG>Commented Examples</STRONG></EM></FONT>
+ <br><FONT color=#000000 size=2>
+ A lot of interesting examples have been revisited and commented in a "portal" fashion.
+ Check "Live Examples" menu entry.
+ </FONT></P>
+ <P><STRONG><EM><FONT color=#ff0000>Each Tile can have its own controller !<BR></FONT></EM></STRONG>
+ <FONT color=#000000 size=2>
+ It is now possible to associate a controller to each Tile. This controller (Java code
+ or struts action) is called immediately before the Tile jsp page. It is useful to prepare
+ data to be shown by jsp page.
+ </FONT></P>
+ <P><STRONG><EM><FONT color=#ff0000>Reload Action<BR></FONT></EM></STRONG>
+ <FONT color=#000000 size=2>
+ There is now a reload action, and a reloadable factory wrapper allowing to reload Tiles
+ configuration files without restarting web server.
+ </FONT></P>
+ <P><STRONG><EM><FONT color=#ff0000>Use and Set Bean in configuration file<BR></FONT></EM></STRONG>
+ <FONT color=#000000 size=2>
+ It is now possible to use and set beans in the configuration file. Such bean can then be
+ set as a <put> or <putList> tag value.
+ <br>
+ This increase and facilitate menu creation.
+ </FONT></P>
+ <P>
+ <FONT size=2>Check "History" for latest modifications (further in this page)</FONT></P>
+ <P>
+
+</td></tr></table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/nextFeatures.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/nextFeatures.jsp
new file mode 100644
index 0000000..fa64a13
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/nextFeatures.jsp
@@ -0,0 +1,17 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua"><font size="+1"><strong>Future Features</strong></font></th>
+</tr>
+ <TR>
+ <TD><FONT size=2><b>Dynamic Portal Example</b></FONT></TD></TR>
+<tr>
+<td><FONT size=2>Portal page is build according to a
+ user profile, or whatever you want.
+</FONT>
+
+
+
+
+ </td>
+</tr>
+</table>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/revisions.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/revisions.jsp
new file mode 100644
index 0000000..342d86c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/revisions.jsp
@@ -0,0 +1,132 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua"><FONT size=4>History</FONT></th></tr>
+ <TR>
+ <TD><FONT size=2><STRONG> 03 Nov. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <FONT size=2>
+ <UL>
+ <LI>Tiles now use the commons-logging package.</LI>
+ <li><useAttribute>: Corrected a bug where the tag fail when reused by server.</li>
+ <li>The struts TilesPlugin now create one factory for each struts module</li>
+ </UL>
+ </FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 19 Jul. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <FONT size=2>
+ <UL>
+ <LI>TilesPlugin available for Struts1.1</LI>
+ <li>Blank war files have been updated</li>
+ <li>Definition factory interface has change. A new life cycle is introduce</li>
+ <li>Struts multi-modules feature works with the Tiles</li>
+ </UL>
+ </FONT>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 20 Jun. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>Update DefinitionDispatcherAction. It now works again</FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 13 Jun. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>Tiles configuration file now accept nested list as attribute</FONT></LI>
+ <LI><FONT size=2>Add <uri> tag to DTD (submitted by Loren Halvorson)</FONT></LI>
+ configuration file</FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 23 May 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>tiles.XmlDefinition.XmlParser : enable default value for <item> classtype
+ attribute
+ (org.apache.struts.tiles.beans.SimpleMenuItem). As a consequence, all classtype attribute
+ can be removed in examples</FONT></LI>
+ <LI><FONT size=2>tiles.XmlDefinition.I18nFactorySet : Enable serialization (bug reported
+ by Dan Sykes)</FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 14 Apr. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>tiles.XmlDefinition.XmlParser : Correct bug with new Digester release
+ preventing config file lists to be correctly parsed</FONT></LI>
+ <LI><FONT size=2>tabsLayout.jsp : Correct some syntax errors(bug reported by David Marshall)</FONT></LI>
+ <LI><FONT size=2>taglib.tiles.UseAttribute : Add release of variable 'id' in release method
+ (bug reported by Heath Chiavettone)</FONT></LI>
+ <LI><FONT size=2>tiles.XmlDefinition.XmlDefinition : Add inheritance for controllerClass and
+ controllerUrl attributes (bug reported by Jim Crossley) </FONT></LI>
+ <LI><FONT size=2>tiles.XmlDefinition.I18nFactorySet : Add another loading method for config
+ files in order to let Websphere 3.5.x run (patch from Stephen Houston)</FONT></LI>
+ <LI><FONT size=2>tiles.ComponentActionServlet : Add overload of processForward and
+ processInclude in order to catch properly forward in struts1.0.x struts-config (bug reported from
+ struts user list)</FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 22 Feb. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>Correct build process preventing examples compilation in war files </FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 20 Feb. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>New tiles-blank-struts1.x applications</FONT></LI>
+ <LI><FONT size=2>Change distribution (again) : back to the old fashion</FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 18 Feb. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>New tiles-blank application</FONT></LI>
+ <LI><FONT size=2>Added a TilesController to run with latest Struts 1.1 dev</FONT></LI>
+ <LI><FONT size=2>Change distribution : a stable release build shipped with Struts1.0.x
+ and a development release build with Struts1.1 dev</FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> 11 Jan. 2002</STRONG> </FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>Corrected bug preventing empty <put> body tags in Tomcat4</FONT></LI>
+ <LI><FONT size=2>Corrected customized factory loading. It now works again</FONT></LI>
+ </UL>
+ </TD>
+ </TR>
+
+ <TR>
+ <TD><FONT size=2><STRONG> <A href="<%=request.getContextPath()%>/doc/portal/revisionsCont.html">
+ <FONT size=2><STRONG>more ...</STRONG></FONT></A></STRONG></FONT>
+ </TD>
+ </TR>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/revisionsCont.html b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/revisionsCont.html
new file mode 100644
index 0000000..b412592
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/revisionsCont.html
@@ -0,0 +1,300 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<title>Untitled Document</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+</head>
+<body>
+<table width="100%">
+<tr>
+<th bgcolor="aqua"><h4>History (con't)</h4></th>
+</tr>
+<tr>
+<td><strong> 27 Dec. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li>Add commented examples portal</li>
+ <li>Allow controller to be associated to a Tile</li>
+ <li>Allow beans set in <put> and <putList> tags</li>
+ <li>Add a reload action, and a reloadable factory wrapper</li>
+ <li>Move NoOpAction to actions subdirectory</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 02 nov. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Correct another bug with Orion : "importAttribute not working when reused"</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 29 oct. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Allow body content in tag <put> and <add> in xml files </li>
+ <li>Correct bug with Orion : "insert tag attribute not reset when ignore=true".</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 08 oct. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Correct bug "path overloaded when inheriting definition". </li>
+ <li> Add example "dynamic portal" </li>
+ <li>Add Tile Rss Channel (Thanks Ted Husted)</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 27 sept. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Correct bug preventing definitions file to be loaded when using latest
+ commons-digester.jar. </li>
+ <li>Remove component-config.tld (replaced by tiles-config.tld). </li>
+ <li>Add a tilesForStruts1.0.jar file, intended for Struts1.0</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 13 sept. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li>Correct bug in getAsString. Nothing is written when ignore=true
+ and no attribute is found.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 09 sept. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Modify ComponentActionServlet. It now allows to :
+ <ul>
+ <li> use a Struts action as the page attribute of an <insert> or <definition> </li>
+ <li>modify tile attributes inside action </li>
+ <li>associate an action with a tile, and this for each tile.</li>
+ </ul>
+ </li>
+ <li>Update and modify the "invoice" example. </li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 30 jul. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Merge Documentation and tutorial in one war file.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 25 jul. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Now use commons.Digester, according to new Struts policy.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 19 jul. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Components become Tiles. </li>
+ <li>Start integration in Struts </li>
+ <li>Change code package names accordingly</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 04 jul. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Add flush attribute to get </li>
+ <li>Update tutorial </li>
+ <li>Add a DTD for configuration file. However, DTD is not used (yet) for validation. </li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 02 jul. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li>Tested successfully on Tomcat-3.2.1, Tomcat-4.0b5, Orion-1.4.5, Resin-2.0.0 </li>
+ <li>Correct the release() bug preventing framework to run on Resin-2.0.0
+ <ul>
+ <li>Remove calls to release() in doEndTag(), call to releaseInternal()
+ instead. </li>
+ </ul>
+ </li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 17 jun. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Remove backward compatibility with deprecated tags. Update webapps accordingly </li>
+ <li> Release multi-channels example.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 20 may. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li>Change definition factory implementation. This simplify design and
+ usage of others implementations. A 'multi-channel' implementation is in study. </li>
+ <li>Allow to insert an 'action URL' as well as a 'definition' or a 'jsp'. This
+ implies a check in ActionServlet just before doing effective forward or include.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 29 apr. 2001</strong><strong>Stable version</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li>Role attribute is taken into account. </li>
+ <li>PutList accept nested putList. </li>
+ <li>Clearly separate definition factory.
+ <ul>
+ <li>Possibility to implement others definition factory </li>
+ <li>Can provide definition factory class name as servlet attribute </li>
+ </ul>
+ </li>
+ <li>Change nested tags implementation (PutTag, PutListTag, AddTag, InsertTag,
+ DefinitionTag).</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 19 apr. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Correct a bug preventing Components to run on Orion 1.4.5. Call release()
+ at the end of insert tag.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 08 apr. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Add attribute 'ignore' to tags <get> <insert>. </li>
+ <li>Add tag <getAsString> to replace <getAttribute> </li>
+ <li> Change tests suite in comps-doc</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 02 apr. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Use word "definition" instead of "instance". Concretely, a lot of class
+ names and tag names change. Have replaced a lot of word "instance" by "definition.
+ Old tags still exist for backward compatibility. </li>
+ <li> Can define a "definition" in XML file, in an Action, or by using tag <definition></li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 14 feb. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Added role attribute in tags. Components are again fully compatible with
+ JSP Templates.</li>
+</ul>
+</td>
+</tr>
+<tr><td colspan="2"> </td></tr>
+<tr>
+<td><strong> 07 feb. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Modification of 'ActionComponentServlet.java' to be compliant with latest
+ Struts servlet implementation. Import the right html.Constant class.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 11 jan. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+<li>Modification of 'ActionComponentServlet.java' to be compliant with new Struts
+servlet implementation. New classes are not compatible with Struts prior to 010108 </li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 08 apr. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Add attribute 'ignore' to tags <get> <insert>. </li>
+ <li>Add tag <getAsString> to replace <getAttribute> </li>
+ <li> Change tests suite in comps-doc </li>
+</ul>
+</td>
+</tr>
+<tr>
+<td><strong> 02 apr. 2001</strong> </td>
+</tr>
+<tr>
+<td>
+<ul>
+ <li> Use word "definition" instead of "instance". Concretely, a lot of class
+ names and tag names change. Have replaced a lot of word "instance" by "definition.
+ Old tags still exist for backward compatibility. </li>
+ <li> Can define a "definition" in XML file, in an Action, or by using tag <definition></li>
+</ul>
+</td>
+</tr>
+</table>
+</body>
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/strutsIntegration.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/strutsIntegration.jsp
new file mode 100644
index 0000000..260daa8
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/strutsIntegration.jsp
@@ -0,0 +1,47 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua">
+ <font size="+1"><strong>Tiles and Struts</STRONG></FONT>
+</TH>
+</TR>
+ <TR>
+ <TD>
+ <P>
+ <FONT size=2>Tiles are actually shipped with Struts</FONT></P>
+ <P>
+ <FONT size=2>
+ Tiles and Struts code are clearly separated. In fact, Tiles can run without Struts. But using
+ both give you interresting features, like forwarding an action to a tile's definition.
+ </FONT>
+ <FONT size=2>Following is a list of actual modifications :</FONT> </P></TD></TR>
+ <TR>
+ <TD><FONT size=2><b>Tile Action Servlet</B></FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>Add a
+ "processForward" method. </FONT>
+ <LI><FONT size=2>Purpose : be
+ able to subclass servlet, and override the forward mechanism. </FONT>
+ <LI><FONT size=2>Needed if you
+ want to forward to a definition in
+ struts-config.xml.</FONT></LI>
+ <LI><FONT size=2>A ready to run servlet is provided.</FONT></LI>
+ </UL>
+
+ </TD>
+ </TR>
+ <TR>
+ <TD><FONT size=2><STRONG> <EM>text</EM>
+ tag</STRONG></FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>Not
+ mandatory, can be omitted if not used </FONT>
+ <LI><FONT size=2>Add a
+ "prefix" attribute. </FONT>
+ <LI><FONT size=2>Purpose : be
+ able to add a prefix to the name of generated input tag. This
+ modification is not mandatory. It is only useful in some
+ examples.</FONT> </LI></UL></TD></TR></TABLE>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/tilesCompsTemplates.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/tilesCompsTemplates.jsp
new file mode 100644
index 0000000..c653c44
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/tilesCompsTemplates.jsp
@@ -0,0 +1,15 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua"><font size="+1"><strong>Tiles, Components
+ <BR>and JSP Templates</STRONG></FONT></TH></TR>
+<tr>
+<td>
+ <P><FONT size=2>Tiles was formely
+ known as "Components". But as components means all and everything, we have
+ choose to rename them to Tiles. </FONT></P>
+ <P><FONT size=2>Tiles provide a
+ superset of Template tags as defined in Struts by David Geary : you can find all
+ tags and behavior defined by Templates. But, Tiles </FONT><FONT size=2> go one step beyond and extend the concept of
+ "templates" to the concept of "parameterized components" or
+ "Tiles".</FONT></P>
+</TD></TR></TABLE>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/todo.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/todo.jsp
new file mode 100644
index 0000000..4928eb1
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/todo.jsp
@@ -0,0 +1,22 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua" colSpan=2><font size="+1"><strong>To
+ Do</STRONG></FONT></TH></TR>
+ <TR>
+ <TD colSpan=2><FONT size=2><STRONG>Components Configuration
+ File</STRONG></FONT></TD></TR>
+ <TR>
+ <TD>
+ <UL>
+ <LI><FONT size=2>Add the
+ ability to have attribute value in tag body. This is already the case in
+ JSP pages, but not in Configuration file.</FONT> </LI></UL></TD>
+ <TR>
+ <TD colSpan=2><FONT size=2><STRONG>Reload</STRONG></FONT></TD></TR>
+ <TR>
+ <TD colSpan=2>
+ <UL>
+ <LI><FONT size=2>Be able to
+ reload definitions descriptions without restarting web container. This
+ can easily be done with an administration
+ page.</FONT></LI></UL></TD></TR></TABLE>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/portal/welcome.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/welcome.jsp
new file mode 100644
index 0000000..ac23f5c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/portal/welcome.jsp
@@ -0,0 +1,22 @@
+<table width="100%">
+<tr>
+<th bgcolor="aqua"><font size="+1"><strong>Welcome</strong></font></th></tr>
+<tr>
+<td>
+ <P>
+ <FONT size=2> Welcome to the <EM>Tiles </EM>website. This "portal" page is an example of what can be
+ done with <EM>Tiles</EM>. It is made by assembling <EM>Tiles</EM>.
+ </FONT>
+ <BR><FONT size=2>
+ You can :
+ <ul>
+ <li>Take a glance at some Tiles features and capabilities by browsing the commented live examples (avalaible if you install Tiles)</li>
+ <li>Check the "Quick Overview" for code examples and results</li>
+ <li>Start learning Tiles with the tutorial</li>
+ <li>Learn <a href="http://www.lifl.fr/~dumoulin/tiles/tilesAdvancedFeatures.pdf" />Tiles Advanced Features (pdf)</a></li>
+ <li>Read article from <a href="http://www.javaworld.com/javaworld/jw-01-2002/jw-0104-tilestrut.html" >javaworld</a></li>
+ </ul>
+ </FONT>
+</P>
+</td></tr>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/tilesTags.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/tilesTags.jsp
new file mode 100644
index 0000000..eb53d59
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/tilesTags.jsp
@@ -0,0 +1,6 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true">
+ <tiles:put name="body" value="/doc/struts-tilesTags.html" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/tutorial.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/tutorial.jsp
new file mode 100644
index 0000000..58ff88d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/tutorial.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="mainLayout" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/tutorialStaticIndex.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/tutorialStaticIndex.jsp
new file mode 100644
index 0000000..365b440
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/tutorialStaticIndex.jsp
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+ <title>Tiles : tutorial Examples not Available on this site</title>
+</head>
+
+<body>
+<P> </P>
+<P> </P>
+<P><FONT size=4>The tutorial live examples are not available on this site.
+</FONT></P>
+<P> </P>
+<P><FONT size=4>You can try them by downloading Tiles application, and running
+the provided war file in a jsp container. </FONT></P>
+
+
+
+
+
+</body>
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/doc/userGuide.jsp b/struts-sandbox/tiles-documentation/src/webapp/doc/userGuide.jsp
new file mode 100644
index 0000000..6f4cfe0
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/doc/userGuide.jsp
@@ -0,0 +1,6 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true">
+ <tiles:put name="body" value="/doc/userGuideBody.html" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/index.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/index.jsp
new file mode 100644
index 0000000..9299240
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/index.jsp
@@ -0,0 +1,3 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<tiles:insert definition="examples.index.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/myMenuSettings.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/myMenuSettings.jsp
new file mode 100644
index 0000000..560466e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/myMenuSettings.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.userMenu.settings.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/myPortal.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/myPortal.jsp
new file mode 100644
index 0000000..86f238e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/myPortal.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.portal.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/myPortalSettings.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/myPortalSettings.jsp
new file mode 100644
index 0000000..bbefd6e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/myPortalSettings.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.portal.settings.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/portal.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/portal.jsp
new file mode 100644
index 0000000..86f238e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/portal.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.portal.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/rssChannels.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/rssChannels.jsp
new file mode 100644
index 0000000..c44e20a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/rssChannels.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.rssChannels.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/rssFeed/apacheweek-headlines.xml b/struts-sandbox/tiles-documentation/src/webapp/examples/rssFeed/apacheweek-headlines.xml
new file mode 100644
index 0000000..90e2e87
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/rssFeed/apacheweek-headlines.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd">
+<rss version="0.91">
+ <channel>
+ <title>Apache Week 262</title>
+ <description>The essential resource for anyone running an Apache server, or anyone responsible for running Apache-based services.</description>
+ <language>en-gb</language>
+ <link>http://www.apacheweek.com/</link>
+ <copyright>Copyright 2001, Red Hat Europe</copyright>
+ <managingEditor>editors@apacheweek.com (Mark Cox)</managingEditor>
+ <webMaster>webadmin@apacheweek.com (Mark Cox)</webMaster>
+ <lastBuildDate>20010907</lastBuildDate>
+ <pubDate>20010907</pubDate>
+ <image>
+ <title>Apache Week</title>
+ <url>http://www.apacheweek.com/img/apacheweek_channel.gif</url>
+ <link>http://www.apacheweek.com/</link>
+ <width>88</width>
+ <height>31</height>
+ <description>Apache Week</description>
+ </image>
+ <item>
+ <title>Under development</title>
+ <link>http://www.apacheweek.com/issues/01-09-07#dev</link>
+ <description>
+Controversy over a gzip content compression module for 2.0
+</description>
+ </item>
+ <item>
+ <title>In the news</title>
+ <link>http://www.apacheweek.com/issues/01-09-07#news</link>
+ <description>
+New web server surveys this month agree that Apache is still in
+use on around 60% of all sites
+</description>
+ </item>
+ <item>
+ <title>Featured articles</title>
+ <link>http://www.apacheweek.com/issues/01-09-07#featured</link>
+ <description>
+Analysing Apache logs with Webalizer; improving your Apache server performance
+</description>
+ </item>
+ </channel>
+</rss>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/rssFeed/rss-example.xml b/struts-sandbox/tiles-documentation/src/webapp/examples/rssFeed/rss-example.xml
new file mode 100644
index 0000000..20a5e50
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/rssFeed/rss-example.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE rss PUBLIC
+ "-//Netscape Communications//DTD RSS 0.91//EN"
+ "http://my.netscape.com/publish/formats/rss-0.91.dtd">
+
+<rss version="0.91">
+
+ <channel>
+
+ <title>MozillaZine</title>
+ <link>http://www.mozillazine.org</link>
+ <description>Your source for Mozilla news, advocacy,
+ interviews, builds, and more!</description>
+ <language>en-US</language>
+ <rating>(PICS-1.1 "http://www.rsac.org/ratingsv01.html"
+ 2 gen true comment "RSACi North America Server"
+ for "http://www.rsac.org" on "1996.04.16T08:15-0500"
+ r (n 0 s 0 v 0 l 0))</rating>
+
+ <image>
+ <title>MozillaZine</title>
+ <url>http://www.mozillazine.org/image/mynetscape88.gif</url>
+ <link>http://www.mozillazine.org</link>
+ <width>88</width>
+ <height>31</height>
+ <description>Articles, discussions, builds, and more...</description>
+ </image>
+
+ <item>
+ <title>Java2 in Navigator 5?</title>
+ <link>http://www.mozillazine.org/talkback.html?article=607</link>
+ <description>Will Java2 be an integrated part of Navigator 5?
+ Read more about it in this discussion...</description>
+ </item>
+
+ <item>
+ <title>Communicator 4.61 Out</title>
+ <link>http://www.mozillazine.org/talkback.html?article=606</link>
+ <description>The latest version of Communicator is now
+ available. It includes security enhancements
+ and various bug fixes.</description>
+ </item>
+
+ <item>
+ <title>Mozilla Dispenses with Old,
+ Proprietary DOM</title>
+ <link>http://www.mozillazine.org/talkback.html?article=604</link>
+ </item>
+
+ <item>
+ <title>The Animation Contest is Now Closed</title>
+ <link>http://www.mozillazine.org/talkback.html?article=603</link>
+ </item>
+
+ <textinput>
+ <title>Send</title>
+ <description>Comments about MozillaZine?</description>
+ <name>responseText</name>
+ <link>http://www.mozillazine.org/cgi-bin/sampleonly.cgi</link>
+ </textinput>
+
+ </channel>
+
+</rss>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/skinSettings.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/skinSettings.jsp
new file mode 100644
index 0000000..9c60af6
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/skinSettings.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.skin.settings.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/summariesTabs.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/summariesTabs.jsp
new file mode 100644
index 0000000..8d08130
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/summariesTabs.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.tabs.summaries.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tabs.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tabs.jsp
new file mode 100644
index 0000000..26ef23b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tabs.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="examples.tabs.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/adminSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/adminSummary.jsp
new file mode 100644
index 0000000..b3ea61b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/adminSummary.jsp
@@ -0,0 +1,30 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>Administration</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>Some administration facilities are provided.</li>
+ <li>It is possible to reload definitions configuration files without restarting
+ the web server.</li>
+ <li>Also, it is possible to view definitions loaded and resolved by the factory.</li>
+ <li>This facilities are used during development. They should be removed or protected with a password
+ if used in a production environment.</li>
+ </ul>
+ </TD>
+ </TR>
+ <TR>
+ <td class="datalightblue">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/admin/tiles/reload.do">Reload Factory</a></li>
+ <li><a href="<%=request.getContextPath()%>/admin/tiles/view.do">View Factory</a></li>
+ </ul>
+ </TD>
+ </TR>
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/body.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/body.jsp
new file mode 100644
index 0000000..ee1b0a6
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/body.jsp
@@ -0,0 +1,10 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<div align="center">
+ <font color="#023264" size="-1">
+ <em> This is the body ! </em>
+ <br>
+ <em> done </em>
+ </font>
+</div>
+<img src="<%=request.getContextPath()%>/images/struts-power.gif" align="center" border="0">
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/componentsSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/componentsSummary.jsp
new file mode 100644
index 0000000..2331e0a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/componentsSummary.jsp
@@ -0,0 +1,27 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>Reuse Tiles</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>A tile can be used several time in a same page</li>
+ <li>For example, you can have a Tile rendering an address, and use it to
+ render as well shipping and billing addresses</li>
+ </ul>
+ </TD>
+ </TR>
+ <TR>
+ <td class="datalightblue">
+ <ul>
+ <li>new examples not yet available, see tutorial in meantime</li>
+ </ul>
+ </TD>
+ </TR>
+
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/footer.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/footer.jsp
new file mode 100644
index 0000000..caa7d4d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/footer.jsp
@@ -0,0 +1,9 @@
+<hr>
+<div align="center">
+ <font color="#023264" size="-1">
+ <em> Copyright © 2001-2004, The Apache Software Foundation </em>
+ <br>
+ <em> and Cedric Dumoulin </em>
+ </font>
+</div>
+<img src="<%=request.getContextPath()%>/images/struts-power.gif" align="right" border="0">
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/header.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/header.jsp
new file mode 100644
index 0000000..236ce10
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/header.jsp
@@ -0,0 +1,3 @@
+<a href="http://www.apache.org"><img src="<%=request.getContextPath()%>/images/asf-logo.gif" align="left" border="0"></a>
+<a href="http://struts.apache.org"><img src="<%=request.getContextPath()%>/images/struts.gif" align="right" border="0"></a>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/i18nSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/i18nSummary.jsp
new file mode 100644
index 0000000..741da8e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/i18nSummary.jsp
@@ -0,0 +1,27 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>Internationalization (i18n)</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>Tiles provide some facilities for i18n</li>
+ <li>It is possible to load a different Tile according to the user Locale setting</li>
+ <li>Tiles have the same definition name, but different definition attributes.</li>
+ <li>Definitions are defined in separate configuration files, one for each locale.
+ Appropriate file is loaded using the same rules as for Java properties :
+ configuration file name is extended with locale abreviations</li>
+ </ul>
+ </TD>
+ </TR>
+ <td class="datalightblue">
+ <ul>
+ <li>new examples not yet available, see tutorial in meantime</li>
+ </ul>
+ </TD>
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/menuSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/menuSummary.jsp
new file mode 100644
index 0000000..05a4416
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/menuSummary.jsp
@@ -0,0 +1,24 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>Menu</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>Build easily menus by specifying entries (or items) to be rendered, and layout used to
+ render them.</li>
+ <li>A menu entry can contains text, link, icon, tooltip, ...</li>
+ <li>Menu layout renders each entry according to properties set.</li>
+ <li> menu is inserted anywhere with the tag <em><tiles:insert name="menuName"></em></li>
+ <li>It is possible to change all menus look and feel simply by changing menu layout.
+ No need to change already defined entries.</li>
+ <li>All menus in this site are build using entries and menu layout.</li>
+ </ul>
+ </TD>
+ </TR>
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/multiChannelsSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/multiChannelsSummary.jsp
new file mode 100644
index 0000000..efb7c8a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/multiChannelsSummary.jsp
@@ -0,0 +1,28 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>Multi Channels</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>Tiles provide some facilities for "multi channels"</li>
+ <li>It is possible to define different Tiles for different channels.</li>
+ <li>Appropriate Tile is loaded according to channel key store somewhere (usually associated to current user)</li>
+ <li>Examples of channels : [html, wml, ...] or [gold, silver, bronze, ...]</li>
+ <li></li>
+ <li></li>
+ <li></li>
+ </ul>
+ </TD>
+ </TR>
+ <td class="datalightblue">
+ <ul>
+ <li>new examples not yet available, see tutorial in meantime</li>
+ </ul>
+ </TD>
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myLayoutSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myLayoutSummary.jsp
new file mode 100644
index 0000000..3d3a890
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myLayoutSummary.jsp
@@ -0,0 +1,26 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>User Customized Layout (Skins)</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>It is possible to change the main layout used by one site</li>
+ <li>Each layout shows the site in a differnent L&F</li>
+ </ul>
+ </TD>
+ </TR>
+ <TR>
+ <td class="datalightblue">
+ <ul>
+ <li>Change Layout
+ <BR><a href="<%=request.getContextPath()%>/examples/skinSettings.jsp">my Layout</a></li>
+ </ul>
+ </TD>
+ </TR>
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myMenuSettings.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myMenuSettings.jsp
new file mode 100644
index 0000000..f2fe370
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myMenuSettings.jsp
@@ -0,0 +1,113 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<%--
+ Render a page allowing user to customize its menu.
+ @param choiceItems Available menu entries proposed as choice
+ @param userItems Actual user menu entries
+--%>
+
+<script language="javaScript1.2">
+function selectAll( )
+{
+for( j=0; j<selectAll.arguments.length; j++ )
+ {
+ col1 = selectAll.arguments[j];
+ for(i=0; i<col1.options.length; i++ )
+ {
+ col1.options[ i ].selected = true;
+ }
+ } // end loop
+ return true;
+}
+
+function move( col1, col2)
+{
+ toMove = col1.options[ col1.selectedIndex ];
+ opt = new Option( toMove.text, toMove.value, false, false );
+ col1.options[col1.selectedIndex ] = null;
+ col2.options[col2.length] = opt;
+ col2.selectedIndex = col2.length-1;
+ return true;
+}
+
+function remove( col1)
+{
+ col1.options[ col1.selectedIndex ] = null;
+ return true;
+}
+
+function up( col1 )
+{
+ index = col1.selectedIndex;
+ if( index <= 0 )
+ return true;
+
+ toMoveX = col1.options[ index -1 ];
+ toMoveY = col1.options[ index ];
+ optX = new Option( toMoveX.text, toMoveX.value, false, false );
+ optY = new Option( toMoveY.text, toMoveY.value, false, false );
+ col1.options[index] = optX;
+ col1.options[index-1] = optY;
+ col1.selectedIndex = index-1;
+ return true;
+}
+
+function down( col1 )
+{
+ index = col1.selectedIndex;
+ if( index+1 >= col1.options.length )
+ return true;
+
+ toMoveX = col1.options[ index ];
+ toMoveY = col1.options[ index + 1 ];
+ optX = new Option( toMoveX.text, toMoveX.value, false, false );
+ optY = new Option( toMoveY.text, toMoveY.value, false, false );
+ col1.options[index] = optY;
+ col1.options[index+1] = optX;
+ col1.selectedIndex = index+1;
+
+ return true;
+}
+
+</script>
+
+<tiles:importAttribute name="catalog" />
+<tiles:importAttribute name="userItems" />
+
+<html:form action="/myMenuSettings.do" >
+
+ <ul>
+ <li>Choose an item from "Items Choice" colomn, and add it to "my Items" using the '>' button.</li>
+ <li>You can also rearange your Menu by using appropriate buttons : '^', 'V' and 'delete'</li>
+ <li>Validate your menu by clicking on 'validate' button. Load any page and check your menu !</li>
+ </ul>
+ <table align="center">
+ <tr>
+ <td align="right">
+ Items Choice
+ <br>
+ <html:select property="selectedChoices" multiple="true" >
+ <html:options collection="catalog" property="link" labelProperty="value"/>
+ </html:select>
+ </td>
+ <td>
+ <html:button property=">" value=">" onclick="move(selectedChoices,selected);return true;"/>
+ </td>
+ <td align="left">
+ My Items
+ <br>
+ <html:select property="selected" multiple="true" size="10">
+ <html:options collection="userItems" property="link" labelProperty="value"/>
+ </html:select>
+ <br>
+ <div align="center">
+ <html:button property="right" value="^" onclick="up(selected);return true;"/>
+ <html:button property="right" value="del" onclick="remove(selected);return true;"/>
+ <html:button property="right" value="v" onclick="down(selected);return true;"/>
+ <br>
+ <html:submit property="validate" value="validate" onclick="selectAll(selected);return true;"/></div>
+ </td>
+ </tr>
+ </table>
+</html:form>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myMenuSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myMenuSummary.jsp
new file mode 100644
index 0000000..ad97df5
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myMenuSummary.jsp
@@ -0,0 +1,35 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>User Customized Menu <br>(my Menu)</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>It is possible to allow user to customize its own menu.</li>
+ <li>User menu settings are stored in user session as a list of menu entries.</li>
+ <li>The same layout as other menus is used, but the list is provided by an associated
+ "controller".</li>
+ <li>You also need to provide a page allowing user to choose and arrange its own menu entries.</li>
+ <li>You can use provided example, or improve it to meet your need.</li>
+ </ul>
+ </TD>
+ </TR>
+ <TR>
+ <td class="datalightblue" >
+ <ul>
+ <li>Edit user menu entries :
+ <BR><a href="<%=request.getContextPath()%>/examples/myMenuSettings.jsp">my Menu</a></li>
+ <li>Actual user menu :
+ <BR><tiles:insert name="examples.userMenu" flush="true" /></li>
+ </ul>
+ </TD>
+ </TR>
+
+</TABLE>
+
+</b></font></div>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalPrefs.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalPrefs.jsp
new file mode 100644
index 0000000..1ead874
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalPrefs.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="myDynamicPortalPreferences" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalSettings.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalSettings.jsp
new file mode 100644
index 0000000..7cf6efa
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalSettings.jsp
@@ -0,0 +1,120 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+
+<script language="javaScript1.2">
+function selectAll( )
+{
+for( j=0; j<selectAll.arguments.length; j++ )
+ {
+ col1 = selectAll.arguments[j];
+ for(i=0; i<col1.options.length; i++ )
+ {
+ col1.options[ i ].selected = true;
+ }
+ } // end loop
+ return true;
+}
+
+function move( col1, col2)
+{
+ toMove = col1.options[ col1.selectedIndex ];
+ opt = new Option( toMove.text, toMove.value, false, false );
+ col1.options[col1.selectedIndex ] = null;
+ col2.options[col2.length] = opt;
+ col2.selectedIndex = col2.length-1;
+ return true;
+}
+
+function remove( col1)
+{
+ col1.options[ col1.selectedIndex ] = null;
+ return true;
+}
+
+function up( col1 )
+{
+ index = col1.selectedIndex;
+ if( index <= 0 )
+ return true;
+
+ toMoveX = col1.options[ index -1 ];
+ toMoveY = col1.options[ index ];
+ optX = new Option( toMoveX.text, toMoveX.value, false, false );
+ optY = new Option( toMoveY.text, toMoveY.value, false, false );
+ col1.options[index] = optX;
+ col1.options[index-1] = optY;
+ col1.selectedIndex = index-1;
+ return true;
+}
+
+function down( col1 )
+{
+ index = col1.selectedIndex;
+ if( index+1 >= col1.options.length )
+ return true;
+
+ toMoveX = col1.options[ index ];
+ toMoveY = col1.options[ index + 1 ];
+ optX = new Option( toMoveX.text, toMoveX.value, false, false );
+ optY = new Option( toMoveY.text, toMoveY.value, false, false );
+ col1.options[index] = optY;
+ col1.options[index+1] = optX;
+ col1.selectedIndex = index+1;
+
+ return true;
+}
+
+</script>
+
+
+<html:form action="/myPortalSettings.do" >
+
+
+
+ <html:select property="remaining" multiple="true" >
+ <html:options property="choices" labelProperty="choiceLabels" />
+ </html:select>
+
+ <html:button property="v" value="v" onclick="move(remaining,l0);return true;"/>
+ <br>
+
+ <table>
+ <tr>
+ <td>
+ <html:select property="l0" multiple="true" size="10">
+ <html:options property="col[0]" labelProperty="colLabels[0]"/>
+ </html:select>
+ </td>
+ <td>
+ <html:select property="l1" multiple="true" size="10">
+ <html:options property="col[1]" labelProperty="colLabels[1]"/>
+ </html:select>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">
+ <html:button property="right" value="^" onclick="up(l0);return true;"/>
+ <html:button property="right" value="del" onclick="remove(l0);return true;"/>
+ <html:button property="right" value="v" onclick="down(l0);return true;"/>
+ <html:button property="left" value=">" onclick="move(l0,l1);return false;" />
+ </td>
+ <td align="center">
+ <html:button property="right" value="<" onclick="move(l1,l0);return true;"/>
+ <html:button property="right" value="^" onclick="up(l1);return true;"/>
+ <html:button property="right" value="del" onclick="remove(l1);return true;"/>
+ <html:button property="right" value="v" onclick="down(l1);return true;"/>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center">
+
+ <html:submit property="validate" value="validate" onclick="selectAll(l0, l1);return true;"/>
+ </td>
+ </tr>
+ </table>
+
+
+
+
+</html:form>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalSummary.jsp
new file mode 100644
index 0000000..db2560d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/myPortalSummary.jsp
@@ -0,0 +1,31 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>User Customized Portal <br>(my Portal)</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>A portal can be customized by user. </li>
+ <li>To do so, build a portal, and add it a "controller" checking and setting
+ user choosen Tiles.</li>
+ <li>You also need to provide a page allowing user to choose and arrange its own Tiles.</li>
+ <li>You can use provided example, or improve it to meet your need.</li>
+ </ul>
+ </TD>
+ </TR>
+ <TR>
+ <td class="datalightblue">
+ <ul>
+ <li>View portal
+ <BR><a href="<%=request.getContextPath()%>/examples/myPortal.jsp">my Portal</a></li>
+ <li>Customize your portal page
+ <BR><a href="<%=request.getContextPath()%>/examples/myPortalSettings.jsp">my Portal Settings</a></li>
+ </ul>
+ </TD>
+ </TR>
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/mySkinSettings.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/mySkinSettings.jsp
new file mode 100644
index 0000000..66e0281
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/mySkinSettings.jsp
@@ -0,0 +1,44 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+
+<tiles:importAttribute name="catalog" />
+<tiles:useAttribute name="selected" />
+
+<html:form action="/mySkinSettings.do" >
+
+
+
+
+ <ul>
+ <li>Current skin is highlighted.</li>
+ <li>Select and validate to change skin</li>
+ <li>Reload page to see result</li>
+ </ul>
+ <table align="center">
+ <tr>
+ <td align="right">
+ Available Skins
+ <br>
+ <html:select property="selected" multiple="false" value="<%=(String)selected%>" >
+ <html:options name="catalog" property="keys" labelName="catalog" labelProperty="names" />
+ </html:select>
+
+ </td>
+ <td align="left">
+ <html:submit property="validate" value="validate" /></div>
+ </td>
+ </tr>
+ </table>
+ <ul>
+ <li>In the examples, only this page is affected by skin change.
+ </li>
+ <li>It is possible to affect all pages by changing
+ root layout definition in configuration file.
+ </li>
+ </ul>
+
+
+
+
+</html:form>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert1.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert1.jsp
new file mode 100644
index 0000000..679863e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert1.jsp
@@ -0,0 +1 @@
+<IMG src='<%=request.getContextPath()%>/tutorial/images/banner1b.gif' border=0>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert2.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert2.jsp
new file mode 100644
index 0000000..c35d5a2
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert2.jsp
@@ -0,0 +1,2 @@
+<DIV align=center><STRONG><FONT size=4><IMG alt="" border=0 height=120
+src="<%=request.getContextPath()%>/tutorial/images/banner_bottom.gif" width=300></FONT></STRONG></DIV>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert3.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert3.jsp
new file mode 100644
index 0000000..679863e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/advert3.jsp
@@ -0,0 +1 @@
+<IMG src='<%=request.getContextPath()%>/tutorial/images/banner1b.gif' border=0>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/login.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/login.jsp
new file mode 100644
index 0000000..1c5d81e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/login.jsp
@@ -0,0 +1,10 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=300>
+
+ <TR>
+ <TD class=spanhd>Login</TD></TR>
+ <TR>
+ <TD class=yellow><!-- IF statement for Alert section here -->
+ <P>If you have World Financial accounts, you can <U>Login</U> to
+ view your account information.<BR>
+</P></TD></TR></TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/messages.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/messages.jsp
new file mode 100644
index 0000000..f10ee1b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/messages.jsp
@@ -0,0 +1,19 @@
+<DIV align=center><STRONG><FONT size=4>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=300>
+
+ <TR>
+ <TD class=spanhd><B>Messages</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Your CD matures in one month!</U></FONT>
+ <LI><FONT color=#003366><U>Now Providing a Technology Mutual Fund</U></FONT>
+ <LI><FONT color=#003366><U>Children's Savings Account Program
+ Update</U></FONT>
+ <LI><FONT color=#003366><U>Small Business Program Offer</U></FONT>
+ <LI><FONT color=#003366><U>Financial Tip of the Day</U></FONT>
+ <LI><FONT color=#003366><U>Mortgage Rate Chart - See how we
+ compare!</U></FONT>
+ <LI><FONT color=#003366><U>Check out our 1-year and 6-month CD
+ rates</U></FONT>
+ <LI><FONT color=#003366><U>Auto Insurance Rates Lowered</U></FONT>
+ <BR> </LI></TD></TR></TABLE></FONT></STRONG></DIV>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/newsFeed.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/newsFeed.jsp
new file mode 100644
index 0000000..eccdd74
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/newsFeed.jsp
@@ -0,0 +1,42 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=300>
+
+ <TR>
+ <TD class=spanhd colSpan=2>News Feed</TD></TR>
+ <TR>
+ <TD class=data><B>Business News</B> </TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Top Fund Managers Make Their Calls On
+ Funds</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>World News</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>China Democracy Crackdown</U></FONT>
+ <LI><FONT color=#003366><U>Pope Visits The U.S. In
+ May</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>General News</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Clinton Polls in Question As To
+ Accuracy</U></FONT>
+ <LI><FONT color=#003366><U>School Violence Erupts And Safety Questions Are
+ Raised</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>Sports</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Winners And Losers - NFL Season
+ Wrap-Up</U></FONT>
+ <LI><FONT color=#003366><U>Ski Finals On The Wire For The Alpine
+ Championships</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>Health</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Tea - A Cup of Comfort</U></FONT>
+ <LI><FONT color=#003366><U>Relieve Stress The Natural Way: 10 Health
+ Tips</U></FONT> </LI></TD></TR>
+</TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/portalBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/portalBody.jsp
new file mode 100644
index 0000000..ede038b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/portalBody.jsp
@@ -0,0 +1,18 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/layout/columnsLayout.jsp" flush="true">
+ <tiles:put name="numCols" value="2" />
+ <tiles:putList name="list0" >
+ <tiles:add value="/tutorial/portal/login.jsp" />
+ <tiles:add value="/tutorial/portal/messages.jsp" />
+ <tiles:add value="/tutorial/portal/newsFeed.jsp" />
+ <tiles:add value="/tutorial/portal/advert2.jsp" />
+ </tiles:putList>
+ <tiles:putList name="list1" >
+ <tiles:add value="/tutorial/portal/advert3.jsp" />
+ <tiles:add value="/tutorial/portal/stocks.jsp" />
+ <tiles:add value="/tutorial/portal/whatsNew.jsp" />
+ <tiles:add value="/tutorial/portal/personalLinks.jsp" />
+ <tiles:add value="/tutorial/portal/search.jsp" />
+ </tiles:putList>
+</tiles:insert>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/stocks.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/stocks.jsp
new file mode 100644
index 0000000..0323cde
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/stocks.jsp
@@ -0,0 +1,59 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=190>
+
+ <TR bgColor=#ffffff>
+ <TD class=spanhd colSpan=2>Stewart's Hot Stocks</TD>
+ <TD class=spanhd> </TD></TR>
+ <TR>
+ <TD class=hdleft>Symbol</TD>
+ <TD class=hdleft>Price</TD>
+ <TD class=hdleft>Change</TD></TR>
+ <TR>
+ <TD class=datagrey><U><FONT color=#003366>AOL</FONT></U></TD>
+ <TD class=datagrey>104.25</TD>
+ <TD class=datagrey><FONT color=#cc0000>5.00</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>CSCO</U></FONT></TD>
+ <TD class=datagrey>73.75</TD>
+ <TD class=datagrey><FONT color=#008800>1.75</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>HD</U></FONT></TD>
+ <TD class=datagrey>68.62</TD>
+ <TD class=datagrey><FONT color=#008800>1.69</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>SONE</U></FONT></TD>
+ <TD class=datagrey>38.88</TD>
+ <TD class=datagrey><FONT color=#008800>1.62</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>DJIA</U></FONT></TD>
+ <TD class=datagrey>10,302.13</TD>
+ <TD class=datagrey><FONT color=#008800>47.80</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=inputgrey colSpan=3>
+ <FORM
+ action="#" method="get">Quote:
+ <INPUT maxLength=5 size=4> <A
+ href="#"><IMG alt="Get Quote"
+ border=0 height=17 src="<%=request.getContextPath()%>/tutorial/images/input_vrm_gen_get.gif" title="Get Quote"
+ width=59></A> <BR> <BR>
+ <CENTER><FONT size=-2>[ </FONT><FONT color=#003366 size=-2><A
+ href="#">Symbol Search</A></FONT><FONT
+ size=-2> ]</FONT> <FONT size=-2>[ </FONT><FONT
+ color=#003366 size=-2><U>Edit Portfolio</U></FONT><FONT
+ size=-2> ]</FONT></CENTER><BR></TD></TR></TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/whatsNew.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/whatsNew.jsp
new file mode 100644
index 0000000..cdbb31c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portal/whatsNew.jsp
@@ -0,0 +1,26 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=190>
+
+ <TR>
+ <TD class=spanhd>What's New</TD>
+ </TR>
+ <TR>
+ <TD class=datagrey><B>New Financial Calculators</B> <BR>Saving For A
+ College Education?
+ <BR>[ <FONT color=#003366><U>More</U></FONT> ]
+ <BR> <BR><B>Special Offer</B>
+ <BR>Get free real-time quotes for three months with a World Financial
+ brokerage account. [ <FONT color=#003366><U>More</U></FONT> ]
+ <BR>
+ </TD>
+ </TR>
+ <TR>
+ <td>
+ <BR><IMG border=0 height=1 src="<%=request.getContextPath()%>/tutorial/images/clear.gif" width=190>
+ </TD>
+ </TR>
+
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portalSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portalSummary.jsp
new file mode 100644
index 0000000..7f69b28
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/portalSummary.jsp
@@ -0,0 +1,24 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border=0 cellPadding=2 cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>Portal</TD>
+ </TR>
+ <TR>
+ <TD class=datagrey>
+ <ul>
+ <li>A portal is built by assembling Tiles in columns.</li>
+ <li>A special layout exists
+ to do such think.</li>
+ <li>This page is an example of a portal.</li>
+ <li>To realize your portal, you specify which Tiles you want to be render in which columns.
+ This is done in centralized definition file or in <insert> tag.</li>
+ <li><a href="<%=request.getContextPath()%>/examples/portal.jsp">Other portal example</a></li>
+ </ul>
+ </TD>
+ </TR>
+
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannelErrors.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannelErrors.jsp
new file mode 100644
index 0000000..8b292b2
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannelErrors.jsp
@@ -0,0 +1,27 @@
+<%--
+/**
+ * Summarize channels errors as unadorned HTML.
+ *
+ * @parameters errors
+ * @version $Revision: 1.2 $ $Date$
+ */
+--%>
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<TABLE border="0" cellspacing="2" cellpadding="4" width="300" align="center" >
+<TR>
+<TD class="alert">
+Error while reading channels.
+<br></br>Are you connected ?
+</TD>
+</TR>
+<TR>
+<TD class="error" width="100%"><html:errors/></TD>
+</TR>
+
+</TABLE>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannels.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannels.jsp
new file mode 100644
index 0000000..57a1d0b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannels.jsp
@@ -0,0 +1,45 @@
+<%--
+/**
+ * Summarize channels as unadorned HTML.
+ *
+ * @param CHANNELS List of channels
+ * @version $Revision: 1.2 $ $Date$
+ */
+--%>
+
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<div align="center"><font size="+1"><b>
+
+<tiles:importAttribute name="CHANNELS" scope="page"/>
+
+<logic:iterate name="CHANNELS" id="CHANNEL" >
+<TABLE border="0" cellspacing="0" cellpadding="4" width="100%" align="center" >
+<TR>
+<TD class="spanhd" ><logic:present name="CHANNEL" property="image">
+ <a href="<bean:write name="CHANNEL" property="link"/>">
+ <img src="<bean:write name="CHANNEL" property="image.URL"/>"></logic:present></a>
+</TD>
+<TD class="spanhd" width="100%"><bean:write name="CHANNEL" property="title"/> <a href="<bean:write name="CHANNEL" property="link"/>">[home]</a></TD>
+</TR>
+<TD class="yellow" colspan="2"><bean:write name="CHANNEL" property="description"/></TD>
+</TR>
+
+<TR>
+<TD class="datagrey" colspan="2">
+<logic:iterate name="CHANNEL" property="items" id="ITEM">
+<br><b><bean:write name="ITEM" property="title"/></b>
+<br><bean:write name="ITEM" property="description"/>
+<br> [ <a href="<bean:write name="ITEM" property="link"/>">more</a> ]
+<br>
+</logic:iterate>
+</TD>
+</TR>
+</TABLE>
+<br>
+</logic:iterate>
+
+</b></font></div>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannelsSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannelsSummary.jsp
new file mode 100644
index 0000000..f9bc362
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/rssChannelsSummary.jsp
@@ -0,0 +1,28 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class="spanhd">Rss Channels</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>This example shows how to do a Rss Channels Tile.</li>
+ <li>The Tile is made of a controller loading the requested rss channels,
+ and a view (jsp page) rendering the loaded channels.</li>
+ <li>It is possible to change the rendering page to adapt it to your need.</li>
+ <li>Channels URLs are set in config files, or as http request parameters.</li>
+ </ul>
+ </TD>
+ </TR>
+ <TR>
+ <td class="datalightblue">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/examples/rssChannels.jsp">Rss Channels</a></li>
+ </ul>
+ </TD>
+ </TR>
+</TABLE>
+
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/tabsSummary.jsp b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/tabsSummary.jsp
new file mode 100644
index 0000000..6aa73d4
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/examples/tiles/tabsSummary.jsp
@@ -0,0 +1,31 @@
+<div align="center"><font size="+1"><b>
+
+<TABLE border="0" cellPadding="2" cellSpacing=0 width="100%" >
+
+ <TR>
+ <TD class=spanhd>Tabs Layout</TD>
+ </TR>
+ <TR>
+ <TD class="datagrey">
+ <ul>
+ <li>You can easily build tabs by using predefined "tabs layout".</li>
+ <li>All you need to do is to specify which bodies you want to render in tabs.</li>
+ <li>You can also associate
+ name, icon and tooltip to tab index.</li>
+ <li>Using provided example, you can easily customize the tabs layout rendering.</li>
+ </ul>
+ </TD>
+ </TR>
+ <TR>
+ <td class="datalightblue">
+ <ul>
+ <li>Selected pages tabs
+ <BR><a href="<%=request.getContextPath()%>/examples/tabs.jsp">Pages Tabs</a></li>
+ <li>View examples Summaries as tabs
+ <BR><a href="<%=request.getContextPath()%>/examples/summariesTabs.jsp">Summaries Tabs</a></li>
+ <li></li>
+ </ul>
+ </TD>
+ </TR>
+</table>
+</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/images/asf-logo.gif b/struts-sandbox/tiles-documentation/src/webapp/images/asf-logo.gif
new file mode 100644
index 0000000..22eb9d7
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/images/asf-logo.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/images/struts-power.gif b/struts-sandbox/tiles-documentation/src/webapp/images/struts-power.gif
new file mode 100644
index 0000000..5f4e9d4
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/images/struts-power.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/images/struts.gif b/struts-sandbox/tiles-documentation/src/webapp/images/struts.gif
new file mode 100644
index 0000000..06388f1
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/images/struts.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/index.jsp b/struts-sandbox/tiles-documentation/src/webapp/index.jsp
new file mode 100644
index 0000000..acb2584
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/index.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="doc.mainLayout" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layout/classicLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layout/classicLayout.jsp
new file mode 100644
index 0000000..a6ae1b0
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layout/classicLayout.jsp
@@ -0,0 +1,37 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ parameters : title, header, menu, body, footer
+--%>
+<HTML>
+ <HEAD>
+ <title><tiles:getAsString name="title"/></title>
+ </HEAD>
+
+<body bgcolor="#ffffff" text="#000000" link="#023264" alink="#023264" vlink="#023264">
+<table border="0" width="100%" cellspacing="5">
+<tr>
+ <td colspan="2"><tiles:insert attribute="header" /></td>
+</tr>
+<tr>
+ <td width="140" valign="top">
+ <tiles:insert attribute='menu'/>
+ </td>
+ <td valign="top" align="left">
+ <tiles:insert attribute='body' />
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+ <hr>
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+ <tiles:insert attribute="footer" />
+ </td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layout/columnsLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layout/columnsLayout.jsp
new file mode 100644
index 0000000..15f4859
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layout/columnsLayout.jsp
@@ -0,0 +1,39 @@
+<%@ page import="org.apache.struts.tiles.ComponentContext"%>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ Render a list on severals columns
+ parameters : numCols, list0, list1, list2, list3, ...
+--%>
+
+<tiles:useAttribute id="numColsStr" name="numCols" classname="java.lang.String" />
+
+
+<table>
+<tr>
+<%
+int numCols = Integer.parseInt(numColsStr);
+ComponentContext context = ComponentContext.getContext( request );
+for( int i=0; i<numCols; i++ )
+ {
+ java.util.List list=(java.util.List)context.getAttribute( "list" + i );
+ pageContext.setAttribute("list", list );
+ if(list==null)
+ System.out.println( "list is null for " + i );
+%>
+<td valign="top">
+ <tiles:insert page="/layout/vboxLayout.jsp" flush="true" >
+ <tiles:put name="componentsList" beanName="list" beanScope="page" />
+ </tiles:insert>
+</td>
+<%
+ } // end loop
+%>
+</tr>
+</table>
+
+
+
+
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layout/vboxLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layout/vboxLayout.jsp
new file mode 100644
index 0000000..762dd69
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layout/vboxLayout.jsp
@@ -0,0 +1,25 @@
+<%@ page import="java.util.Iterator"%>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ Render a list on severals columns
+ parameters : componentsList
+--%>
+
+<tiles:useAttribute id="list" name="componentsList" classname="java.util.List" />
+
+<%-- Next will be a tag, as soon as tags allow include in iteration
+ Wait until jsp1.3 --%>
+<%
+Iterator i=list.iterator();
+while( i.hasNext() )
+ {
+ String comp=(String)i.next();
+%>
+<tiles:insert name="<%=comp%>" flush="true" />
+<br>
+
+<%
+ } // end loop
+%>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/centerLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/centerLayout.jsp
new file mode 100644
index 0000000..e80e5d4
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/centerLayout.jsp
@@ -0,0 +1,34 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Centered Layout Tiles
+ This layout render a header, left tile, right tile, body and footer.
+ It doesn't create <html> and <body> tag.
+ @param header Header tile (jsp url or definition name)
+ @param right Right center tile (optional)
+ @param body Body or center tile
+ @param left Left center tile (optional)
+ @param footer Footer tile
+--%>
+
+<table border="0" width="100%" cellspacing="5">
+<tr>
+ <td colspan="3"><tiles:insert attribute="header" /></td>
+</tr>
+<tr>
+ <td width="140" valign="top">
+ <tiles:insert attribute=right ignore='true'/>
+ </td>
+ <td valign="top" align="left">
+ <tiles:insert attribute='body' />
+ </td>
+ <td valign="top" align="left">
+ <tiles:insert attribute='left' ignore='true'/>
+ </td>
+</tr>
+<tr>
+ <td colspan="3">
+ <tiles:insert attribute="footer" />
+ </td>
+</tr>
+</table>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/classicLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/classicLayout.jsp
new file mode 100644
index 0000000..bbbf1a3
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/classicLayout.jsp
@@ -0,0 +1,40 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout Tiles
+ This layout create a html page with <header> and <body> tags. It render
+ a header, left menu, body and footer tile.
+ @param title String use in page title
+ @param header Header tile (jsp url or definition name)
+ @param menu Menu
+ @param body Body
+ @param footer Footer
+--%>
+<HTML>
+ <HEAD>
+ <link rel=stylesheet href="<%=request.getContextPath()%>/layouts/stylesheet.css" type="text/css">
+ <title><tiles:getAsString name="title"/></title>
+
+ </HEAD>
+
+<body bgcolor="#ffffff" text="#000000" link="#023264" alink="#023264" vlink="#023264">
+<table border="0" width="100%" cellspacing="5">
+<tr>
+ <td colspan="2"><tiles:insert attribute="header" /></td>
+</tr>
+<tr>
+ <td width="140" valign="top">
+ <tiles:insert attribute='menu'/>
+ </td>
+ <td valign="top" align="left">
+ <tiles:insert attribute='body' />
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+ <tiles:insert attribute="footer" />
+ </td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/columnsLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/columnsLayout.jsp
new file mode 100644
index 0000000..fbc9a63
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/columnsLayout.jsp
@@ -0,0 +1,47 @@
+<%@ page import="org.apache.struts.tiles.ComponentContext"%>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Multi-columns Layout
+ This layout render lists of tiles in multi-columns. Each column renders its tiles
+ vertically stacked.
+ The number of columns passed in parameter must correspond to the number of list passed.
+ Each list contains tiles. List are named list0, list1, list2, ...
+ parameters : numCols, list0, list1, list2, list3, ...
+ @param numCols Number of columns to render and passed as parameter
+ @param list1 First list of tiles (url or definition name)
+ @param list2 Second list of tiles (url or definition name) [optional]
+ @param list3 Third list of tiles (url or definition name) [optional]
+ @param listn Niene list of tiles (url or definition name), where n is replaced by column index.
+--%>
+
+
+<tiles:useAttribute id="numColsStr" name="numCols" classname="java.lang.String" />
+
+<table>
+<tr>
+<%
+int numCols = Integer.parseInt(numColsStr);
+ComponentContext context = ComponentContext.getContext( request );
+for( int i=0; i<numCols; i++ )
+ {
+ java.util.List list=(java.util.List)context.getAttribute( "list" + i );
+ pageContext.setAttribute("list", list );
+ if(list==null)
+ System.out.println( "list is null for " + i );
+%>
+<td valign="top">
+ <tiles:insert page="/layouts/vboxLayout.jsp" flush="true" >
+ <tiles:put name="list" beanName="list" beanScope="page" />
+ </tiles:insert>
+</td>
+<%
+ } // end loop
+%>
+</tr>
+</table>
+
+
+
+
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/menu.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/menu.jsp
new file mode 100644
index 0000000..d8e7e5c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/menu.jsp
@@ -0,0 +1,52 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ page import="java.util.Iterator" %>
+
+
+<%-- Menu Layout
+ This layout render a menu with links.
+ It takes as parameter the title, and a list of items. Each item is a bean with following properties :
+ value, href, icon, tooltip.
+ @param title Menu title
+ @param items list of items. Items are beans whith following properties :
+ --%>
+
+
+
+<%-- Push tiles attributes in page context --%>
+<tiles:importAttribute />
+
+<table>
+<logic:present name="title">
+<tr>
+ <th colspan=2>
+ <div align="left"><strong><tiles:getAsString name="title"/></strong></div>
+ </th>
+</tr>
+</logic:present>
+
+<%-- iterate on items list --%>
+<logic:iterate id="item" name="items" type="org.apache.struts.tiles.beans.MenuItem" >
+
+<% // Add site url if link start with "/"
+ String link = item.getLink();
+ if(link.startsWith("/") ) link = request.getContextPath() + link;
+%>
+<tr>
+ <td width="10" valign="top" ></td>
+ <td valign="top" >
+ <font size="-1"><a href="<%=link%>">
+<logic:notPresent name="item" property="icon"><%=item.getValue()%></logic:notPresent>
+<logic:present name="item" property="icon">
+ <% // Add site url if link start with "/"
+ String icon = item.getIcon();
+ if(icon.startsWith("/") ) icon = request.getContextPath() + icon;
+ %>
+<img src='<%=request.getContextPath()%><bean:write name="item" property="icon" scope="page"/>'
+ alt='<bean:write name="item" property="tooltip" scope="page" ignore="true"/>' /></logic:present></a>
+ </font>
+ </td>
+</tr>
+</logic:iterate>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/nestedTabsLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/nestedTabsLayout.jsp
new file mode 100644
index 0000000..f326e2f
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/nestedTabsLayout.jsp
@@ -0,0 +1,106 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%--
+ Tabs Layout .
+ This layout allows to render several tiles in a tabs fashion. Such tabs can be nested: a tab level can contain nested tabs. Each tabs must be declared with a different parameter name.
+ Implementation store each tabs selection index in the session context. The unique id for the
+ session attribut is compute from the url and the tabs selection parameter.
+ [todo] Improve the computation of unique id.
+ @param tabList A list of available tabs. We use MenuItem to carry data (name, body, icon, ...)
+ @param selectedIndex Index of default selected tab
+ @param parameterName Name of parameter carrying selected info in http request.
+--%>
+
+<%--
+Use tiles attributes, and declare them as page java variable.
+These attribute must be passed to the tile.
+--%>
+
+<tiles:useAttribute name="parameterName" classname="java.lang.String" />
+<tiles:useAttribute id="selectedIndexStr" name="selectedIndex" ignore="true" classname="java.lang.String" />
+<tiles:useAttribute name="tabList" classname="java.util.List" />
+<%
+ String selectedColor="#98ABC7";
+ String notSelectedColor="#C0C0C0";
+
+ int index = 0; // Loop index
+ int selectedIndex = 0;
+ // Check if selected come from request parameter
+ try {
+ selectedIndex = Integer.parseInt(selectedIndexStr);
+ // Try to retrieve from http parameter, or previous storage
+ // Need to use a more unique id for storage name
+ String paramValue = request.getParameter( parameterName );
+ if( paramValue == null )
+ {
+ selectedIndex = ((Integer)(session.getAttribute(
+ request.getRequestURI() + parameterName ))).intValue();
+ }
+ else
+ selectedIndex = Integer.parseInt(paramValue);
+ }
+ catch( java.lang.NumberFormatException ex )
+ { // do nothing
+ }
+ catch( java.lang.NullPointerException ex )
+ { // do nothing
+ }
+ // Check selectedIndex bounds
+ if( selectedIndex < 0 || selectedIndex >= tabList.size() ) selectedIndex = 0;
+ String selectedBody = ((org.apache.struts.tiles.beans.MenuItem)tabList.get(selectedIndex)).getLink(); // Selected body
+ // Store selected index for future references
+ session.setAttribute( request.getRequestURI() + parameterName , new Integer(selectedIndex) );
+%>
+
+<table border="0" cellspacing="0" cellpadding="0">
+ <%-- Draw tabs --%>
+<tr>
+ <td width="10"> </td>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+<logic:iterate id="tab" name="tabList" type="org.apache.struts.tiles.beans.MenuItem" >
+<% // compute href
+ String href = request.getRequestURI() + "?"+parameterName + "=" + index;
+ String color = notSelectedColor;
+ if( index == selectedIndex )
+ {
+ selectedBody = tab.getLink();
+ color = selectedColor;
+ } // enf if
+ index++;
+%>
+ <td bgcolor="<%=color%>">
+ <a href="<%=href%>" ><%=tab.getValue()%></a>
+ </td>
+ <td width="1" ></td>
+
+</logic:iterate>
+ </tr>
+ </table>
+ </td>
+ <td width="10" > </td>
+</tr>
+
+
+<tr>
+ <td height="5" bgcolor="<%=selectedColor%>" colspan="3" > </td>
+</tr>
+
+ <%-- Draw body --%>
+<tr>
+ <td width="10" bgcolor="<%=selectedColor%>"> </td>
+ <td>
+ <tiles:insert name="<%=selectedBody%>" flush="true" />
+ </td>
+ <td width="10" bgcolor="<%=selectedColor%>"> </td>
+</tr>
+
+<tr>
+ <td height="5" bgcolor="<%=selectedColor%>" colspan="3" > </td>
+</tr>
+
+</table>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/skin1/menuLeftLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/skin1/menuLeftLayout.jsp
new file mode 100644
index 0000000..95866fc
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/skin1/menuLeftLayout.jsp
@@ -0,0 +1,40 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout Tiles
+ This layout create a html page with <header> and <body> tags. It render
+ a header, left menu, body and footer tile.
+ @param title String use in page title
+ @param header Header tile (jsp url or definition name)
+ @param menu Menu
+ @param body Body
+ @param footer Footer
+--%>
+<HTML>
+ <HEAD>
+ <link rel=stylesheet href="<%=request.getContextPath()%>/layouts/stylesheet.css" type="text/css">
+ <title><tiles:getAsString name="title"/></title>
+
+ </HEAD>
+
+<body bgcolor="#C0C0C0" text="#000000" link="#023264" alink="#023264" vlink="#023264">
+<table border="0" width="100%" cellspacing="5">
+<tr>
+ <td colspan="2"><tiles:insert attribute="header" /></td>
+</tr>
+<tr>
+ <td valign="top" align="left">
+ <tiles:insert attribute='body' />
+ </td>
+ <td width="140" valign="top">
+ <tiles:insert attribute='menu'/>
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+ <tiles:insert attribute="footer" />
+ </td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/stylesheet.css b/struts-sandbox/tiles-documentation/src/webapp/layouts/stylesheet.css
new file mode 100644
index 0000000..6ad8bd8
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/stylesheet.css
@@ -0,0 +1,255 @@
+/* CSS */
+
+/* base element inheritance formatting */
+body { margin-left: 0px; margin-right: 0px;
+ margin-top: 0px; margin-bottom: 0px;
+ font-family: arial, geneva, helvetica, "sans serif"; }
+a { font-weight: bold; } /* all links are bold */
+a:link { color: #3300cc } /* unvisited link */
+a:visited { color: #330099 } /* visited links */
+a:active { color: #000033 } /* active links */
+a:hover { color: #000033 } /* MSIE rollover links */
+table { margin-left: 0px; margin-right: 0px;
+ margin-top: 0px; margin-bottom: 0px; }
+td { font-family: arial, geneva, helvetica, "sans serif"; }
+th { font-family: arial, geneva, helvetica, "sans serif";
+ font-weight: bold; }
+
+/* begin defined classes */
+
+/* headline classes */
+.headline { font-family: verdana, arial, geneva, "sans serif";
+ font-size: 110%; color: #000000;
+ vertical-align: middle; text-align: left; }
+
+/* on-screen hint class */
+.hint { font-size: x-small;
+ color: #000000; background: #ffffff; }
+.hintvbm { font-size: x-small; }
+
+/* Message classes */
+.note { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.noteimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+.success { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.successimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+.alert { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.alertimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+.error { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.errorimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+
+/* column header classes */
+.hdleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: left; }
+.hdright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.hdmiddle { font-size: smaller; color: #333333; background: #cccccc;
+ text-align: center; }
+.datahd { font-size: smaller; font-weight: bold;
+ color: #000000; background: #cccccc; }
+.spanhd { font-size: smaller; font-weight: bold;
+ color: #eeeeee; background: #003366;
+ text-align: left; }
+.spanhdright { font-size: smaller; font-weight: bold;
+ color: #eeeeee; background: #003366;
+ text-align: right; }
+.spanhdcenter { font-size: smaller; font-weight: bold;
+ color: #eeeeee; background: #003366;
+ text-align: center; }
+.subhdleft { font-size: x-small; color: #333333; background: #cccccc;
+ text-align: left; }
+
+/* label classes */
+.right { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.topright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ vertical-align: top; text-align: right; }
+.left { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ text-align: left; }
+.topleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ vertical-align: top; text-align: left; }
+.center { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ text-align: center; }
+.greyright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.greyleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ text-align: left; }
+.greycenter { font-size: smaller; font-weight: bold;
+ color: #333333; background: #eeeeee;
+ text-align: center; }
+.greytopright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ vertical-align: top; text-align: right; }
+.greytopleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ vertical-align: top; text-align: left; }
+ /* remove after changing subright use to fine */
+.greysubright { font-size: x-small; color: #333333; background: #cccccc;
+ text-align: right; font-weight: normal; }
+
+
+/* data classes and alternating row color classes */
+.data { font-size: smaller;
+ color: #000000; background: #ffffff; }
+.datamiddle { font-size: smaller;
+ color: #000000; background: #ffffff; vertical-align: middle }
+.datagrey { font-size: smaller;
+ color: #000000; background: #eeeeee; }
+.datalightblue {
+ font-size: smaller;
+ color: #000000;
+ background: #E1F8F9;
+}
+.bdata { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff; }
+.bdatagrey { font-size: smaller; font-weight: bold;
+ color: #000000; background: #eeeeee; }
+.datart { font-size: smaller;
+ color: #000000; background: #ffffff;
+ text-align: right; }
+.datartgrey { font-size: smaller;
+ color: #000000; background: #eeeeee;
+ text-align: right; }
+.bdatart { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ text-align: right; }
+.bdatartgrey { font-size: smaller; font-weight: bold;
+ color: #000000; background: #eeeeee;
+ text-align: right; }
+.curr { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ text-align: right; }
+.currgrey { font-size: smaller; font-weight: bold;
+ color: #000000; background: #eeeeee;
+ text-align: right; }
+.currleft { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ text-align: left; }
+.color { color: #800000; } /*change to 000000 if FI doesn't want negative numbers to be red*/
+.subdata { font-size: x-small; color: #000000; background: #ffffff }
+.subdatagrey { font-size: x-small; color: #000000; background: #eeeeee }
+.dataright { font-size: smaller; color: #000000; background: #ffffff; text-align: right;}
+.datagreyright { font-size: smaller; color: #000000; background: #eeeeee; text-align: right;}
+.yellow { font-size: smaller; color: #000000; background: #ffffcc;
+ vertical-align: middle; text-align: left; }
+
+
+
+/* vrm classes and account balance classes */
+.subcurr { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.editorial { font-size: smaller;
+ color: #000000; background: #ffffff; }
+.editgrey { font-size: smaller;
+ color: #000000; background: #eeeeee; }
+
+
+/* fine print for inputs and tables */
+.fine { font-size: x-small; font-weight: normal;
+ color: #333333; }
+.fineright { font-size: x-small; font-weight: normal;
+ color: #333333;
+ text-align: right; }
+.finewhite { font-size: x-small; font-weight: normal; color: #000000; background: #ffffff; }
+.subright { font-size: x-small; font-weight: normal;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+
+/* form element cell classes */
+.input { font-size: smaller;
+ background: #ffffff;
+ vertical-align: baseline; }
+.topinput { font-size: smaller;
+ background: #ffffff;
+ vertical-align: top; }
+.btminput { font-size: smaller;
+ background: #ffffff;
+ vertical-align: bottom; }
+.inputgrey { font-size: smaller;
+ background: #eeeeee;
+ vertical-align: baseline; }
+.submit { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ vertical-align: middle; text-align: right; }
+.submitgrey { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ vertical-align: middle; text-align: right; }
+.inputtop { font-size: smaller;
+ vertical-align: top; background: #ffffff; }
+
+/* help classes */
+.help { font-family: arial, helvetica, "sans serif";
+ font-size: smaller;
+ color: #666666; background: #ffffcc; }
+
+/* navigation bar classes */
+.navtext { font-size: x-small;
+ color: #000066;
+ text-align: right; }
+.info { font-size: x-small;
+ color: #000066; background: #eeeeee; }
+.infotext { padding-left: 2pt; }
+
+/* footer classes */
+.footlt { font-size: x-small;
+ color: #333333; background: #cccccc; }
+.footdk { font-size: x-small;
+ color: #cccccc; background: #333333; }
+
+/* background packing classes */
+.bkgnd { font-size: 1pt; }
+.wtspace { font-size: 1pt; background: #ffffff; }
+.greyspace { font-size: 1pt; background: #eeeeee; }
+.yellowspace { font-size: 1pt; background: #ffffcc; }
+.bottom { vertical-align: bottom; }
+
+
+
+/* additional VIM classes */
+.yellowbar { font-size: smaller; background: #ffffcc;
+ text-align: left; }
+
+.yellowbarrt { font-size: smaller; background: #ffffcc;
+ text-align: right; }
+
+.yellowspace { font-size: 4pt; background: #ffffcc; }
+
+.datacntr { font-size: smaller;
+ color: #000000; background: #ffffff; text-align: center; }
+
+.datacntrgrey { font-size: smaller;
+ color: #000000; background: #eeeeee; text-align: center; }
+
+.hdctr { font-size: smaller; font-weight: bold; color: #333333;
+ background: #cccccc; text-align: center;}
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/tabsLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/tabsLayout.jsp
new file mode 100644
index 0000000..94fc7e4
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/tabsLayout.jsp
@@ -0,0 +1,94 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%--
+ Tabs Layout .
+ This layout allows to render several tiles in a tabs fashion.
+ @param tabList A list of available tabs. We use MenuItem to carry data (name, body, icon, ...)
+ @param selectedIndex Index of default selected tab
+ @param parameterName Name of parameter carrying selected info in http request.
+--%>
+
+<%--
+Use tiles attributes, and declare them as page java variable.
+These attribute must be passed to the tile.
+--%>
+
+<tiles:useAttribute name="parameterName" classname="java.lang.String" />
+<tiles:useAttribute id="selectedIndexStr" name="selectedIndex" ignore="true" classname="java.lang.String" />
+<tiles:useAttribute name="tabList" classname="java.util.List" />
+<%
+ String selectedColor="#98ABC7";
+ String notSelectedColor="#C0C0C0";
+
+ int index = 0; // Loop index
+ int selectedIndex = 0;
+ // Check if selected come from request parameter
+ try {
+ selectedIndex = Integer.parseInt(selectedIndexStr);
+ selectedIndex = Integer.parseInt(request.getParameter( parameterName ));
+ }
+ catch( java.lang.NumberFormatException ex )
+ { // do nothing
+ }
+ // Check selectedIndex bounds
+ if( selectedIndex < 0 || selectedIndex >= tabList.size() ) selectedIndex = 0;
+ String selectedBody = ((org.apache.struts.tiles.beans.MenuItem)tabList.get(selectedIndex)).getLink(); // Selected body
+
+%>
+
+<table border="0" cellspacing="0" cellpadding="0">
+ <%-- Draw tabs --%>
+<tr>
+ <td width="10"> </td>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+<logic:iterate id="tab" name="tabList" type="org.apache.struts.tiles.beans.MenuItem" >
+<% // compute href
+ String href = request.getRequestURI() + "?"+parameterName + "=" + index;
+ // Don't add request URI prefix , but let the client compute the original URL
+ // This allows to use a Struts action as page URL, and perform a forward.
+ // Bug reported by Don Peterkofsky
+ //String href = "" + "?"+parameterName + "=" + index;
+ String color = notSelectedColor;
+ if( index == selectedIndex )
+ {
+ selectedBody = tab.getLink();
+ color = selectedColor;
+ } // enf if
+ index++;
+%>
+ <td bgcolor="<%=color%>">
+ <a href="<%=href%>" ><%=tab.getValue()%></a>
+ </td>
+ <td width="1" ></td>
+
+</logic:iterate>
+ </tr>
+ </table>
+ </td>
+ <td width="10" > </td>
+</tr>
+
+
+<tr>
+ <td height="5" bgcolor="<%=selectedColor%>" colspan="3" > </td>
+</tr>
+
+ <%-- Draw body --%>
+<tr>
+ <td width="10" bgcolor="<%=selectedColor%>"> </td>
+ <td>
+ <tiles:insert name="<%=selectedBody%>" flush="true" />
+ </td>
+ <td width="10" bgcolor="<%=selectedColor%>"> </td>
+</tr>
+
+<tr>
+ <td height="5" bgcolor="<%=selectedColor%>" colspan="3" > </td>
+</tr>
+
+</table>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/layouts/vboxLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/layouts/vboxLayout.jsp
new file mode 100644
index 0000000..0e77836
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/layouts/vboxLayout.jsp
@@ -0,0 +1,52 @@
+<%@ page import="java.util.Iterator"%>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ Render a list of tiles in a vertical column
+ @param : list List of names to insert
+ This file contains 3 possible implementations.
+ Use only one and comment the others. Don't forget to move the appropriate taglib
+ declaration in the header.
+--%>
+
+<tiles:useAttribute id="list" name="list" classname="java.util.List" />
+
+<%-- Iterate over names.
+ We don't use <iterate> tag because it doesn't allow insert (in JSP1.1)
+ --%>
+<%
+Iterator i=list.iterator();
+while( i.hasNext() )
+ {
+ String name= (String)i.next();
+%>
+<tiles:insert name="<%=name%>" flush="true" />
+<br>
+
+<%
+ } // end loop
+%>
+
+
+<%-- Iterate over names.
+ Use jstl <forEach> tag.
+ Require the jstl taglib.
+ --%>
+<%--
+<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
+<c:forEach var="name" items="${list}">
+ <tiles:insert beanName="name" flush="true" />
+<br>
+</c:forEach>
+ --%>
+
+<%-- Iterate over names.
+ Use struts <iterate> tag. Work on jsp1.2 and greater web container.
+ --%>
+<%--
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<logic:iterate id="name" name="list" type="java.lang.String">
+ <tiles:insert beanName="name" flush="false" />
+<br>
+</logic:iterate>
+ --%>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/body.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/body.jsp
new file mode 100644
index 0000000..45221f9
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/body.jsp
@@ -0,0 +1 @@
+<div align="center"><b><i>This is a body</i></b></div>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/failpage.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/failpage.jsp
new file mode 100644
index 0000000..9faa52a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/failpage.jsp
@@ -0,0 +1,3 @@
+<strong>Error</strong>
+<br>
+<%=request.getAttribute( "actionError" )%>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/header.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/header.jsp
new file mode 100644
index 0000000..16fd061
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/header.jsp
@@ -0,0 +1 @@
+<strong>This is the header</strong><img src="<%=request.getContextPath()%>/images/struts-power.gif" align="right" border="0">
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/index.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/index.jsp
new file mode 100644
index 0000000..255968f
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/index.jsp
@@ -0,0 +1,21 @@
+<h1>Tiles Simple Tests</h1>
+<P>
+
+ These tests allow quick checking of
+Tiles behaviors and Tiles instalation. </P>
+<P>It is possible to run each test separately, or all in one. In this later
+case, test results and test codes are displayed in the same page. You can
+compare the resulting page with the quick overview page from main site to check
+if all is ok.</P>
+<P>To run tests, follow the "all in one" link. If there is a problem, try
+each separate test in turn to localize which one fail.</P>
+<UL>
+ <LI><A href="testAll.jsp">All in one</A> (main code + test results)
+ <LI><A href="testBasic.jsp">basic tests</A>(no definitions)
+ <LI><A href="testIgnore.jsp">Test 'ignore' attribute, and basic errors processing</A>
+ <LI><A href="testList.jsp">test lists</A>
+ <LI><A href="testDefinitions.jsp">test definitions</A>
+ <LI><A href="testRole.jsp">test role (With Tomcat, use 'tomcat' as userid and password)</A>
+ <LI><A href="testStrutsAction.jsp">test struts action integration and behavior</A>
+ <LI><A href="testController.jsp">test tile controller calls</A>
+</LI></UL>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/layout.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/layout.jsp
new file mode 100644
index 0000000..518cbdb
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/layout.jsp
@@ -0,0 +1,20 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+
+
+<%--
+ A simple layout.
+ First, we get component/template attribute (title) as a String.
+ Next, we insert component/template attribute (header and body).
+--%>
+<table border="2" width="300" bordercolor="Gray">
+<tr>
+<td bgcolor="Blue"><strong><tiles:getAsString name="title"/></strong></td>
+</tr>
+<tr>
+<td><tiles:insert attribute="header"/></td>
+</tr>
+<tr>
+<td><tiles:insert attribute="body"/></td>
+</tr>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/layoutTestIgnore.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/layoutTestIgnore.jsp
new file mode 100644
index 0000000..7ad2af7
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/layoutTestIgnore.jsp
@@ -0,0 +1,19 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+
+
+<%--
+ Layout to test 'ignore' attribute.
+--%>
+<table border="2" width="300" bordercolor="Gray">
+<tr>
+<td bgcolor="Blue"><strong><tiles:getAsString name="title" ignore="false" /></strong></td>
+</tr>
+<tr>
+<td><tiles:insert attribute="header" ignore="true"/></td>
+</tr>
+<tr>
+<td><tiles:insert attribute="body" ignore="true"/>
+</td>
+</tr>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/menu.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/menu.jsp
new file mode 100644
index 0000000..bb9b70d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/menu.jsp
@@ -0,0 +1,33 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ page import="java.util.Iterator" %>
+
+<%--
+--%>
+
+<%-- Push component attributes in page context --%>
+<tiles:importAttribute />
+
+<%-- Prepare the links list to be iterated --%>
+<bean:define id="links" name="links" type="java.util.List" scope="page" />
+<% Iterator i = links.iterator(); %>
+
+<%-- Iterate on list of items
+ --%>
+<table>
+<logic:iterate id="item" name="items" >
+
+<tr>
+ <td width="10" valign="top" ></td>
+ <td valign="top" >
+ <% // Compute link value
+ String link = i.next().toString();
+ if(link.startsWith("/") )
+ link = request.getContextPath() + link;
+ %>
+ <font size="-1"><a href="<%=link%>"><bean:write name="item" filter="false"/></a></font>
+ </td>
+</tr>
+</logic:iterate>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/quickOverview.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/quickOverview.jsp
new file mode 100644
index 0000000..b6548ba
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/quickOverview.jsp
@@ -0,0 +1,4 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="test.home.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/showRequestUri.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/showRequestUri.jsp
new file mode 100644
index 0000000..c7f6231
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/showRequestUri.jsp
@@ -0,0 +1,4 @@
+<div align="center"><b><i>RequestUri: <%=request.getRequestURI()%> </i></b>
+<b><i>ContextPath: <%=request.getContextPath()%> </i></b>
+
+</div>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testAll.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testAll.jsp
new file mode 100644
index 0000000..dc7f4c5
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testAll.jsp
@@ -0,0 +1,35 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+
+In the right column you can find some basic examples,
+while in the left column you find the corresponding output result.
+<table cellspacing=4 cellpadding="2" border="4" >
+<tr>
+<td><strong>Output Result</strong></td>
+<td><strong>Sources</strong></td>
+</tr>
+<tr>
+ <td valign="top"><tiles:insert page="testBasic.jsp" /></td>
+ <td valign="top">
+ <tiles:insert page="/common/viewSrcBody.jsp">
+ <tiles:put name="srcPath" value="/test/testBasic.jsp" />
+ </tiles:insert>
+ </td>
+</tr>
+<tr>
+ <td valign="top"><tiles:insert page="testList.jsp" /></td>
+ <td valign="top">
+ <tiles:insert page="/common/viewSrcBody.jsp">
+ <tiles:put name="srcPath" value="/test/testList.jsp" />
+ </tiles:insert>
+ </td>
+</tr>
+<tr>
+ <td valign="top"><tiles:insert page="testDefinitions.jsp" /></td>
+ <td valign="top">
+ <tiles:insert page="/common/viewSrcBody.jsp">
+ <tiles:put name="srcPath" value="/test/testDefinitions.jsp" />
+ </tiles:insert>
+ </td>
+</tr>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testBackward.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testBackward.jsp
new file mode 100644
index 0000000..927c649
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testBackward.jsp
@@ -0,0 +1,15 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test backward compatibility
+--%>
+
+<hr>
+<strong>Check synonyms for include and put.</strong>
+<br>
+<tiles:insert component="layout.jsp">
+ <tiles:put name="title" value="Test with a tag body" direct="true" />
+ <tiles:put name="header" value="header.jsp">
+ <strong>This is a header</strong>
+ </tiles:put>
+ <tiles:put name="body" value="body.jsp" direct="false" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testBasic.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testBasic.jsp
new file mode 100644
index 0000000..4a1b2a2
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testBasic.jsp
@@ -0,0 +1,60 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test tags basic behaviors
+--%>
+<hr>
+<strong>Basic template usage</strong>
+<br>
+<tiles:insert template="layout.jsp">
+ <tiles:put name="title" value="Test with default no types" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:insert>
+
+<hr>
+<strong>Specify attribute types</strong>
+<br>
+<tiles:insert template="layout.jsp">
+ <tiles:put name="title" value="Test with specified types" type="string" />
+ <tiles:put name="header" value="header.jsp" type="page" />
+ <tiles:put name="body" value="body.jsp" type="page" />
+</tiles:insert>
+
+<hr>
+<strong>Set attribute value with tag body</strong>
+<br>
+<tiles:insert template="layout.jsp">
+ <tiles:put name="title" value="Test with a tag body" />
+ <tiles:put name="header" type="string">
+ <strong>This header is inserted as body of tag</strong>
+ </tiles:put>
+ <tiles:put name="body" value="body.jsp"/>
+</tiles:insert>
+
+<hr>
+<strong>Use of definition</strong>
+<br>
+<tiles:definition id="templateDefinition" template="layout.jsp">
+ <tiles:put name="title" value="Use of definition" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:definition>
+<tiles:insert beanName="templateDefinition" />
+
+<hr>
+<strong>Use of definition, overload of parameters </strong>Title parameter
+from previous definition is overloaded
+<br>
+<tiles:insert beanName="templateDefinition" >
+ <tiles:put name="title" value="Use of definition, overload of parameters" type="string" />
+</tiles:insert>
+
+<hr>
+<strong>Test ignore : body isn't defined </strong>(We use another layout)
+<br>
+<tiles:insert template="layoutTestIgnore.jsp">
+ <tiles:put name="title" value="Test ignore : body isn't defined" />
+ <tiles:put name="header" value="header.jsp" />
+</tiles:insert>
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testController.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testController.jsp
new file mode 100644
index 0000000..e83787f
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testController.jsp
@@ -0,0 +1,30 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test tiles Controller call
+--%>
+<hr>
+<strong>Test controller set in definition from config file</strong>
+<br>
+<tiles:insert definition="test.struts.controller" >
+</tiles:insert>
+
+<hr>
+<strong>Test controller set in insert</strong>
+<br>
+<tiles:insert template="layout.jsp"
+ controllerClass="org.apache.struts.webapp.tiles.test.TestTileController" >
+ <tiles:put name="title" value="Test controller set in insert" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:insert>
+
+<hr>
+<strong>Test controller set in insert, and attribute from definition</strong>
+<br>
+<tiles:insert definition="test.layout.test1"
+ controllerClass="org.apache.struts.webapp.tiles.test.TestTileController" >
+ <tiles:put name="title" value="Test controller set in insert, and attribute from definition" />
+</tiles:insert>
+
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testDefinitions.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testDefinitions.jsp
new file mode 100644
index 0000000..ff84978
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testDefinitions.jsp
@@ -0,0 +1,36 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test template definitions (from factory)
+--%>
+<hr>
+<strong>Insert definition defined directly in jsp page</strong>
+<tiles:definition id="definition" template="/test/layout.jsp" >
+ <tiles:put name="title" value="Test definition defined in jsp page" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:definition>
+
+<br>
+<tiles:insert beanName="definition"/>
+
+<hr>
+<strong>Insert definition defined in factory</strong>
+<br>
+<tiles:insert definition="test.layout.test1"/>
+
+<hr>
+<strong>Insert definition defined in factory</strong>
+<br>
+<tiles:insert definition="test.layout.test2"/>
+
+<hr>
+<strong>Insert definition defined in factory</strong>
+<br>
+<tiles:insert definition="test.layout.test3"/>
+
+<hr>
+<strong>Insert definition defined in factory : Overload title attribute</strong>
+<br>
+<tiles:insert definition="test.layout.test3">
+ <tiles:put name="title" value="Test definition : overload attribute 'title'" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testIgnore.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testIgnore.jsp
new file mode 100644
index 0000000..7279369
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testIgnore.jsp
@@ -0,0 +1,42 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test 'ignore' attribute :
+ Insert components/templates with undefined attributes, or bad urls.
+ Undefined must be spkipped, while false urls must output exception.
+--%>
+<hr>
+<strong>Test ignore : body isn't defined</strong>
+<br>
+<tiles:insert template="layoutTestIgnore.jsp">
+ <tiles:put name="title" value="Test ignore : body isn't defined" />
+ <tiles:put name="header" value="header.jsp" />
+</tiles:insert>
+
+<hr>
+<strong>Test ignore : bad body definition name (exception must be shown)</strong>
+<br>
+<tiles:insert template="layoutTestIgnore.jsp">
+ <tiles:put name="title" value="Test ignore : bad body definition name (exception must be shown)" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="badDefinitionName" type="definition" />
+</tiles:insert>
+
+<hr>
+<strong>Test ignore : Definition not found (no errors, no insertion)</strong>
+<br>
+<tiles:definition id="templateDefinition" template="layout.jsp">
+ <tiles:put name="title" value="Test ignore : Definition not found (no errors, no insertion)" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:definition>
+<tiles:insert beanName="badTemplateDefinitionName" ignore="true"/>
+
+<hr>
+<strong>Test ignore : bad body urls (exception must be shown)</strong>
+<br>
+<tiles:insert template="layoutTestIgnore.jsp">
+ <tiles:put name="title" value="Test ignore : bad body urls (exception must be shown)" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body2.jsp"/>
+</tiles:insert>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testInclude.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testInclude.jsp
new file mode 100644
index 0000000..8b590e9
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testInclude.jsp
@@ -0,0 +1,55 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test jsp include in a BodyTag (<iterate>).
+--%>
+<%
+java.util.List list = new java.util.ArrayList();
+list.add( "header.jsp" );
+list.add( "body.jsp" );
+int position=0;
+%>
+
+ <hr>
+
+ <strong>1 request.getRequestDispatcher(uri).include(request, response)</strong>
+
+ <logic:iterate id="uri" collection="<%=list%>" type="java.lang.String" >
+ <br>
+ include number <%= position++ %>
+ <br>
+ <% // insert the id
+ response.flushBuffer();
+ response.getWriter().flush();
+ //out.flush();
+ request.getRequestDispatcher(uri).include(request, response);
+ response.getWriter().flush();
+ response.flushBuffer();
+ %>
+ </logic:iterate>
+
+<hr>
+<strong>pageContext.include(page)</strong>
+
+ <logic:iterate id="uri" collection="<%=list%>" type="java.lang.String" >
+ <br>
+ include number <%= position++ %>
+ <br>
+ <% // insert the id
+ pageContext.include(uri);
+ %>
+ </logic:iterate><hr>
+
+<hr>
+<strong>tiles:insert</strong>
+
+ <logic:iterate id="uri" collection="<%=list%>" type="java.lang.String" >
+ <br>
+ include number <%= position++ %>
+ <br>
+ <tiles:insert definition="test.layout.test1" flush="false"/>
+ </logic:iterate>
+
+<strong>Done</strong>
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testList.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testList.jsp
new file mode 100644
index 0000000..b6a1224
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testList.jsp
@@ -0,0 +1,21 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<strong>Example of list usage</strong>
+<%-- Insert a menu component.
+ Menu component require two lists : one of items, and one of links.
+--%>
+<tiles:insert component="menu.jsp" >
+ <tiles:put name="title" value="Test menu" />
+ <tiles:putList name="items">
+ <tiles:add value="home" />
+ <tiles:add>
+ <img src="<%=request.getContextPath()%>/images/struts-power.gif"
+ align="right" border="0"></tiles:add>
+ <tiles:add value="documentation"/>
+ </tiles:putList>
+ <tiles:putList name="links">
+ <tiles:add value="/index.jsp"/>
+ <tiles:add value="/../struts-documentation"/>
+ <tiles:add value="/../comps-doc" type="string" />
+ </tiles:putList>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testRole.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testRole.jsp
new file mode 100644
index 0000000..4290e70
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testRole.jsp
@@ -0,0 +1,22 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test tags basic behaviors
+--%>
+<hr>
+<strong>Show Component if 'tomcat' role is set</strong>
+<br>
+<tiles:insert template="layout.jsp" role="tomcat">
+ <tiles:put name="title" value="Tomcat role" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:insert>
+
+<hr>
+<strong>Show Component if 'role1' role is set</strong>
+<br>
+<tiles:insert template="layout.jsp" role="role1">
+ <tiles:put name="title" value="role1 role" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:insert>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/test/testStrutsAction.jsp b/struts-sandbox/tiles-documentation/src/webapp/test/testStrutsAction.jsp
new file mode 100644
index 0000000..309562e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/test/testStrutsAction.jsp
@@ -0,0 +1,36 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Test tiles and struts action integration (require factory)
+--%>
+<hr>
+<strong>Test definition set in action, and action forward to another definition</strong>
+<br>
+<tiles:insert page="/test/testAction.do" >
+ <tiles:put name="title" value="Test definition set in action, and action forward to another definition. Title is overloaded from insert" />
+ <%-- header and body values come from definition used in action's forward --%>
+ <%-- name of definition to use in action --%>
+ <tiles:put name="set-definition" value="test.layout.test1" />
+</tiles:insert>
+
+<hr>
+<strong>Test overload parameter in action</strong>
+<br>
+<tiles:insert page="/test/testAction.do" >
+ <tiles:put name="title" value="Test overload parameter in action" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+ <%-- name and value of attribute to set in action --%>
+ <tiles:put name="set-attribute" value="title" />
+ <tiles:put name="set-attribute-value" value="Test overload parameter in action : Overloaded title" />
+</tiles:insert>
+
+<hr>
+<strong>Test definition set in action, and action forward directly to jsp</strong>
+<br>
+<tiles:insert page="/test/testActionForwardJsp.do" >
+ <tiles:put name="title" value="Test definition set in action, and action forward directly to jsp" />
+ <tiles:put name="header" value="header.jsp" />
+ <tiles:put name="body" value="body.jsp" />
+</tiles:insert>
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/helloBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/helloBody.jsp
new file mode 100644
index 0000000..5c71ffd
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/helloBody.jsp
@@ -0,0 +1 @@
+<div align="center"><font size="+1"><b>Hello the World</b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/menu.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/menu.jsp
new file mode 100644
index 0000000..f4c05bb
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/menu.jsp
@@ -0,0 +1,22 @@
+<table>
+<tr bgcolor="Blue">
+ <td>
+ Menu
+ </td>
+</tr>
+<tr>
+ <td width="120" valign="top">
+ <font size="-1"><a href="<%=request.getContextPath()%>/tutorial/index.jsp">Home</a></font>
+ </td>
+</tr>
+<tr>
+ <td width="120" valign="top">
+ <font size="-1">Item 2</a></font>
+ </td>
+</tr>
+<tr>
+ <td width="120" valign="top">
+ <font size="-1">Item 3</a></font>
+ </td>
+</tr>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/myFramesetLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/myFramesetLayout.jsp
new file mode 100644
index 0000000..c04cb51
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/myFramesetLayout.jsp
@@ -0,0 +1,19 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Frameset Layout component
+ parameters : title, header, menu, body, footer
+--%>
+
+<html>
+<head>
+ <title><tiles:get name="title"/></title>
+</head>
+
+<frameset rows="73, *, 73">
+ <frame src="<%=request.getContextPath()%><tiles:get name="header" />" name="header" >
+ <frame src="<%=request.getContextPath()%><tiles:get name="body" />" name="body" >
+ <frame src="<%=request.getContextPath()%><tiles:get name="footer" />" name="footer" >
+</frameset>
+
+
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/myLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/myLayout.jsp
new file mode 100644
index 0000000..6b791c3
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basic/myLayout.jsp
@@ -0,0 +1,26 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ parameters : title, header, menu, body, footer
+--%>
+
+<html>
+<head>
+ <title><tiles:getAsString name="title"/></title>
+</head>
+
+<body>
+<TABLE width="100%">
+
+ <TR>
+ <TD colspan="2"><tiles:insert attribute="header" /></TD></TR>
+ <TR>
+ <TD width="120"><tiles:insert attribute="menu" /></TD>
+ <TD><tiles:insert attribute="body" /></TD></TR>
+ <TR>
+ <TD colspan="2"><tiles:insert attribute="footer" /></TD>
+ </TR>
+</TABLE>
+
+</body>
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/basicFramesetPage.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basicFramesetPage.jsp
new file mode 100644
index 0000000..327eec2
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basicFramesetPage.jsp
@@ -0,0 +1,9 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert template="/tutorial/basic/myFramesetLayout.jsp" >
+ <tiles:put name="title" content="My first frameset page" direct="true" />
+ <tiles:put name="header" content="/tutorial/common/header.jsp" direct="true"/>
+ <tiles:put name="footer" content="/tutorial/common/footer.jsp" direct="true"/>
+ <tiles:put name="menu" content="/tutorial/basic/menu.jsp" direct="true"/>
+ <tiles:put name="body" content="/tutorial/basic/helloBody.jsp" direct="true"/>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/basicPage.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basicPage.jsp
new file mode 100644
index 0000000..c9a3d72
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/basicPage.jsp
@@ -0,0 +1,9 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/tutorial/basic/myLayout.jsp" flush="true">
+ <tiles:put name="title" value="My first page" />
+ <tiles:put name="header" value="/tutorial/common/header.jsp" />
+ <tiles:put name="footer" value="/common/footer.jsp" />
+ <tiles:put name="menu" value="/tutorial/basic/menu.jsp" />
+ <tiles:put name="body" value="/tutorial/basic/helloBody.jsp" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/footer.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/footer.jsp
new file mode 100644
index 0000000..8947f8b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/footer.jsp
@@ -0,0 +1,8 @@
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<div align="center">
+ <font color="#023264" size="-1">
+ <em> Copyright © 2000-2003, MyCompany </em>
+ </font>
+</div>
+<html:img page="/images/struts-power.gif" align="right" border="0"/>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/header.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/header.jsp
new file mode 100644
index 0000000..2e19d5a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/header.jsp
@@ -0,0 +1,10 @@
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+<P>
+<html:img page="/images/id_nav_outside.gif" align="left" border="0"/>
+<html:img page="/images/id_nav_bkgnd.gif" align="right" border="0"/> </P>
+
+<%--
+<P><img src="<%=request.getContextPath()%>/tutorial/images/id_nav_outside.gif" align="left" border="0">
+<img src="<%=request.getContextPath()%>/tutorial/images/id_nav_bkgnd.gif" align="right" border="0"> </P>
+--%>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu.jsp
new file mode 100644
index 0000000..59f2b97
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu.jsp
@@ -0,0 +1,9 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/layout/vboxLayout.jsp" flush="true" >
+ <tiles:putList name="componentsList" >
+ <tiles:add value="/tutorial/common/menu/menuLogo.jsp" />
+ <tiles:add value="/tutorial/common/menu/menuLinks.jsp" />
+ <tiles:add value="/tutorial/common/menu/menuSrc.jsp" />
+ </tiles:putList>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuLinks.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuLinks.jsp
new file mode 100644
index 0000000..c7fe2be
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuLinks.jsp
@@ -0,0 +1,15 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/common/submenu.jsp" flush="true">
+ <tiles:put name="title" value="Main Menu" />
+ <tiles:putList name="items" >
+ <tiles:add value="Home" />
+ <tiles:add value="Basic Page" />
+ <tiles:add value="First Portal" />
+ </tiles:putList>
+ <tiles:putList name="links" >
+ <tiles:add value="/tutorial/index.jsp" />
+ <tiles:add value="/tutorial/basicPage.jsp" />
+ <tiles:add value="/tutorial/portalPage.jsp" />
+ </tiles:putList>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuLogo.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuLogo.jsp
new file mode 100644
index 0000000..7c255aa
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuLogo.jsp
@@ -0,0 +1 @@
+<img src="<%=request.getContextPath()%>/images/struts-power.gif" width="95" height="37" border="0" alt="">
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuSrc.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuSrc.jsp
new file mode 100644
index 0000000..882b889
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menu/menuSrc.jsp
@@ -0,0 +1,14 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/tutorial/common/menuViewSrc.jsp" flush="true" >
+ <tiles:putList name="list" >
+ <tiles:add value="/tutorial/basicPage.jsp" />
+ <tiles:add value="/tutorial/portalPage.jsp" />
+ <tiles:add value="/tutorial/portal/portalBody.jsp" />
+ <tiles:add value="/tutorial/common/header.jsp" />
+ <tiles:add value="/tutorial/common/menu.jsp" />
+ <tiles:add value="/tutorial/common/footer.jsp" />
+ <tiles:add value="/layout/classicLayout.jsp" />
+ <tiles:add value="/layout/vboxLayout.jsp" />
+ </tiles:putList>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menuViewSrc.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menuViewSrc.jsp
new file mode 100644
index 0000000..4a8e917
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/menuViewSrc.jsp
@@ -0,0 +1,40 @@
+<%@ page import="java.util.Iterator"%>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<%-- Menu of sources component
+ This component is a menu of sources. When a source is clicked, its
+ code is shown using a viewer.
+ A list of absolute source path must be provided.
+ Viewer path can be provided.
+ @param list List of source paths to display
+ @param viewerPath Path of viewer page. Optional.
+--%>
+
+<tiles:importAttribute />
+
+ <%-- Set default viewer if not specified --%>
+<logic:notPresent name="viewerPath" >
+ <% pageContext.setAttribute( "viewerPath", request.getContextPath()+"/tutorial/common/viewSrc.jsp" ); %>
+</logic:notPresent>
+<bean:define id="viewerPath" name="viewerPath" type="java.lang.String" />
+
+<table>
+<tr><th colspan=2><div align="left"><strong>JSP Sources</strong></div></th></tr>
+
+<%-- Iterate on sources list --%>
+<logic:iterate id="iterateItem" name="list" >
+<bean:define id="srcPath" name="iterateItem" type="java.lang.String" scope="page" />
+
+<tr>
+ <td width="10" align="center"></td>
+ <td width="120">
+ <font size="-2">
+ <a href="<%=viewerPath%>?src=<%=srcPath%>"><%=srcPath%></a>
+ </font>
+ </td>
+</tr>
+
+</logic:iterate>
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/submenu.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/submenu.jsp
new file mode 100644
index 0000000..d05875c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/submenu.jsp
@@ -0,0 +1,78 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ page import="java.util.Iterator" %>
+
+
+<%-- Push component attributes in page context --%>
+<tiles:importAttribute />
+
+<table>
+<logic:present name="title">
+<tr>
+ <th colspan=2>
+ <div align="left"><strong><bean:write name="title"/></strong></div>
+ </th>
+</tr>
+</logic:present>
+
+<%-- Check if selected exist. --%>
+<logic:notPresent name="selected" >
+ <% pageContext.setAttribute( "selected", "" ); %>
+</logic:notPresent>
+
+<%-- Prepare the links list to be iterated --%>
+<bean:define id="links" name="links" type="java.util.List" scope="page" />
+<% Iterator i = links.iterator(); %>
+
+<%-- iterate on items list --%>
+<%-- Normally, we should write something like this :
+ <logic:iterate id="item" name="items" type="java.lang.String" >
+ But, Struts doesn't declare the TEI class for iterate, and
+ some web container deal badly with the declared variable.
+ So, we use what follow instead.
+ --%>
+<logic:iterate id="iterateItem" name="items" >
+<bean:define id="item" name="iterateItem" type="java.lang.String" scope="page" />
+
+
+<tr>
+ <td width="10" valign="top" ></td>
+ <td valign="top" >
+ <%-- check if selected --%>
+ <logic:notEqual name="selected" value="<%=item%>">
+ <% // Compute link value
+ String link = (String)i.next();
+ if(link.startsWith("/") )
+ link = request.getContextPath() + link;
+ %>
+ <font size="-1"><a href="<%=link%>"><%=item%></a></font>
+ </logic:notEqual>
+ <logic:equal name="selected" value="<%=item%>">
+ <font size="-1" color="fuchsia"><%=item%></font>
+ </logic:equal>
+ </td>
+</tr>
+</logic:iterate>
+
+</table>
+
+<%-- Following are some code example using this submenu
+<tiles:insert page="/common/submenu.jsp" flush="true">
+ <tiles:put name="title" value="Main Menu" />
+ <tiles:putList name="items" >
+ <tiles:add value="Home" />
+ <tiles:add value="Edit Customer" />
+ <tiles:add value="Invoice" />
+ </tiles:putList>
+ <tiles:putList name="links" >
+ <tiles:add value="index.jsp" />
+ <tiles:add value="invoice/index.jsp" />
+ <tiles:add value="invoice/index.jsp" />
+ </tiles:putList>
+</tiles:insert>
+
+<tiles:insert definition="mainSubMenu" flush="true">
+ <tiles:put name="selected" value="Home" />
+</tiles:insert>
+--%>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrc.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrc.jsp
new file mode 100644
index 0000000..75f1a1c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrc.jsp
@@ -0,0 +1,7 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="mainLayout" flush="true" >
+ <tiles:put name="title" value="JSP Source Code" />
+ <tiles:put name="body" value="/tutorial/common/viewSrcBody.jsp" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrcBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrcBody.jsp
new file mode 100644
index 0000000..39736ca
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrcBody.jsp
@@ -0,0 +1,38 @@
+<%@ page language="java" %>
+<%@ page errorPage="/common/viewSrcBodyError.jsp" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+
+<%-- Include requested resource file.
+ If file is not found, Exception is thrown, and catched by the errorPage
+ directive (see above). Error page show a message.
+--%>
+
+ <%-- Import component attributes, if any.
+ --%>
+
+
+<tiles:importAttribute/>
+
+<logic:notPresent name="srcPath" >
+ <logic:present parameter="src" >
+ <bean:parameter id="srcPath" name="src" />
+ </logic:present>
+</logic:notPresent>
+
+
+<logic:present name="srcPath" >
+<bean:define id="srcPathVar" name="srcPath" type="java.lang.String"/>
+<bean:resource id="src" name="<%=srcPathVar%>" />
+<strong>file '<%=srcPathVar%>'</strong>
+<br>
+<pre>
+<bean:write filter="true" name="src" scope="page"/>
+</pre>
+<br>
+</logic:present>
+
+<logic:notPresent name="srcPath" >
+No source specified !
+</logic:notPresent>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrcBodyError.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrcBodyError.jsp
new file mode 100644
index 0000000..cd97613
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/common/viewSrcBodyError.jsp
@@ -0,0 +1,15 @@
+<%@ page language="java" %>
+<%@ page isErrorPage="true" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+
+
+<logic:present parameter="src" >
+<bean:parameter id="srcPath" name="src" />
+<strong>file '<%=srcPath%>' not found !</strong>
+</logic:present>
+
+<logic:notPresent parameter="src" >
+No source specified !
+</logic:notPresent>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/contentForm.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/contentForm.jsp
new file mode 100644
index 0000000..3c9b7b8
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/contentForm.jsp
@@ -0,0 +1,7 @@
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+
+
+label : <tiles:get name="label" />
+property : <tiles:get name="property" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/de/common/footer.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/de/common/footer.jsp
new file mode 100644
index 0000000..4d33d16
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/de/common/footer.jsp
@@ -0,0 +1,7 @@
+<div align="center">
+ <font color="#023264" size="-1">
+ <em> Copyright © 2000-2001, MyCompany </em>
+<br><em> German Version </em>
+ </font>
+</div>
+<img src="<%=request.getContextPath()%>/images/struts-power.gif" align="right" border="0">
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/de/common/header.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/de/common/header.jsp
new file mode 100644
index 0000000..553f69c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/de/common/header.jsp
@@ -0,0 +1,3 @@
+
+<P><img src="<%=request.getContextPath()%>/images/id_nav_outside.gif" align="left" border="0">
+<img src="<%=request.getContextPath()%>/images/id_nav_bkgnd.gif" align="right" border="0"> </P>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitionTag.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitionTag.jsp
new file mode 100644
index 0000000..b0eea79
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitionTag.jsp
@@ -0,0 +1,11 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:definition id="definitionName" template="/tutorial/basic/myLayout.jsp" >
+ <tiles:put name="title" value="My first page" />
+ <tiles:put name="header" value="/tutorial/common/header.jsp" />
+ <tiles:put name="footer" value="/tutorial/common/footer.jsp" />
+ <tiles:put name="menu" value="/tutorial/basic/menu.jsp" />
+ <tiles:put name="body" value="/tutorial/basic/helloBody.jsp" />
+</tiles:definition>
+
+<tiles:insert beanName="definitionName" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/definitionsConfig.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/definitionsConfig.jsp
new file mode 100644
index 0000000..c6105c3
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/definitionsConfig.jsp
@@ -0,0 +1,42 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+
+<%--
+ This file contains definition declarations.
+ These definitions can be used in any jsp page by including
+ this file with :
+ <%@ include file="filename.jsp" %>
+ Each definition declaration create a bean stored in specified jsp context.
+ Default jsp context is 'page', so we need to specify a more useful context.
+--%>
+
+ <%-- Master layout definition --%>
+<tiles:definition id="masterLayout" page="/layouts/classicLayout.jsp" scope="request" >
+ <tiles:put name="title" value="My First Definition Page" />
+ <tiles:put name="header" value="/tutorial/common/header.jsp" />
+ <tiles:put name="footer" value="/tutorial/common/footer.jsp" />
+ <tiles:put name="menu" value="/tutorial/common/menu.jsp" />
+ <tiles:put name="body" value="/tutorial/basic/helloBody.jsp" />
+</tiles:definition>
+
+ <%-- portal definition --%>
+<tiles:definition id="portalExample" page="/layout/columnsLayout.jsp" scope="request">
+ <tiles:put name="numCols" value="2" />
+ <tiles:putList name="list0" >
+ <tiles:add value="/portal/login.jsp" />
+ <tiles:add value="/portal/messages.jsp" />
+ <tiles:add value="/portal/newsFeed.jsp" />
+ <tiles:add value="/portal/advert2.jsp" />
+ </tiles:putList>
+ <tiles:putList name="list1" >
+ <tiles:add value="/portal/advert3.jsp" />
+ <tiles:add value="/portal/stocks.jsp" />
+ <tiles:add value="/portal/whatsNew.jsp" />
+ <tiles:add value="/portal/personalLinks.jsp" />
+ <tiles:add value="/portal/search.jsp" />
+ </tiles:putList>
+</tiles:definition>
+
+ <%--
+ Add as many definition as you need ...
+ --%>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/firstDefinitionPage.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/firstDefinitionPage.jsp
new file mode 100644
index 0000000..8d4938f
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/firstDefinitionPage.jsp
@@ -0,0 +1,5 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="myFirstDefinition" flush="true" >
+ <tiles:put name="title" value="My first Definition Page" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/simpleBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/simpleBody.jsp
new file mode 100644
index 0000000..58bbaec
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/simpleBody.jsp
@@ -0,0 +1,18 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/layout/columnsLayout.jsp" flush="true">
+ <tiles:put name="numCols" value="2" />
+ <tiles:putList name="list0" >
+ <tiles:add value="/portal/login.jsp" />
+ <tiles:add value="/portal/messages.jsp" />
+ <tiles:add value="/portal/newsFeed.jsp" />
+ <tiles:add value="/portal/advert2.jsp" />
+ </tiles:putList>
+ <tiles:putList name="list1" >
+ <tiles:add value="/portal/advert3.jsp" />
+ <tiles:add value="/portal/stocks.jsp" />
+ <tiles:add value="/portal/whatsNew.jsp" />
+ <tiles:add value="/portal/personalLinks.jsp" />
+ <tiles:add value="/portal/search.jsp" />
+ </tiles:putList>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/useDefinitionConfig.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/useDefinitionConfig.jsp
new file mode 100644
index 0000000..10f107b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/definitions/useDefinitionConfig.jsp
@@ -0,0 +1,13 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+
+<%--
+ This example insert a definition defined in another jsp file.
+ First, it include jsp file containing definition.
+ Second, it do an insert where it want the definition to be rendered.
+--%>
+
+<%@ include file="definitionsConfig.jsp" %>
+
+<tiles:insert beanName="masterLayout" beanScope="request" />
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynFramesetPage.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynFramesetPage.jsp
new file mode 100644
index 0000000..06370fe
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynFramesetPage.jsp
@@ -0,0 +1,10 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert template="/tutorial/basic/myFramesetLayout.jsp" beanName="templateDefinition" >
+ <%-- Uncomment lines to overload parameters --%>
+ <%-- <tiles:put name="title" content="My first frameset page" direct="true" /> --%>
+ <%-- <tiles:put name="header" content="/tutorial/common/header.jsp" direct="true"/> --%>
+ <%-- <tiles:put name="footer" content="/tutorial/common/footer.jsp" direct="true"/> --%>
+ <%-- <tiles:put name="menu" content="/tutorial/basic/menu.jsp" direct="true"/> --%>
+ <%-- <tiles:put name="body" content="/tutorial/basic/helloBody.jsp" direct="true"/> --%>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/Channels.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/Channels.jsp
new file mode 100644
index 0000000..d5ea4b1
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/Channels.jsp
@@ -0,0 +1,38 @@
+<%--
+/**
+ * Summarize channels as unadorned HTML.
+ *
+ * @parameters ListArray CHANNELS
+ * @version $Revision: 1.2 $ $Date$
+ */
+--%>
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:importAttribute name="CHANNELS" scope="page"/>
+
+<logic:iterate name="CHANNELS" id="CHANNEL" >
+<TABLE border="0" cellspacing="2" cellpadding="4" width="300" align="center" >
+<TR>
+<TD><logic:present name="CHANNEL" property="image"><img src="<bean:write name="CHANNEL" property="image.URL"/>"></logic:present></TD>
+<TD class="spanhd" width="100%"><a href="<bean:write name="CHANNEL" property="link"/>">
+<bean:write name="CHANNEL" property="title"/></a></TD>
+</TR>
+<TD class="yellow" colspan="2"><bean:write name="CHANNEL" property="description"/></TD>
+</TR>
+
+<TR>
+<TD class="datagrey" colspan="2">
+<logic:iterate name="CHANNEL" property="items" id="ITEM">
+<br><b><bean:write name="ITEM" property="title"/></b>
+<br><bean:write name="ITEM" property="description"/>
+<br> [ <a href="<bean:write name="ITEM" property="link"/>">more</a> ]
+<br>
+</logic:iterate>
+</TD>
+</TR>
+</TABLE>
+<br>
+</logic:iterate>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/Errors.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/Errors.jsp
new file mode 100644
index 0000000..8b292b2
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/Errors.jsp
@@ -0,0 +1,27 @@
+<%--
+/**
+ * Summarize channels errors as unadorned HTML.
+ *
+ * @parameters errors
+ * @version $Revision: 1.2 $ $Date$
+ */
+--%>
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<TABLE border="0" cellspacing="2" cellpadding="4" width="300" align="center" >
+<TR>
+<TD class="alert">
+Error while reading channels.
+<br></br>Are you connected ?
+</TD>
+</TR>
+<TR>
+<TD class="error" width="100%"><html:errors/></TD>
+</TR>
+
+</TABLE>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/index.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/index.jsp
new file mode 100644
index 0000000..b41a9ea
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/index.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="myDynamicPortal" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/myPortalPrefTile.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/myPortalPrefTile.jsp
new file mode 100644
index 0000000..4951b72
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/myPortalPrefTile.jsp
@@ -0,0 +1,112 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+
+
+<script language="javaScript1.2">
+function selectAll( )
+{
+for( j=0; j<selectAll.arguments.length; j++ )
+ {
+ col1 = selectAll.arguments[j];
+ for(i=0; i<col1.options.length; i++ )
+ {
+ col1.options[ i ].selected = true;
+ }
+ } // end loop
+ return true;
+}
+
+function move( col1, col2)
+{
+ toMove = col1.options[ col1.selectedIndex ];
+ opt = new Option( toMove.text, toMove.value, false, false );
+ col1.options[col1.selectedIndex ] = null;
+ col2.options[col2.length] = opt;
+ return true;
+}
+
+function remove( col1)
+{
+ col1.options[ col1.selectedIndex ] = null;
+ return true;
+}
+
+function up( col1 )
+{
+ index = col1.selectedIndex;
+ if( index <= 0 )
+ return true;
+
+ toMove = col1.options[ index ];
+ opt = new Option( toMove.text, toMove.value, false, false );
+ col1.options[index] = col1.options[index-1];
+ col1.options[index-1] = opt;
+ return true;
+}
+
+function down( col1 )
+{
+ index = col1.selectedIndex;
+ if( index+1 >= col1.options.length )
+ return true;
+
+ toMove = col1.options[ index ];
+ opt = new Option( toMove.text, toMove.value, false, false );
+ col1.options[index] = col1.options[index+1];
+ col1.options[index+1] = opt;
+ return true;
+}
+
+</script>
+
+
+<html:form action="/actions/myPortalPrefs.do" >
+
+
+
+ <html:select property="remaining" multiple="true" >
+ <html:options property="choices" />
+ </html:select>
+
+ <html:button property="v" value="v" onclick="move(remaining,l0);return true;"/>
+ <br>
+
+ <table>
+ <tr>
+ <td>
+ <html:select property="l0" multiple="true" size="10">
+ <html:options property="col[0]" labelProperty="colLabels[0]"/>
+ </html:select>
+ </td>
+ <td>
+ <html:select property="l1" multiple="true" size="10">
+ <html:options property="col[1]" labelProperty="colLabels[1]"/>
+ </html:select>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">
+ <html:button property="right" value="^" onclick="up(l0);return true;"/>
+ <html:button property="right" value="del" onclick="remove(l0);return true;"/>
+ <html:button property="right" value="v" onclick="down(l0);return true;"/>
+ <html:button property="left" value=">" onclick="move(l0,l1);return false;" />
+ </td>
+ <td align="center">
+ <html:button property="right" value="<" onclick="move(l1,l0);return true;"/>
+ <html:button property="right" value="^" onclick="up(l1);return true;"/>
+ <html:button property="right" value="del" onclick="remove(l1);return true;"/>
+ <html:button property="right" value="v" onclick="down(l1);return true;"/>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center">
+
+ <html:submit property="validate" value="validate" onclick="selectAll(l0, l1);return true;"/>
+ </td>
+ </tr>
+ </table>
+
+
+
+
+</html:form>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/myPortalPrefs.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/myPortalPrefs.jsp
new file mode 100644
index 0000000..1ead874
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/myPortalPrefs.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="myDynamicPortalPreferences" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/testChannels.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/testChannels.jsp
new file mode 100644
index 0000000..e5a9083
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/dynPortal/testChannels.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="test.rssChannel.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/extendedDefinition.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/extendedDefinition.jsp
new file mode 100644
index 0000000..1745fe9
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/extendedDefinition.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="extended.definition.example" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/extendedDefinitionTag.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/extendedDefinitionTag.jsp
new file mode 100644
index 0000000..19035c7
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/extendedDefinitionTag.jsp
@@ -0,0 +1,7 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:definition id="definitionName" extends="myFirstDefinition" >
+ <tiles:put name="title" value="My first extended definition tag page" />
+</tiles:definition>
+
+<tiles:insert beanName="definitionName" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/firstDefinition.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/firstDefinition.jsp
new file mode 100644
index 0000000..63582c9
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/firstDefinition.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="myFirstDefinition" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/failureBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/failureBody.jsp
new file mode 100644
index 0000000..8efe11b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/failureBody.jsp
@@ -0,0 +1,5 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+ Struts forward to 'failure'.
+ <br>
+<tiles:insert page="/tutorial/forward/forwardBody.jsp" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/forwardBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/forwardBody.jsp
new file mode 100644
index 0000000..95dfa00
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/forwardBody.jsp
@@ -0,0 +1,5 @@
+<form action="forwardExampleAction.do">
+Select an action :
+<br><input type="submit" name="success" value="success">
+<br><input type="submit" name="failure" value="failure">
+</form>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/successBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/successBody.jsp
new file mode 100644
index 0000000..8a4e73d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/forward/successBody.jsp
@@ -0,0 +1,6 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+ Struts forward to 'success'.
+ <br>
+<tiles:insert page="/tutorial/forward/forwardBody.jsp" flush="true" />
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/fr/common/footer.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/fr/common/footer.jsp
new file mode 100644
index 0000000..56489e4
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/fr/common/footer.jsp
@@ -0,0 +1,7 @@
+<div align="center">
+ <font color="#023264" size="-1">
+ <em> Copyright © 2000-2001, MaPetiteEntreprise </em>
+<br><em> Version Française </em>
+ </font>
+</div>
+<img src="<%=request.getContextPath()%>/images/struts-power.gif" align="right" border="0">
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/fr/common/header.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/fr/common/header.jsp
new file mode 100644
index 0000000..553f69c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/fr/common/header.jsp
@@ -0,0 +1,3 @@
+
+<P><img src="<%=request.getContextPath()%>/images/id_nav_outside.gif" align="left" border="0">
+<img src="<%=request.getContextPath()%>/images/id_nav_bkgnd.gif" align="right" border="0"> </P>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/frameset.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/frameset.jsp
new file mode 100644
index 0000000..2582e6e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/frameset.jsp
@@ -0,0 +1,21 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ parameters : title, header, menu, body, footer
+--%>
+
+<html>
+<head>
+ <title><tiles:getAsString name="title"/></title>
+</head>
+
+<body>
+<frameset rows="3">
+ <frame src="<tiles:get name="header" />" name="header" id="header" scrolling="Auto">
+ <frame src="<tiles:get name="body" />" name="body" id="header" scrolling="Auto">
+ <frame src="<tiles:get name="footer" />" name="footer" id="header" scrolling="Auto">
+</frameset>
+</body>
+
+
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/banner1b.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/banner1b.gif
new file mode 100644
index 0000000..3d6a108
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/banner1b.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/banner_bottom.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/banner_bottom.gif
new file mode 100644
index 0000000..6cdeb32
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/banner_bottom.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_bkgnd.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_bkgnd.gif
new file mode 100644
index 0000000..98ada49
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_bkgnd.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_nav_bkgnd.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_nav_bkgnd.gif
new file mode 100644
index 0000000..0a4c898
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_nav_bkgnd.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_nav_outside.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_nav_outside.gif
new file mode 100644
index 0000000..5a2437c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/id_nav_outside.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input.gif
new file mode 100644
index 0000000..26ffc31
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input_gen_search.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input_gen_search.gif
new file mode 100644
index 0000000..5a26998
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input_gen_search.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input_vrm_gen_get.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input_vrm_gen_get.gif
new file mode 100644
index 0000000..1214e90
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/input_vrm_gen_get.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/struts-power.gif b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/struts-power.gif
new file mode 100644
index 0000000..5f4e9d4
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/images/struts-power.gif
Binary files differ
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/index.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/index.jsp
new file mode 100644
index 0000000..235f989
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/index.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="mainLayout" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editAddress.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editAddress.jsp
new file mode 100644
index 0000000..a419577
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editAddress.jsp
@@ -0,0 +1,68 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<%-- Edit an Address object
+ @param bean An address object to edit.
+ @param beanName The path to add between the bean and the properties to edit.
+--%>
+<%-- Retrieve parameters from component context, and declare them as page variable --%>
+<tiles:useAttribute id="beanName" name="property" classname="java.lang.String" ignore="true" />
+<tiles:importAttribute name="bean" />
+
+<%-- Add a '.' separator to the path (beanName), in order to access the property from the given bean --%>
+<% if( beanName == null ) beanName = ""; else if (beanName !="" ) beanName = beanName + "."; %>
+
+<table border="0" width="100%">
+
+ <tr>
+ <th align="right" width="30%">
+ Street
+ </th>
+ <td align="left">
+ <%-- Declare an html input field. --%>
+ <%-- We use the bean passed as parameter. --%>
+ <%-- Property name is prefixed by the sub-bean name if any. --%>
+
+ <html:text name="bean" property='<%=beanName+"street1"%>' size="50"/>
+
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Street (con't)
+ </th>
+ <td align="left">
+ <html:text property='<%=beanName+"street2"%>' size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ City
+ </th>
+ <td align="left">
+ <html:text name="bean" property='<%=beanName+"city"%>' size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Country
+ </th>
+ <td align="left">
+ <html:text property='<%=beanName+"country"%>' size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Zip code
+ </th>
+ <td align="left">
+ <html:text property='<%=beanName+"zipCode"%>' size="50"/>
+ </td>
+ </tr>
+
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editAddress2.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editAddress2.jsp
new file mode 100644
index 0000000..0217444
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editAddress2.jsp
@@ -0,0 +1,65 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="/WEB-INF/extensions.tld" prefix="ext" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<%-- Edit an Address object
+ @param address An address object to edit.
+ @param compName UI Component name. Use as prefix for html fields and sub-components
+--%>
+<%-- Retrieve parameters from component context, and declare them as page variable --%>
+<tiles:useAttribute id="addr" name="address" scope="page" />
+<tiles:useAttribute id="prefix" name="compName" classname="java.lang.String"/>
+<%-- Add a separator tothe component name, in order to have html fields prefix name : 'compName.'--%>
+<% prefix = prefix + "."; %>
+
+<table border="0" width="100%">
+
+ <tr>
+ <th align="right" width="30%">
+ Street helo
+ </th>
+ <td align="left">
+ <%-- Declare an html input field. --%>
+ <%-- We use a tag that extends Struts 'text' tag. This extension add --%>
+ <%-- attribute 'prefix', allowing to give a prefix to the normal name --%>
+ <ext:text name="addr" prefix="<%=prefix%>" property="street1" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Street (con't)
+ </th>
+ <td align="left">
+ <ext:text prefix="<%=prefix%>" name="addr" property="street2" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ City
+ </th>
+ <td align="left">
+ <ext:text prefix="<%=prefix%>" name="addr" property="city" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Country
+ </th>
+ <td align="left">
+ <ext:text prefix="<%=prefix%>" name="addr" property="country" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Zip code
+ </th>
+ <td align="left">
+ <ext:text prefix="<%=prefix%>" name="addr" property="zipCode" size="50"/>
+ </td>
+ </tr>
+
+</table>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editInvoice.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editInvoice.jsp
new file mode 100644
index 0000000..a98ca3a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editInvoice.jsp
@@ -0,0 +1,91 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<html:errors/>
+
+<html:form action="/invoice/editInvoice.do" >
+
+<font size="+1">Edit Customer Informations</font>
+
+<table border="0" width="100%">
+
+ <tr>
+ <th align="right" width="30%">
+ First Name
+ </th>
+ <td align="left">
+ <html:text property="firstname" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Last Name
+ </th>
+ <td align="left">
+ <html:text property="lastname" size="50"/>
+ </td>
+ </tr>
+
+
+ <tr>
+ <th align="right" >
+ Shipping Address
+ </th>
+ <td align="left">
+
+ </td>
+ </tr>
+ <tr>
+ <td align="center" colspan="2">
+ <%-- Include an "address editor" component. --%>
+ <%-- Pass the component name and component value as parameter --%>
+ <%-- Value comes from the form bean --%>
+ <tiles:insert page="/tutorial/invoice/editAddress.jsp" >
+ <tiles:put name="property" value="shippingAddress" />
+ <tiles:put name="bean" beanName="invoiceForm" />
+ </tiles:insert>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right" >
+ Billing Address
+ </th>
+ <td align="left">
+
+ </td>
+ </tr>
+ <tr>
+ <td align="center" colspan="2">
+ <tiles:insert page="/tutorial/invoice/editAddress.jsp" >
+ <tiles:put name="property" value="billAddress" />
+ <tiles:put name="bean" beanName="invoiceForm" />
+ </tiles:insert>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">
+ <html:submit>
+ save
+ </html:submit>
+ <html:submit>
+ confirm
+ </html:submit>
+ </td>
+ <td align="left">
+ <html:reset>
+ reset
+ </html:reset>
+
+ <html:cancel>
+ cancel
+ </html:cancel>
+ </td>
+ </tr>
+</table>
+
+</html:form>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editInvoice2.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editInvoice2.jsp
new file mode 100644
index 0000000..f85c98a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/editInvoice2.jsp
@@ -0,0 +1,91 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<html:errors/>
+
+<html:form action="/invoice/editInvoice.do" >
+
+<font size="+1">Edit Customer Informations</font>
+
+<table border="0" width="100%">
+
+ <tr>
+ <th align="right" width="30%">
+ First Name
+ </th>
+ <td align="left">
+ <html:text property="firstname" size="50"/>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">
+ Last Name
+ </th>
+ <td align="left">
+ <html:text property="lastname" size="50"/>
+ </td>
+ </tr>
+
+
+ <tr>
+ <th align="right" >
+ Shipping Address
+ </th>
+ <td align="left">
+
+ </td>
+ </tr>
+ <tr>
+ <td align="center" colspan="2">
+ <%-- Include an "address editor" component. --%>
+ <%-- Pass the component name and component value as parameter --%>
+ <%-- Value comes from the form bean --%>
+ <tiles:insert page="/tutorial/invoice/editAddress.jsp" >
+ <tiles:put name="compName" value="shippingAddress" />
+ <tiles:put name="address" beanName="invoiceForm" beanProperty="shippingAddress" />
+ </tiles:insert>
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right" >
+ Billing Address
+ </th>
+ <td align="left">
+
+ </td>
+ </tr>
+ <tr>
+ <td align="center" colspan="2">
+ <tiles:insert page="/tutorial/invoice/editAddress.jsp" >
+ <tiles:put name="compName" value="billAddress" />
+ <tiles:put name="address" beanName="invoiceForm" beanProperty="billAddress" />
+ </tiles:insert>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">
+ <html:submit>
+ save
+ </html:submit>
+ <html:submit>
+ confirm
+ </html:submit>
+ </td>
+ <td align="left">
+ <html:reset>
+ reset
+ </html:reset>
+
+ <html:cancel>
+ cancel
+ </html:cancel>
+ </td>
+ </tr>
+</table>
+
+</html:form>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/index.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/index.jsp
new file mode 100644
index 0000000..39c30e0
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/invoice/index.jsp
@@ -0,0 +1,8 @@
+<%@ page language="java" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="mainLayout" flush="true">
+ <tiles:put name="body" value="/tutorial/invoice/editInvoice.jsp" />
+ <%-- <tiles:put name="body" value="/tutorial/invoice/editInvoice2.jsp" /> --%>
+</tiles:insert>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/lang/lang.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/lang/lang.jsp
new file mode 100644
index 0000000..610be6d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/lang/lang.jsp
@@ -0,0 +1,5 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<a href="tutorial/lang.do?language=FR">Francais</a>
+<br>
+<a href="tutorial/lang.do?language=UK">English</a>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/classicLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/classicLayout.jsp
new file mode 100644
index 0000000..af2783d
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/classicLayout.jsp
@@ -0,0 +1,45 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout Tiles
+ This layout render a header, left menu, body and footer.
+ @param title String use in page title
+ @param header Header tile (jsp url or definition name)
+ @param menu Menu
+ @param body Body
+ @param footer Footer
+--%>
+
+<HTML>
+ <HEAD>
+ <link rel=stylesheet href="<%=request.getContextPath()%>/tutorial/layout/stylesheet.css" type="text/css">
+
+ <title><tiles:getAsString name="title"/></title>
+ </HEAD>
+
+<body bgcolor="#ffffff" text="#000000" link="#023264" alink="#023264" vlink="#023264">
+<table border="0" width="100%" cellspacing="5">
+<tr>
+ <td colspan="2"><tiles:insert attribute="header" /></td>
+</tr>
+<tr>
+ <td width="140" valign="top">
+ <tiles:insert attribute='menu'/>
+ </td>
+ <td valign="top" align="left">
+ <tiles:insert attribute='body' />
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+ <hr>
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+ <tiles:insert attribute="footer" />
+ </td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/columnsLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/columnsLayout.jsp
new file mode 100644
index 0000000..0cb87f4
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/columnsLayout.jsp
@@ -0,0 +1,39 @@
+<%@ page import="org.apache.struts.tiles.ComponentContext"%>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ Render a list in severals columns
+ parameters : numCols, list0, list1, list2, list3, ...
+--%>
+
+<tiles:useAttribute id="numColsStr" name="numCols" classname="java.lang.String" />
+
+
+<table>
+<tr>
+<%
+int numCols = Integer.parseInt(numColsStr);
+ComponentContext context = ComponentContext.getContext( request );
+for( int i=0; i<numCols; i++ )
+ {
+ java.util.List list=(java.util.List)context.getAttribute( "list" + i );
+ pageContext.setAttribute("list", list );
+ if(list==null)
+ System.out.println( "list is null for " + i );
+%>
+<td valign="top">
+ <tiles:insert page="/layout/vboxLayout.jsp" flush="true" >
+ <tiles:put name="componentsList" beanName="list" beanScope="page" />
+ </tiles:insert>
+</td>
+<%
+ } // end loop
+%>
+</tr>
+</table>
+
+
+
+
+
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/stylesheet.css b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/stylesheet.css
new file mode 100644
index 0000000..ab93601
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/stylesheet.css
@@ -0,0 +1,263 @@
+/* CSS World Financial Personality - Revised jun99 */
+
+/* base element inheritance formatting */
+body { margin-left: 0px; margin-right: 0px;
+ margin-top: 0px; margin-bottom: 0px;
+ font-family: arial, geneva, helvetica, "sans serif"; }
+a { font-weight: bold; } /* all links are bold */
+a:link { color: #3300cc } /* unvisited link */
+a:visited { color: #330099 } /* visited links */
+a:active { color: #000033 } /* active links */
+a:hover { color: #000033 } /* MSIE rollover links */
+table { margin-left: 0px; margin-right: 0px;
+ margin-top: 0px; margin-bottom: 0px; }
+td { font-family: arial, geneva, helvetica, "sans serif"; }
+th { font-family: arial, geneva, helvetica, "sans serif";
+ font-weight: bold; }
+
+/* begin defined classes */
+
+/* headline classes */
+.headline { font-family: verdana, arial, geneva, "sans serif";
+ font-size: 110%; color: #000000;
+ vertical-align: middle; text-align: left; }
+
+/* on-screen hint class */
+.hint { font-size: x-small;
+ color: #000000; background: #ffffff; }
+.hintvbm { font-size: x-small; }
+
+/* Message classes */
+.note { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.noteimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+.success { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.successimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+.alert { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.alertimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+.error { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: middle; text-align: left;
+ padding: 2px; }
+.errorimg { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffcc;
+ vertical-align: top; text-align: center; }
+
+/* column header classes */
+.hdleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: left; }
+.hdright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.hdmiddle { font-size: smaller; color: #333333; background: #cccccc;
+ text-align: center; }
+.datahd { font-size: smaller; font-weight: bold;
+ color: #000000; background: #cccccc; }
+.spanhd { font-size: smaller; font-weight: bold;
+ color: #eeeeee; background: #003366;
+ text-align: left; }
+.spanhdright { font-size: smaller; font-weight: bold;
+ color: #eeeeee; background: #003366;
+ text-align: right; }
+.spanhdcenter { font-size: smaller; font-weight: bold;
+ color: #eeeeee; background: #003366;
+ text-align: center; }
+.subhdleft { font-size: x-small; color: #333333; background: #cccccc;
+ text-align: left; }
+
+/* label classes */
+.right { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.topright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ vertical-align: top; text-align: right; }
+.left { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ text-align: left; }
+.topleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ vertical-align: top; text-align: left; }
+.center { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ text-align: center; }
+.greyright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.greyleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ text-align: left; }
+.greycenter { font-size: smaller; font-weight: bold;
+ color: #333333; background: #eeeeee;
+ text-align: center; }
+.greytopright { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ vertical-align: top; text-align: right; }
+.greytopleft { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ vertical-align: top; text-align: left; }
+ /* remove after changing subright use to fine */
+.greysubright { font-size: x-small; color: #333333; background: #cccccc;
+ text-align: right; font-weight: normal; }
+
+
+/* data classes and alternating row color classes */
+.data { font-size: smaller;
+ color: #000000; background: #ffffff; }
+.datamiddle { font-size: smaller;
+ color: #000000; background: #ffffff; vertical-align: middle }
+.datagrey { font-size: smaller;
+ color: #000000; background: #eeeeee; }
+.bdata { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff; }
+.bdatagrey { font-size: smaller; font-weight: bold;
+ color: #000000; background: #eeeeee; }
+.datart { font-size: smaller;
+ color: #000000; background: #ffffff;
+ text-align: right; }
+.datartgrey { font-size: smaller;
+ color: #000000; background: #eeeeee;
+ text-align: right; }
+.bdatart { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ text-align: right; }
+.bdatartgrey { font-size: smaller; font-weight: bold;
+ color: #000000; background: #eeeeee;
+ text-align: right; }
+.curr { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ text-align: right; }
+.currgrey { font-size: smaller; font-weight: bold;
+ color: #000000; background: #eeeeee;
+ text-align: right; }
+.currleft { font-size: smaller; font-weight: bold;
+ color: #000000; background: #ffffff;
+ text-align: left; }
+.color { color: #800000; } /*change to 000000 if FI doesn't want negative numbers to be red*/
+.subdata { font-size: x-small; color: #000000; background: #ffffff }
+.subdatagrey { font-size: x-small; color: #000000; background: #eeeeee }
+.dataright { font-size: smaller; color: #000000; background: #ffffff; text-align: right;}
+.datagreyright { font-size: smaller; color: #000000; background: #eeeeee; text-align: right;}
+.yellow { font-size: smaller; color: #000000; background: #ffffcc;
+ vertical-align: middle; text-align: left; }
+
+
+
+/* vrm classes and account balance classes */
+.subcurr { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+.editorial { font-size: smaller;
+ color: #000000; background: #ffffff; }
+.editgrey { font-size: smaller;
+ color: #000000; background: #eeeeee; }
+
+
+/* fine print for inputs and tables */
+.fine { font-size: x-small; font-weight: normal;
+ color: #333333; }
+.fineright { font-size: x-small; font-weight: normal;
+ color: #333333;
+ text-align: right; }
+.finewhite { font-size: x-small; font-weight: normal; color: #000000; background: #ffffff; }
+.subright { font-size: x-small; font-weight: normal;
+ color: #333333; background: #cccccc;
+ text-align: right; }
+
+/* form element cell classes */
+.input { font-size: smaller;
+ background: #ffffff;
+ vertical-align: baseline; }
+.topinput { font-size: smaller;
+ background: #ffffff;
+ vertical-align: top; }
+.btminput { font-size: smaller;
+ background: #ffffff;
+ vertical-align: bottom; }
+.inputgrey { font-size: smaller;
+ background: #eeeeee;
+ vertical-align: baseline; }
+.submit { font-size: smaller; font-weight: bold;
+ color: #333333; background: #ffffff;
+ vertical-align: middle; text-align: right; }
+.submitgrey { font-size: smaller; font-weight: bold;
+ color: #333333; background: #cccccc;
+ vertical-align: middle; text-align: right; }
+.inputtop { font-size: smaller;
+ vertical-align: top; background: #ffffff; }
+
+/* help classes */
+.help { font-family: arial, helvetica, "sans serif";
+ font-size: smaller;
+ color: #666666; background: #ffffcc; }
+
+/* navigation bar classes */
+.navtext { font-size: x-small;
+ color: #000066;
+ text-align: right; }
+.info { font-size: x-small;
+ color: #000066; background: #eeeeee; }
+.infotext { padding-left: 2pt; }
+
+/* footer classes */
+.footlt { font-size: x-small;
+ color: #333333; background: #cccccc; }
+.footdk { font-size: x-small;
+ color: #cccccc; background: #333333; }
+
+/* background packing classes */
+.bkgnd { font-size: 1pt; }
+.wtspace { font-size: 1pt; background: #ffffff; }
+.greyspace { font-size: 1pt; background: #eeeeee; }
+.yellowspace { font-size: 1pt; background: #ffffcc; }
+.bottom { vertical-align: bottom; }
+
+
+
+/* additional VIM classes */
+.yellowbar { font-size: smaller; background: #ffffcc;
+ text-align: left; }
+
+.yellowbarrt { font-size: smaller; background: #ffffcc;
+ text-align: right; }
+
+.yellowspace { font-size: 4pt; background: #ffffcc; }
+
+.datacntr { font-size: smaller;
+ color: #000000; background: #ffffff; text-align: center; }
+
+.datacntrgrey { font-size: smaller;
+ color: #000000; background: #eeeeee; text-align: center; }
+
+.hdctr { font-size: smaller; font-weight: bold; color: #333333;
+ background: #cccccc; text-align: center;}
+
+
+
+
+/* deprecated - duplicate functionality - use .fine */
+
+/* deprecated - duplicate functionality - use .fineright */
+
+
+/* deprecated - duplicate functionality - use .data and .datagrey */
+/*.normal { font-family: arial, geneva, helvetica, "sans serif"; }*/
+/*.normalgrey { font-family: arial, geneva, helvetica, "sans serif"; background: #cccccc; }*/
+
+/* deprecated - duplicate functionality - not sure what this is used for */
+/*.bottom { vertical-align: bottom; }*/
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/vboxLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/vboxLayout.jsp
new file mode 100644
index 0000000..135b1c2
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/layout/vboxLayout.jsp
@@ -0,0 +1,36 @@
+<%@ page import="java.util.Iterator"%>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<%-- Layout component
+ Render a list on severals columns
+ parameters : componentsList
+--%>
+
+<tiles:useAttribute id="list" name="componentsList" classname="java.util.List" />
+
+<%-- Normally, we should use the iterate tag to iterate over the list.
+ Unfortunatelly, this doesn't work with jsp1.1, because actual iterate tag use a BodyContent
+ and include do a flush(), which is illegal inside a BodyContent.
+ Jsp1.3 propose a new tag mechanism for iteration, which not use BodyContent.
+ Wait until jsp1.3
+
+<logic:iterate id="comp" name="list" type="String" >
+ <tiles:insert name="<%=comp%>" flush="false" />
+ <br>
+</logic:iterate>
+--%>
+
+<%-- For now, do iteration manually : --%>
+<%
+Iterator i=list.iterator();
+while( i.hasNext() )
+ {
+ String comp=(String)i.next();
+%>
+<tiles:insert name="<%=comp%>" flush="true" />
+<br>
+
+<%
+ } // end loop
+%>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/overloadDefinitionParameters.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/overloadDefinitionParameters.jsp
new file mode 100644
index 0000000..c6ff1c9
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/overloadDefinitionParameters.jsp
@@ -0,0 +1,5 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="myFirstDefinition" flush="true" >
+ <tiles:put name="title" value="My First Definition Page With Overloaded Title" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert1.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert1.jsp
new file mode 100644
index 0000000..679863e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert1.jsp
@@ -0,0 +1 @@
+<IMG src='<%=request.getContextPath()%>/tutorial/images/banner1b.gif' border=0>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert2.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert2.jsp
new file mode 100644
index 0000000..c35d5a2
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert2.jsp
@@ -0,0 +1,2 @@
+<DIV align=center><STRONG><FONT size=4><IMG alt="" border=0 height=120
+src="<%=request.getContextPath()%>/tutorial/images/banner_bottom.gif" width=300></FONT></STRONG></DIV>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert3.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert3.jsp
new file mode 100644
index 0000000..679863e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/advert3.jsp
@@ -0,0 +1 @@
+<IMG src='<%=request.getContextPath()%>/tutorial/images/banner1b.gif' border=0>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/login.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/login.jsp
new file mode 100644
index 0000000..1c5d81e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/login.jsp
@@ -0,0 +1,10 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=300>
+
+ <TR>
+ <TD class=spanhd>Login</TD></TR>
+ <TR>
+ <TD class=yellow><!-- IF statement for Alert section here -->
+ <P>If you have World Financial accounts, you can <U>Login</U> to
+ view your account information.<BR>
+</P></TD></TR></TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/messages.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/messages.jsp
new file mode 100644
index 0000000..f10ee1b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/messages.jsp
@@ -0,0 +1,19 @@
+<DIV align=center><STRONG><FONT size=4>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=300>
+
+ <TR>
+ <TD class=spanhd><B>Messages</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Your CD matures in one month!</U></FONT>
+ <LI><FONT color=#003366><U>Now Providing a Technology Mutual Fund</U></FONT>
+ <LI><FONT color=#003366><U>Children's Savings Account Program
+ Update</U></FONT>
+ <LI><FONT color=#003366><U>Small Business Program Offer</U></FONT>
+ <LI><FONT color=#003366><U>Financial Tip of the Day</U></FONT>
+ <LI><FONT color=#003366><U>Mortgage Rate Chart - See how we
+ compare!</U></FONT>
+ <LI><FONT color=#003366><U>Check out our 1-year and 6-month CD
+ rates</U></FONT>
+ <LI><FONT color=#003366><U>Auto Insurance Rates Lowered</U></FONT>
+ <BR> </LI></TD></TR></TABLE></FONT></STRONG></DIV>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/newsFeed.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/newsFeed.jsp
new file mode 100644
index 0000000..eccdd74
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/newsFeed.jsp
@@ -0,0 +1,42 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=300>
+
+ <TR>
+ <TD class=spanhd colSpan=2>News Feed</TD></TR>
+ <TR>
+ <TD class=data><B>Business News</B> </TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Top Fund Managers Make Their Calls On
+ Funds</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>World News</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>China Democracy Crackdown</U></FONT>
+ <LI><FONT color=#003366><U>Pope Visits The U.S. In
+ May</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>General News</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Clinton Polls in Question As To
+ Accuracy</U></FONT>
+ <LI><FONT color=#003366><U>School Violence Erupts And Safety Questions Are
+ Raised</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>Sports</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Winners And Losers - NFL Season
+ Wrap-Up</U></FONT>
+ <LI><FONT color=#003366><U>Ski Finals On The Wire For The Alpine
+ Championships</U></FONT></LI></TD></TR>
+ <TR>
+ <TD class=data><B>Health</B></TD></TR>
+ <TR>
+ <TD class=data>
+ <LI><FONT color=#003366><U>Tea - A Cup of Comfort</U></FONT>
+ <LI><FONT color=#003366><U>Relieve Stress The Natural Way: 10 Health
+ Tips</U></FONT> </LI></TD></TR>
+</TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/personalLinks.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/personalLinks.jsp
new file mode 100644
index 0000000..b89cfdc
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/personalLinks.jsp
@@ -0,0 +1,14 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=190>
+
+ <TR>
+ <TD class=spanhd>My Personal Links</TD></TR>
+ <TR>
+ <TD class=datagrey>
+ <LI><FONT color=#003366><U>Free Edgar</U></FONT>
+ <LI><FONT color=#003366><U>Raging Bull</U></FONT>
+ <LI><FONT color=#003366><U>The Motley Fool</U></FONT>
+ <LI><FONT color=#003366><U>The Street.com</U></FONT> <BR> </LI></TD></TR>
+ <TR>
+ <TD class=datagrey><IMG border=0 height=1 src="<%=request.getContextPath()%>/tutorial/images/clear.gif"
+ width=190></TD></TR></TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/portalBody.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/portalBody.jsp
new file mode 100644
index 0000000..585faac
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/portalBody.jsp
@@ -0,0 +1,18 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/layout/columnsLayout.jsp" flush="true">
+ <tiles:put name="numCols" value="2" />
+ <tiles:putList name="list0" >
+ <tiles:add value="/tutorial/portal/login.jsp" />
+ <tiles:add value="/tutorial/portal/messages.jsp" />
+ <tiles:add value="/tutorial/portal/newsFeed.jsp" />
+ <tiles:add value="/tutorial/portal/advert2.jsp" />
+ </tiles:putList>
+ <tiles:putList name="list1" >
+ <tiles:add value="/tutorial/portal/advert3.jsp" />
+ <tiles:add value="/tutorial/portal/stocks.jsp" />
+ <tiles:add value="/tutorial/portal/whatsNew.jsp" />
+ <tiles:add value="/tutorial/portal/personalLinks.jsp" />
+ <tiles:add value="/tutorial/portal/search.jsp" />
+ </tiles:putList>
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/search.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/search.jsp
new file mode 100644
index 0000000..d441713
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/search.jsp
@@ -0,0 +1,23 @@
+<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=190>
+ <FORM name=panel>
+ <TBODY>
+ <TR>
+ <TD class=spanhd>Internet Search</TD></TR>
+ <TR>
+
+<logic:present parameter="query">
+<bean:parameter id="query" name="query"/>
+ <TD class=datagrey>Query found : <BR><BR> <%=query%></TD></TR>
+</logic:present>
+
+ <TD class=datagrey>Enter a term or topic: <BR><BR><INPUT maxLength=32
+ name=query size=17></TD></TR>
+ <TR>
+ <TD class=inputgrey> <INPUT alt="Search the Internet" border=0
+ height=24 name="Search the Internet" src="<%=request.getContextPath()%>/tutorial/images/input_gen_search.gif"
+ title="Search the Internet" type=image
+ width=86></FORM></TD></TR></FORM></TBODY></TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/stocks.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/stocks.jsp
new file mode 100644
index 0000000..0323cde
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/stocks.jsp
@@ -0,0 +1,59 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=190>
+
+ <TR bgColor=#ffffff>
+ <TD class=spanhd colSpan=2>Stewart's Hot Stocks</TD>
+ <TD class=spanhd> </TD></TR>
+ <TR>
+ <TD class=hdleft>Symbol</TD>
+ <TD class=hdleft>Price</TD>
+ <TD class=hdleft>Change</TD></TR>
+ <TR>
+ <TD class=datagrey><U><FONT color=#003366>AOL</FONT></U></TD>
+ <TD class=datagrey>104.25</TD>
+ <TD class=datagrey><FONT color=#cc0000>5.00</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>CSCO</U></FONT></TD>
+ <TD class=datagrey>73.75</TD>
+ <TD class=datagrey><FONT color=#008800>1.75</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>HD</U></FONT></TD>
+ <TD class=datagrey>68.62</TD>
+ <TD class=datagrey><FONT color=#008800>1.69</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>SONE</U></FONT></TD>
+ <TD class=datagrey>38.88</TD>
+ <TD class=datagrey><FONT color=#008800>1.62</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=datagrey><FONT color=#003366><U>DJIA</U></FONT></TD>
+ <TD class=datagrey>10,302.13</TD>
+ <TD class=datagrey><FONT color=#008800>47.80</FONT></TD></TR>
+ <TR>
+ <TD class=datagrey colSpan=3><IMG height=1 src="<%=request.getContextPath()%>/tutorial/images/id_line.gif"
+ width=190></TD></TR>
+ <TR>
+ <TD class=inputgrey colSpan=3>
+ <FORM
+ action="#" method="get">Quote:
+ <INPUT maxLength=5 size=4> <A
+ href="#"><IMG alt="Get Quote"
+ border=0 height=17 src="<%=request.getContextPath()%>/tutorial/images/input_vrm_gen_get.gif" title="Get Quote"
+ width=59></A> <BR> <BR>
+ <CENTER><FONT size=-2>[ </FONT><FONT color=#003366 size=-2><A
+ href="#">Symbol Search</A></FONT><FONT
+ size=-2> ]</FONT> <FONT size=-2>[ </FONT><FONT
+ color=#003366 size=-2><U>Edit Portfolio</U></FONT><FONT
+ size=-2> ]</FONT></CENTER><BR></TD></TR></TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/whatsNew.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/whatsNew.jsp
new file mode 100644
index 0000000..2885e4e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portal/whatsNew.jsp
@@ -0,0 +1,16 @@
+<div align="center"><font size="+1"><b>
+<TABLE border=0 cellPadding=2 cellSpacing=0 width=190>
+
+ <TR>
+ <TD class=spanhd>What's New</TD></TR>
+ <TR>
+ <TD class=datagrey><B>New Financial Calculators</B> <BR>Saving For A
+ College Education?
+ <BR>[ <FONT color=#003366><U>More</U></FONT> ]
+ <BR> <BR><B>Special Offer</B>
+ <BR>Get free real-time quotes for three months with a World Financial
+ brokerage account. [ <FONT color=#003366><U>More</U></FONT> ]
+ <BR> </TD></TR>
+ <TR>
+ <BR><IMG border=0 height=1 src="<%=request.getContextPath()%>/tutorial/images/clear.gif"
+width=190></TD></TR></TABLE> </b></font></div>
\ No newline at end of file
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/portalPage.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portalPage.jsp
new file mode 100644
index 0000000..edc2412
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/portalPage.jsp
@@ -0,0 +1,10 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/tutorial/layout/classicLayout.jsp" flush="true">
+ <tiles:put name="title" value="My First Portal Page" />
+ <tiles:put name="header" value="/tutorial/common/header.jsp" />
+ <tiles:put name="footer" value="/tutorial/common/footer.jsp" />
+ <tiles:put name="menu" value="/tutorial/basic/menu.jsp" />
+ <%-- <tiles:put name="menu" value="/tutorial/common/menu.jsp" /> --%>
+ <tiles:put name="body" value="/tutorial/portal/portalBody.jsp" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/strutsForward.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/strutsForward.jsp
new file mode 100644
index 0000000..dccb3a8
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/strutsForward.jsp
@@ -0,0 +1,3 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert definition="forward.example.choice.page" flush="true" />
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/test.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test.jsp
new file mode 100644
index 0000000..012097e
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test.jsp
@@ -0,0 +1,21 @@
+<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<html:html>
+ <head>
+ <title>Content Form</title>
+ </head>
+
+ <body bgcolor="white">
+ <bean:insert id='xout2' page='/testAction.do'/>
+ <bean:write name='xout2' filter='true'/>
+
+ <tiles:insert template="/forwardExampleAction.do">
+ <tiles:put name="label" content="Text:" direct="true"/>
+ <tiles:put name="property" content="contentForm" direct="true"/>
+ </tiles:insert>
+
+
+ </body>
+</html:html>
+
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/header.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/header.jsp
new file mode 100644
index 0000000..0755beb
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/header.jsp
@@ -0,0 +1,8 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+
+<P><img src="<%=request.getContextPath()%>/images/id_nav_outside.gif" align="left" border="0">
+<img src="<%=request.getContextPath()%>/images/id_nav_bkgnd.gif" align="right" border="0"> </P>
+
+value="<tiles:getAsString name="body"/>"
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/myLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/myLayout.jsp
new file mode 100644
index 0000000..f61649c
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/myLayout.jsp
@@ -0,0 +1,35 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<%-- Layout component
+ parameters : title, header, menu, body, footer
+--%>
+
+<html>
+<head>
+ <title><tiles:getAsString name="title"/></title>
+</head>
+
+<body>
+<TABLE width="100%">
+
+ <TR>
+ <TD colspan="2">
+ <tiles:insert attribute="header" >
+ <tiles:put name="body" beanName="body" beanScope="template" />
+ </tiles:insert>
+ </TD></TR>
+ <TR>
+ <TD width="120"><tiles:insert attribute="menu" /></TD>
+ <TD>
+ <tiles:useAttribute name="body" classname="java.lang.String"/>
+ <bean:insert id="bodyStr" page="<%=body%>" />
+ <bean:write name="bodyStr" filter="false"/>
+ </TD></TR>
+ <TR>
+ <TD colspan="2"><tiles:insert attribute="footer" /></TD>
+ </TR>
+</TABLE>
+
+</body>
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/templateLayout.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/templateLayout.jsp
new file mode 100644
index 0000000..728ffc1
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test/templateLayout.jsp
@@ -0,0 +1,29 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<%-- Layout component
+ parameters : title, header, menu, body, footer
+--%>
+
+<html>
+<head>
+ <title><tiles:get name="title"/></title>
+</head>
+
+<body>
+<TABLE width="100%">
+
+ <TR>
+ <TD colspan="2"><tiles:get name="header" /></TD></TR>
+ <TR>
+ <TD width="120"><tiles:get name="menu" /></TD>
+ <TD>
+ **<tiles:insert name="body" flush='true'/>**
+ </TD></TR>
+ <TR>
+ <TD colspan="2"><tiles:get name="footer" /></TD>
+ </TR>
+</TABLE>
+
+</body>
+</html>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/test2.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test2.jsp
new file mode 100644
index 0000000..025686a
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test2.jsp
@@ -0,0 +1,9 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+
+<tiles:insert page="/test/myLayout.jsp" flush="true">
+ <tiles:put name="title" value="My first page" />
+ <tiles:put name="header" value="/test/header.jsp" />
+ <tiles:put name="footer" value="/common/footer.jsp" />
+ <tiles:put name="menu" value="/basic/menu.jsp" />
+ <tiles:put name="body" value="/forwardExampleAction.do" />
+</tiles:insert>
diff --git a/struts-sandbox/tiles-documentation/src/webapp/tutorial/test3.jsp b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test3.jsp
new file mode 100644
index 0000000..9c6bb2b
--- /dev/null
+++ b/struts-sandbox/tiles-documentation/src/webapp/tutorial/test3.jsp
@@ -0,0 +1,18 @@
+<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
+<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
+
+<tiles:insert template='/test/templateLayout.jsp'>
+ <tiles:put name="title" content="My first page" direct="true"/>
+ <tiles:put name="header" content="/common/header.jsp" direct="true"/>
+ <tiles:put name="footer" content="/common/footer.jsp" />
+ <tiles:put name="menu" content="/basic/menu.jsp" direct="true"/>
+ <tiles:put name="body" content='/testAction.do' type="page"/>
+</tiles:insert>
+
+<%--
+ <tiles:put name="body" content='/testAction2.do'/>
+ <tiles:put name="body" direct='true'>
+ <bean:insert id='xout2' page='/forwardExampleAction.do'/>
+ <bean:write name='xout2' filter='false'/>
+ </tiles:put>
+--%>
diff --git a/struts-sandbox/tiles-original/NOTICE.txt b/struts-sandbox/tiles-original/NOTICE.txt
new file mode 100644
index 0000000..3f59805
--- /dev/null
+++ b/struts-sandbox/tiles-original/NOTICE.txt
@@ -0,0 +1,2 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/struts-sandbox/tiles-original/README.txt b/struts-sandbox/tiles-original/README.txt
new file mode 100644
index 0000000..e7084fb
--- /dev/null
+++ b/struts-sandbox/tiles-original/README.txt
@@ -0,0 +1,47 @@
+WHAT IS THIS?
+
+This is a standalone version of Tiles, extricated from Struts 1.1.
+
+
+HOW IS IT DIFFERENT FROM STRUTS TILES?
+
+There are a few differences between this version of Tiles and Tiles included
+in Struts 1.1.
+
+1. Instead of org.apache.struts.tiles, standalone Tiles uses org.apache.tiles.
+ This means:
+
+ a. Your Tiles servlet declaration in web.xml should look like this:
+
+ <servlet>
+ <servlet-name>Tiles Servlet</servlet-name>
+ <servlet-class>org.apache.tiles.servlets.TilesServlet</servlet-class>
+ ...
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ (Note the classname for the Tiles servlet:
+ org.apache.tiles.servlets.TilesServlet)
+
+ b. The fully qualified name for Tiles controllers has changed to
+ org.apache.tiles.Controller.
+
+2. Instead of http://jakarta.apache.org/struts/tags-tiles for the tag library
+ uri, standalone Tiles uses http://jakarta.apache.org/tiles. So your taglib
+ declaration should like this:
+
+ <%@ taglib uri="http://jakarta.apache.org/tiles" %>
+
+
+HOW DO I GET STARTED?
+
+First, you must build the tiles-core.jar file. Copy build.properties.sample
+to build.properties and edit properties as appropriate. Then change to
+the core-library directory and do "ant dist". That will create, among other
+things, core-library/dist/lib/tiles-core.jar, which you include in the lib
+directory of your WAR file.
+
+To get started using Tiles, you'll find an examples/simple directory in
+the top-level directory (in which this file resides). That directory contains
+a simple example that illustrates Tiles fundamentals. That application is
+documented in tiles.pdf, which is also in the top-level directory.
diff --git a/struts-sandbox/tiles-original/build.properties.sample b/struts-sandbox/tiles-original/build.properties.sample
new file mode 100644
index 0000000..4d23712
--- /dev/null
+++ b/struts-sandbox/tiles-original/build.properties.sample
@@ -0,0 +1,60 @@
+# build.properties.sample
+# -----------------------
+#
+# ==============================================================================
+# Copyright 2004 The Apache Software Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ==============================================================================
+#
+# This file contains example property settings that you would use to customzie
+# your build environment to build the Struts Shale Library from
+# source code. To use this file, make a copy of it in "build.properties" and
+# customize the values as required.
+#
+# $Id: $
+#
+
+# The absolute or relative pathname of the directory containing the
+# Jakarta Commons BeanUtils library
+beanutils.home = /Developer/Java/Tools/jakarta/commons-beanutils-1.6.1
+
+# The absolute or relative pathname of the directory containing the
+# Jakarta Commons Digester library
+digester.home = /Developer/Java/Tools/jakarta/commons-digester-1.5
+
+# The absolute or relative pathname of the directory containing the
+# Jakarta Commons Logging library
+logging.home = /Developer/Java/Tools/jakarta/commons-logging-1.0.3
+
+# The absolute or relative pathname of the directory containing your
+# Servlet API classes JAR file (servlet.jar)
+server.home = /Developer/Java/Tools/jakarta/jakarta-tomcat-5.0.30
+
+# The absolute or relative pathname of the JavaServer Faces
+# implementation
+jsf.home = /Developer/Java/Tools/jsf-1_1_01
+
+# The absolute or relative pathname of the JUnit 3.8.1 JAR
+junit.home = /Developer/Java/Tools/junit3.8.1
+
+# The absolute or relative pathname of the JSTL install dir
+jstl.home = /Developer/Java/Tools/jakarta/jakarta-taglibs-standard-1.1.0
+
+# The absolute or relative pathname of the JSTL install dir
+jstl.home = /Developer/Java/Tools/jakarta/jakarta-taglibs-standard-1.1.0
+
+# The username and password for Tomcat for hot deploys
+username=yourUsername
+password=yourPassword
+manager.url=http://localhost:8080/manager
diff --git a/struts-sandbox/tiles-original/core-library/LICENSE.txt b/struts-sandbox/tiles-original/core-library/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/struts-sandbox/tiles-original/core-library/NOTICE.txt b/struts-sandbox/tiles-original/core-library/NOTICE.txt
new file mode 100644
index 0000000..819698e
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/NOTICE.txt
@@ -0,0 +1,8 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+This product includes the JavaServer Faces reference
+implementation, developed by Sun Microsystems
+(http://java.sun.com/j2ee/javaserverfaces/) and
+redistributed in accordance with license terms found
+in LICENSE-JSF.txt.
diff --git a/struts-sandbox/tiles-original/core-library/build.xml b/struts-sandbox/tiles-original/core-library/build.xml
new file mode 100644
index 0000000..48ad276
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/build.xml
@@ -0,0 +1,301 @@
+<!--
+
+ Copyright 2004-2005 The Apache Software Foundation.
+
+ Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ $Id: build.xml 54942 2004-10-16 22:39:25Z craigmcc $
+
+-->
+
+
+<project name="Tiles Core Library" default="library" basedir=".">
+
+
+ <!-- ===================== Initialize Property Values ==================== -->
+
+
+ <!-- Initialize property values -->
+ <property file="build.properties"/>
+ <property file="../build.properties"/>
+ <property file="../../build.properties"/>
+ <property file="${user.home}/build.properties"/>
+
+
+ <!-- Build Defaults -->
+ <property name="build.home" value="${basedir}/target"/>
+ <property name="dist.home" value="${basedir}/dist"/>
+ <property name="project.name" value="Tiles Core Library"/>
+ <property name="project.package" value="org.apache.tiles"/>
+ <property name="project.version" value="0.1-dev"/>
+
+
+ <!-- Dependency library defaults -->
+ <property name="commons-beanutils.jar" value="${beanutils.home}/commons-beanutils.jar"/>
+ <property name="commons-digester.jar" value="${digester.home}/commons-digester.jar"/>
+ <property name="commons-logging.jar" value="${logging.home}/commons-logging.jar"/>
+ <property name="jsp-api.jar" value="${server.home}/common/lib/jsp-api.jar"/>
+ <property name="jsf-impl.jar" value="${jsf.home}/lib/jsf-impl.jar"/>
+ <property name="jsf-api.jar" value="${jsf.home}/lib/jsf-api.jar"/>
+ <property name="junit.jar" value="${junit.home}/junit.jar"/>
+ <property name="servlet-api.jar" value="${server.home}/common/lib/servlet-api.jar"/>
+
+
+ <!-- Compile Defaults -->
+ <property name="compile.debug" value="true"/>
+ <property name="compile.deprecation" value="false"/>
+ <property name="compile.optimize" value="true"/>
+
+
+ <!-- Unit Test Defaults -->
+ <property name="test.haltonerror" value="true"/>
+ <property name="test.haltonfailure" value="true"/>
+ <property name="test.runner" value="junit.textui.TestRunner"/>
+
+
+ <!-- Compile Classpath -->
+ <path id="compile.classpath">
+ <pathelement location="${commons-beanutils.jar}"/>
+ <pathelement location="${commons-digester.jar}"/>
+ <pathelement location="${commons-logging.jar}"/>
+ <pathelement location="${jsf-api.jar}"/>
+ <pathelement location="${jsf-impl.jar}"/>
+ <pathelement location="${jsp-api.jar}"/>
+ <pathelement location="${servlet-api.jar}"/>
+ <pathelement location="${build.home}/classes"/>
+ </path>
+
+
+ <!-- Findbugs Classpath -->
+ <path id="findbugs.classpath">
+ <pathelement location="${commons-beanutils.jar}"/>
+ <pathelement location="${commons-digester.jar}"/>
+ <pathelement location="${commons-logging.jar}"/>
+ <pathelement location="${jsf-api.jar}"/>
+ <pathelement location="${jsp-api.jar}"/>
+ <pathelement location="${servlet-api.jar}"/>
+ </path>
+
+
+ <!-- Test Classpath -->
+ <path id="test.classpath">
+ <pathelement location="${commons-beanutils.jar}"/>
+ <pathelement location="${commons-digester.jar}"/>
+ <pathelement location="${jsf-api.jar}"/>
+ <pathelement location="${jsp-api.jar}"/>
+ <pathelement location="${junit.jar}"/>
+ <pathelement location="${servlet-api.jar}"/>
+ <pathelement location="${build.home}/classes"/>
+ <pathelement location="${build.home}/test-classes"/>
+ </path>
+
+
+ <!-- ==================== Maintenance Targets ============================ -->
+
+
+ <target name="clean"
+ description="Clean all build directories">
+ <delete dir="${build.home}"/>
+ <delete dir="${dist.home}"/>
+ </target>
+
+
+ <target name="init">
+ <echo message="---------- ${project.name} ${project.version} -----------"/>
+ <filter token="name" value="${project.name}"/>
+ <filter token="package" value="${project.package}"/>
+ <filter token="state" value="${systest.state.saving}"/>
+ <filter token="version" value="${project.version}"/>
+ <echo message="commons-beanutils.jar = ${commons-beanutils.jar}"/>
+ <echo message="commons-digester.jar = ${commons-digester.jar}"/>
+ <echo message="commons-logging.jar = ${commons-logging.jar}"/>
+ <echo message="jsf-api.jar = ${jsf-api.jar}"/>
+ <echo message="jsf-impl.jar = ${jsf-impl.jar}"/>
+ <echo message="jsp-api.jar = ${jsp-api.jar}"/>
+ <echo message="servlet-api.jar = ${servlet-api.jar}"/>
+ </target>
+
+
+ <target name="prepare" depends="init">
+ <mkdir dir="${build.home}"/>
+ <mkdir dir="${build.home}/classes"/>
+ <mkdir dir="${build.home}/classes/META-INF"/>
+ <mkdir dir="${build.home}/conf"/>
+ <mkdir dir="${build.home}/lib"/>
+ <mkdir dir="${dist.home}"/>
+ <mkdir dir="${dist.home}/docs"/>
+ <mkdir dir="${dist.home}/docs/api"/>
+ </target>
+
+
+ <target name="static" depends="prepare">
+ <tstamp/>
+ <copy todir="${build.home}/conf"
+ filtering="on">
+ <fileset dir="src/conf"
+ includes="*.MF"/>
+ </copy>
+ <copy todir="${build.home}/classes/META-INF">
+ <fileset dir="src/conf"
+ includes="tiles-core.tld"/>
+ </copy>
+ </target>
+
+
+ <!-- =================== Compile Library Components ====================== -->
+
+
+ <target name="compile" depends="static"
+ description="Compile core library">
+
+ <!-- Compile Java Sources -->
+ <javac srcdir="src/java"
+ destdir="${build.home}/classes"
+ debug="${compile.debug}"
+ deprecation="${compile.deprecation}"
+ optimize="${compile.optimize}">
+ <classpath refid="compile.classpath" />
+ </javac>
+
+ <!-- Copy non-Java Sources -->
+ <copy todir="${build.home}/classes">
+ <fileset dir="src/java">
+ <exclude name="**/*.java"/>
+ </fileset>
+ </copy>
+
+ <!-- Copy DTDs into appropriate resources directory -->
+ <mkdir dir="${build.home}/classes/org/apache/tiles/resources"/>
+ <copy todir="${build.home}/classes/org/apache/tiles/resources">
+ <fileset dir="src/conf"
+ includes="*.dtd"/>
+ </copy>
+
+ <!-- Copy license and notice files -->
+ <copy tofile="${build.home}/classes/META-INF/LICENSE.txt"
+ file="LICENSE.txt"/>
+ <copy tofile="${build.home}/classes/META-INF/NOTICE.txt"
+ file="NOTICE.txt"/>
+
+ </target>
+
+
+ <target name="library" depends="compile"
+ description="Package core library">
+
+ <jar jarfile="${build.home}/lib/tiles-core.jar"
+ basedir="${build.home}/classes"/>
+ </target>
+
+
+ <!-- ===================== Generate Documentation ======================== -->
+
+
+ <target name="docs" depends="library"
+ description="Create generated documentation and JavaDocs">
+
+ <javadoc
+ sourcepath="src/java"
+ destdir="${dist.home}/docs/api"
+ author="false"
+ private="true"
+ version="true"
+ packagenames="org.apache.tiles.*"
+ windowtitle="${project.name} (Version ${project.version})"
+ doctitle="${project.name} (Version ${project.version})"
+ bottom="Copyright © 2004-2005 - The Apache Software Foundation">
+ <classpath refid="compile.classpath"/>
+ </javadoc>
+
+ </target>
+
+
+ <!-- ==================== Create Binary Distribution ==================== -->
+
+
+ <target name="dist" depends="docs"
+ description="Create binary distribution">
+
+ <mkdir dir="${dist.home}"/>
+ <copy todir="${dist.home}">
+ <fileset dir="${basedir}" includes="*.txt build.*"
+ excludes="build.properties"/>
+ </copy>
+
+ <mkdir dir="${dist.home}/conf"/>
+ <copy todir="${dist.home}/conf">
+ <fileset dir="src/conf" includes="*.tld"/>
+ <fileset dir="src/conf" includes="*.dtd"/>
+ </copy>
+
+ <mkdir dir="${dist.home}/lib"/>
+ <copy todir="${dist.home}/lib">
+ <fileset dir="${build.home}/lib" includes="*.jar"/>
+ </copy>
+
+ <mkdir dir="${dist.home}/src"/>
+ <copy todir="${dist.home}/src">
+ <fileset dir="src" excludes="**/.svn/**"/>
+ </copy>
+
+ </target>
+
+
+ <!-- ========================= Unit Tests ================================ -->
+
+
+ <target name="test:compile" depends="library"
+ description="Compile library unit tests">
+
+ <mkdir dir="${build.home}/test-classes"/>
+
+ <!-- Compile Java Sources -->
+ <javac srcdir="src/test"
+ destdir="${build.home}/test-classes"
+ debug="${compile.debug}"
+ deprecation="${compile.deprecation}"
+ optimize="${compile.optimize}">
+ <classpath refid="test.classpath" />
+ </javac>
+
+ <!-- Copy non-Java Sources -->
+ <copy todir="${build.home}/test-classes">
+ <fileset dir="src/test">
+ <exclude name="**/*.java"/>
+ </fileset>
+ </copy>
+
+ </target>
+
+
+ <target name="test" depends="test:compile"
+ description="Execute library unit tests">
+ <junit fork="yes"
+ haltonerror="${test.haltonerror}"
+ haltonfailure="${test.haltonfailure}"
+ printSummary="no">
+
+ <classpath refid="test.classpath"/>
+ <formatter type="plain"
+ usefile="false"/>
+ <batchtest fork="yes">
+ <fileset dir="${build.home}/test-classes"
+ includes="org/apache/tiles/*/*TestCase.class"/>
+ </batchtest>
+
+ </junit>
+
+ </target>
+
+
+</project>
diff --git a/struts-sandbox/tiles-original/core-library/src/conf/tiles-config_1_2.dtd b/struts-sandbox/tiles-original/core-library/src/conf/tiles-config_1_2.dtd
new file mode 100644
index 0000000..f883763
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/conf/tiles-config_1_2.dtd
@@ -0,0 +1,280 @@
+<!--
+ DTD for the Tile Definition File, Version 1.2
+
+ To support validation of your configuration file, include the following
+ DOCTYPE element at the beginning (after the "xml" declaration):
+
+ <!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.2//EN"
+ "http://apache.org/dtds/tiles-config_1_2.dtd">
+
+-->
+
+
+<!-- ========== Defined Types ============================================= -->
+
+
+<!-- A "Boolean" is the string representation of a boolean (true or false)
+ variable.
+-->
+<!ENTITY % Boolean "(true|false)">
+
+
+<!-- A "ContentType" is the content type of an attribute passed to a tile
+ component.
+-->
+<!ENTITY % ContentType "(string|page|template|definition)">
+
+<!-- A "ClassName" is the fully qualified name of a Java class that is
+ instantiated to provide the functionality of the enclosing element.
+-->
+<!ENTITY % ClassName "CDATA">
+
+<!-- A "RequestPath" is an module-relative URI path, beginning with a
+ slash, that identifies a mapped resource (such as a JSP page or a servlet)
+ within this web application.
+-->
+<!ENTITY % RequestPath "CDATA">
+
+<!-- A "DefinitionName" is the unique identifier of a definition. This identifier
+ is a logical name used to reference the definition.
+-->
+<!ENTITY % DefinitionName "CDATA">
+
+<!-- A "BeanName" is the identifier of a JavaBean, such as a form bean,
+ and also serves as the name of the corresponding scripting variable
+ and the name of the JSP attribute under which the bean is accessed.
+ Therefore, it must conform to the rules for a Java identifier.
+-->
+<!ENTITY % BeanName "CDATA">
+
+<!-- A "PropName" is the name of a JavaBeans property, and must begin with
+ a lower case letter and contain only characters that are legal in a
+ Java identifier.
+-->
+<!ENTITY % PropName "CDATA">
+
+<!-- A "Location" is a relative path, delimited by "/" characters, that
+ defines the location of a resource relative to the location of the
+ configuration file itself.
+-->
+<!ENTITY % Location "#PCDATA">
+
+
+
+<!-- ========== Top Level Elements ======================================== -->
+
+
+ <!-- deprecated: use tiles-definitions instead.-->
+<!ELEMENT component-definitions (definition+)>
+
+<!-- The "tiles-definitions" element is the root of the configuration file
+ hierarchy, and contains nested elements for all of the other
+ configuration settings.
+-->
+<!ELEMENT tiles-definitions (definition+)>
+
+<!-- The "definition" element describes a definition that can be inserted in a jsp
+ page. This definition is identified by its logical name. A definition allows
+ to define all the attributes that can be set in <insert> tag from a jsp page.
+
+ controllerClass The fully qualified Java class name of the controller
+ subclass to call immediately before the tiles is inserted.
+ Only one of controllerClass or controllerUrl should be
+ specified.
+
+ controllerUrl The context-relative path to the resource used as controller
+ called immediately before the tiles is inserted.
+ Only one of controllerClass or controllerUrl should be
+ specified.
+
+ extends Name of a definition that is used as ancestor of this definition.
+ All attributes from the ancestor are available to the new
+ definition. Any attribute inherited from the ancestor can
+ be overloaded by providing a new value.
+
+ name The unique identifier for this definition.
+
+ page Same as path.
+
+ path The context-relative path to the resource used as tiles to
+ insert. This tiles will be inserted and a tiles context
+ containing appropriate attributes will be available.
+
+ role Security role name that is allowed access to this definition
+ object. The definition is inserted only if the role name is
+ allowed.
+
+ template Same as path. For compatibility with the template tag library.
+-->
+<!ELEMENT definition (icon?, display-name?, description?, put*, putList*)>
+<!ATTLIST definition id ID #IMPLIED>
+<!ATTLIST definition controllerClass %ClassName; #IMPLIED>
+<!ATTLIST definition controllerUrl %RequestPath; #IMPLIED>
+<!ATTLIST definition extends %DefinitionName; #IMPLIED>
+<!ATTLIST definition name %DefinitionName; #REQUIRED>
+<!ATTLIST definition page %RequestPath; #IMPLIED>
+<!ATTLIST definition path %RequestPath; #IMPLIED>
+<!ATTLIST definition role CDATA #IMPLIED>
+<!ATTLIST definition template %RequestPath; #IMPLIED>
+
+
+<!-- The "put" element describes an attribute of a definition. It allows to
+ specify the tiles attribute name and its value. The tiles value can be
+ specified as an xml attribute, or in the body of the <put> tag.
+
+ content Same as value. For compatibility with the template tag library.
+
+ direct Same as type="string". For compatibility with the template
+ tag library.
+
+ name The unique identifier for this put.
+
+ type The type of the value. Can be: string, page, template or definition.
+ By default, no type is associated to a value. If a type is
+ associated, it will be used as a hint to process the value
+ when the attribute will be used in the inserted tiles.
+
+ value The value associated to this tiles attribute. The value should
+ be specified with this tag attribute, or in the body of the tag.
+-->
+<!ELEMENT put (#PCDATA)>
+<!ATTLIST put id ID #IMPLIED>
+<!ATTLIST put content CDATA #IMPLIED>
+<!ATTLIST put direct %Boolean; #IMPLIED>
+<!ATTLIST put name CDATA #REQUIRED>
+<!ATTLIST put type %ContentType; #IMPLIED>
+<!ATTLIST put value CDATA #IMPLIED>
+
+
+<!-- The "putList" element describes a list attribute of a definition. It allows to
+ specify an attribute that is a java List containing any kind of values. In
+ the config file, the list elements are specified by nested <add>, <item> or
+ <putList>.
+
+ name The unique identifier for this put list.
+-->
+<!ELEMENT putList ( (add* | item* | bean* | putList*)+) >
+<!ATTLIST putList id ID #IMPLIED>
+<!ATTLIST putList name CDATA #REQUIRED>
+
+<!-- ========== Subordinate Elements ====================================== -->
+
+<!-- The "add" element describes an element of a list. It is similar to the
+ <put> element.
+
+ content Same as value. For compatibility with the template tag library.
+
+ direct Same as type="string". For compatibility with the template
+ tag library.
+
+ type The type of the value. Can be: string, page, template or definition.
+ By default, no type is associated to a value. If a type is
+ associated, it will be used as a hint to process the value
+ when the attribute will be used in the inserted tiles.
+
+ value The value associated to this tiles attribute. The value should
+ be specified with this tag attribute, or in the body of the tag.
+-->
+<!ELEMENT add (#PCDATA)>
+<!ATTLIST add id ID #IMPLIED>
+<!ATTLIST add content CDATA #IMPLIED>
+<!ATTLIST add direct %Boolean; #IMPLIED>
+<!ATTLIST add type %ContentType; #IMPLIED>
+<!ATTLIST add value CDATA #IMPLIED>
+
+
+<!-- The "bean" element describes an element of a list. It create a bean of the
+ specified java classtype. This bean is initialized with appropriate nested
+ <set-property>.
+
+ classtype The fully qualified classname for this bean.
+-->
+<!ELEMENT bean (set-property*)>
+<!ATTLIST bean id ID #IMPLIED>
+<!ATTLIST bean classtype %ClassName; #REQUIRED>
+
+<!-- The "set-property" element specifies the method name and initial value of
+ a bean property. When the object representing
+ the surrounding element is instantiated, the accessor for the indicated
+ property is called and passed the indicated value.
+
+ property Name of the JavaBeans property whose setter method
+ will be called.
+
+ value String representation of the value to which this
+ property will be set, after suitable type conversion
+-->
+<!ELEMENT set-property EMPTY>
+<!ATTLIST set-property id ID #IMPLIED>
+<!ATTLIST set-property property %PropName; #REQUIRED>
+<!ATTLIST set-property value CDATA #REQUIRED>
+
+
+<!-- The "item" element describes an element of a list. It create a bean added as
+ element to the list. Each bean can contain different properties: value, link,
+ icon, tooltip. These properties are to be interpreted by the jsp page using
+ them.
+ By default the bean is of type
+ "org.apache.struts.tiles.beans.SimpleMenuItem". This bean is useful to
+ create a list of beans used as menu items.
+
+ classtype The fully qualified classtype for this bean.
+ If specified, the classtype must be a subclass of the interface
+ "org.apache.struts.tiles.beans.MenuItem".
+
+ icon The bean 'icon' property.
+
+ link The bean 'link' property.
+
+ tooltip The bean 'tooltip' property.
+
+ value The bean 'value' property.
+-->
+<!ELEMENT item (#PCDATA)>
+<!ATTLIST item id ID #IMPLIED>
+<!ATTLIST item classtype %ClassName; #IMPLIED>
+<!ATTLIST item icon CDATA #IMPLIED>
+<!ATTLIST item link CDATA #REQUIRED>
+<!ATTLIST item tooltip CDATA #IMPLIED>
+<!ATTLIST item value CDATA #REQUIRED>
+
+
+<!-- ========== Info Elements ====================================== -->
+
+<!-- The "description" element contains descriptive (paragraph length) text
+ about the surrounding element, suitable for use in GUI tools.
+-->
+<!ELEMENT description (#PCDATA)>
+<!ATTLIST description id ID #IMPLIED>
+
+
+<!-- The "display-name" element contains a short (one line) description of
+ the surrounding element, suitable for use in GUI tools.
+-->
+<!ELEMENT display-name (#PCDATA)>
+<!ATTLIST display-name id ID #IMPLIED>
+
+
+<!-- The "icon" element contains a small-icon and large-icon element which
+ specify the location, relative to the Struts configuration file, for small
+ and large images used to represent the surrounding element in GUI tools.
+-->
+<!ELEMENT icon (small-icon?, large-icon?)>
+<!ATTLIST icon id ID #IMPLIED>
+
+
+<!-- The "large-icon" element specifies the location, relative to the Struts
+ configuration file, of a resource containing a large (32x32 pixel)
+ icon image.
+-->
+<!ELEMENT large-icon (%Location;)>
+<!ATTLIST large-icon id ID #IMPLIED>
+
+
+<!-- The "small-icon" element specifies the location, relative to the Struts
+ configuration file, of a resource containing a small (16x16 pixel)
+ icon image.
+-->
+<!ELEMENT small-icon (%Location;)>
+<!ATTLIST small-icon id ID #IMPLIED>
diff --git a/struts-sandbox/tiles-original/core-library/src/conf/tiles-core.tld b/struts-sandbox/tiles-original/core-library/src/conf/tiles-core.tld
new file mode 100644
index 0000000..235875f
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/conf/tiles-core.tld
@@ -0,0 +1,344 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+
+
+
+
+
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
+<taglib>
+<tlibversion>1.2</tlibversion>
+<jspversion>1.1</jspversion>
+<shortname>tiles</shortname>
+<uri>http://jakarta.apache.org/tiles</uri>
+<tag>
+<name>insert</name>
+<tagclass>org.apache.taglib.tiles.InsertTag</tagclass>
+<bodycontent>JSP</bodycontent>
+<attribute>
+<name>template</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>component</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>page</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>definition</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>attribute</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>name</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanName</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanProperty</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanScope</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>flush</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>ignore</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>role</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>controllerUrl</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>controllerClass</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>definition</name>
+<tagclass>org.apache.taglib.tiles.DefinitionTag</tagclass>
+<bodycontent>JSP</bodycontent>
+<attribute>
+<name>id</name>
+<required>true</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>scope</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>template</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>page</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>role</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>extends</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>put</name>
+<tagclass>org.apache.taglib.tiles.PutTag</tagclass>
+<bodycontent>JSP</bodycontent>
+<attribute>
+<name>name</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>value</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>content</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>direct</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>type</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanName</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanProperty</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanScope</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>role</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>putList</name>
+<tagclass>org.apache.taglib.tiles.PutListTag</tagclass>
+<bodycontent>JSP</bodycontent>
+<attribute>
+<name>name</name>
+<required>true</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>add</name>
+<tagclass>org.apache.taglib.tiles.AddTag</tagclass>
+<bodycontent>JSP</bodycontent>
+<attribute>
+<name>value</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>content</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>direct</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>type</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanName</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanProperty</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>beanScope</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>role</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>get</name>
+<tagclass>org.apache.taglib.tiles.GetTag</tagclass>
+<bodycontent>empty</bodycontent>
+<attribute>
+<name>name</name>
+<required>true</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>ignore</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>flush</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>role</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>getAsString</name>
+<tagclass>org.apache.taglib.tiles.GetAttributeTag</tagclass>
+<bodycontent>empty</bodycontent>
+<attribute>
+<name>name</name>
+<required>true</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>ignore</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>role</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>useAttribute</name>
+<tagclass>org.apache.taglib.tiles.UseAttributeTag</tagclass>
+<teiclass>org.apache.taglib.tiles.UseAttributeTei</teiclass>
+<bodycontent>empty</bodycontent>
+<attribute>
+<name>id</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>classname</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>scope</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>name</name>
+<required>true</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>ignore</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>importAttribute</name>
+<tagclass>org.apache.taglib.tiles.ImportAttributeTag</tagclass>
+<bodycontent>empty</bodycontent>
+<attribute>
+<name>name</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+<attribute>
+<name>scope</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>ignore</name>
+<required>false</required>
+<rtexprvalue>true</rtexprvalue>
+</attribute>
+</tag>
+<tag>
+<name>initComponentDefinitions</name>
+<tagclass>org.apache.taglib.tiles.InitDefinitionsTag</tagclass>
+<bodycontent>empty</bodycontent>
+<attribute>
+<name>file</name>
+<required>true</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+<attribute>
+<name>classname</name>
+<required>false</required>
+<rtexprvalue>false</rtexprvalue>
+</attribute>
+</tag>
+</taglib>
+
+
+
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/LocalStrings.properties b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/LocalStrings.properties
new file mode 100755
index 0000000..88a5a11
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/LocalStrings.properties
@@ -0,0 +1,25 @@
+actionErrors.errors=Cannot process ActionErrors instance of class {0}
+
+actionMessages.errors=Cannot process ActionMessages instance of class {0}
+
+computeURL.forward=Cannot retrieve ActionForward named {0}
+
+computeURL.specifier=You must specify exactly one of "forward", "href", "page" or "action"
+
+lookup.access=Invalid access looking up property {0} of bean {1}
+
+lookup.bean.any=Cannot find bean {0} in any scope
+
+lookup.bean=Cannot find bean {0} in scope {1}
+
+lookup.method=No getter method for property {0} of bean {1}
+
+lookup.scope=Invalid bean scope {0}
+
+lookup.target=Exception thrown by getter for property {0} of bean {1}
+
+message.bundle=Cannot find message resources under key {0}
+
+parameters.multi=Cannot cast to Map for name={0} property={1} scope={2}
+
+write.io=Input/output error: {0}
\ No newline at end of file
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AddTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AddTag.java
new file mode 100644
index 0000000..b1c82c8
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AddTag.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+
+ /**
+ * Add an element to the surrounding list tag.
+ * Same syntax as <code><put></code>.
+ */
+public class AddTag extends PutTag {
+
+ /**
+ * default constructor
+ */
+ public AddTag() {
+ super();
+ }
+
+ /**
+ * Call parent tag which must implement AttributeContainer.
+ * @throws JspException If we can't find an appropriate enclosing tag.
+ */
+ protected void callParent() throws JspException
+ {
+ // Get enclosing parent
+ AddTagParent enclosingParent = findEnclosingPutListTagParent();
+ enclosingParent.processNestedTag( this );
+ }
+
+ /**
+ * Find parent tag which must implement AttributeContainer.
+ * @throws JspException If we can't find an appropriate enclosing tag.
+ */
+ protected AddTagParent findEnclosingPutListTagParent() throws JspException {
+ try
+ {
+ AddTagParent parent = (AddTagParent)findAncestorWithClass(this,AddTagParent.class);
+ if( parent == null )
+ {
+ throw new JspException( "Error - tag add : enclosing tag doesn't accept 'add' tag." );
+ }
+ return parent;
+ }
+ catch( ClassCastException ex )
+ {
+ throw new JspException( "Error - tag add : enclosing tag doesn't accept 'add' tag." );
+ }
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AddTagParent.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AddTagParent.java
new file mode 100644
index 0000000..d586244
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AddTagParent.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+
+/**
+ * Tag classes implementing this interface can contain nested <code>PutTag</code>s.
+ * This interface defines a method called by the nested tag.
+ */
+public interface AddTagParent {
+ /**
+ * Process the nested tag.
+ * @param nestedTag Nested to process.
+ */
+ void processNestedTag(AddTag nestedTag) throws JspException;
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AttributeToScopeTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AttributeToScopeTag.java
new file mode 100644
index 0000000..b9d9020
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/AttributeToScopeTag.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.taglib.tiles.util.TagUtils;
+import org.apache.tiles.ComponentContext;
+
+
+/**
+ * Custom tag that puts component's attributes in a scope (request, page, ...).
+ * @deprecated Is it still in use ?
+ */
+public final class AttributeToScopeTag extends TagSupport {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The scope name.
+ */
+ private String scopeName = null;
+
+ /**
+ * The scope value.
+ */
+ private int scope = PageContext.PAGE_SCOPE;
+
+
+
+ /**
+ * The property name to be exposed.
+ */
+ private String property = null;
+
+
+ // ------------------------------------------------------------- Properties
+
+
+
+ /**
+ * Return the property name.
+ */
+ public String getProperty()
+ {
+ return (this.property);
+ }
+
+
+ /**
+ * Set the property name.
+ *
+ * @param property The property name
+ */
+ public void setProperty(String property)
+ {
+ this.property = property;
+ }
+
+ /**
+ * Set the scope.
+ *
+ * @param scope The new scope
+ */
+ public void setScope(String scope)
+ {
+ this.scopeName = scope;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Expose the requested property from component context.
+ *
+ * @exception JspException if a JSP exception has occurred
+ */
+ public int doStartTag() throws JspException
+ {
+ if( id==null )
+ id=property;
+
+ ComponentContext compContext = (ComponentContext)pageContext.getAttribute( ComponentConstants.COMPONENT_CONTEXT, PageContext.REQUEST_SCOPE);
+
+ if( compContext == null )
+ throw new JspException ( "Error - tag.useProperty : component context is not defined. Check tag syntax" );
+
+ Object value = compContext.getAttribute(property);
+ if( value == null )
+ throw new JspException ( "Error - tag.useProperty : property '"+ property + "' not found in context. Check tag syntax" );
+
+ if( scopeName != null )
+ {
+ scope = TagUtils.getScope( scopeName, PageContext.PAGE_SCOPE );
+ pageContext.setAttribute(id, value, scope);
+ }
+ else
+ pageContext.setAttribute(id, value);
+
+ // Continue processing this page
+ return SKIP_BODY;
+ }
+
+
+
+
+ /**
+ * Clean up after processing this enumeration.
+ *
+ * @exception JspException if a JSP exception has occurred
+ */
+ public int doEndTag() throws JspException
+ {
+ return (EVAL_PAGE);
+ }
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+
+ super.release();
+ property = null;
+ scopeName = null;
+ scope = PageContext.PAGE_SCOPE;
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/ComponentConstants.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/ComponentConstants.java
new file mode 100644
index 0000000..aaecb1e
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/ComponentConstants.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+/**
+ * Constants used by Tiles/Components.
+ */
+public interface ComponentConstants {
+
+ /** Name used to store Tile/Component context. */
+ public static final String COMPONENT_CONTEXT = "org.apache.taglib.tiles.CompContext";
+
+ public static final int COMPONENT_SCOPE = 8;
+
+ // DG: hardcoded LOCALE_KEY and EXCEPTION_KEY to remove dependency
+ // on org.apache.tiles.Globals
+ public static final String LOCALE_KEY = "org.apache.tiles.action.LOCALE";
+ public static final String EXCEPTION_KEY = "org.apache.tiles.action.EXCEPTION";
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/DefinitionTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/DefinitionTag.java
new file mode 100644
index 0000000..ff0a3ba
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/DefinitionTag.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+
+import org.apache.taglib.tiles.util.TagUtils;
+import org.apache.tiles.AttributeDefinition;
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.UntypedAttribute;
+
+/**
+ * This is the tag handler for <tiles:definition>, which defines
+ * a tiles (or template / component). Definition is put in requested context and can be
+ * used in <tiles:insert>.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ * $Id$
+ */
+public class DefinitionTag
+ extends DefinitionTagSupport
+ implements PutTagParent, PutListTagParent {
+
+ /* JSP Tag attributes */
+ /**
+ * Definition identifier.
+ */
+ private String id = null;
+
+ /**
+ * Scope into which definition will be saved.
+ */
+ private String scope = null;
+
+ /**
+ * Extends attribute value.
+ */
+ private String extendsDefinition = null;
+
+ /* Internal properties */
+ /**
+ * Template definition
+ */
+ private ComponentDefinition definition = null;
+
+ /**
+ * Reset member values for reuse. This method calls super.release(),
+ * which invokes TagSupport.release(), which typically does nothing.
+ */
+ public void release() {
+ super.release();
+ id = null;
+ page = null;
+ scope = null;
+ role = null;
+ extendsDefinition = null;
+ }
+
+ /**
+ * Release internal references.
+ */
+ protected void releaseInternal() {
+ definition = null;
+ }
+
+ /**
+ * This method is a convenience for other tags for
+ * putting content into the tile definition.
+ * Content is already typed by caller.
+ */
+ public void putAttribute(String name, Object content) {
+ definition.putAttribute(name, content);
+ }
+
+ /**
+ * Process nested ≶put> tag.
+ * Method is called from nested ≶put> tags.
+ * Nested list is added to current list.
+ * If role is defined, nested attribute is wrapped into an untyped definition
+ * containing attribute value and role.
+ */
+ public void processNestedTag(PutTag nestedTag) throws JspException {
+ // Get real value and check role
+ // If role is set, add it in attribute definition if any.
+ // If no attribute definition, create untyped one and set role.
+ Object attributeValue = nestedTag.getRealValue();
+ AttributeDefinition def;
+
+ if (nestedTag.getRole() != null) {
+ try {
+ def = ((AttributeDefinition) attributeValue);
+ } catch (ClassCastException ex) {
+ def = new UntypedAttribute(attributeValue);
+ }
+ def.setRole(nestedTag.getRole());
+ attributeValue = def;
+ }
+
+ // now add attribute to enclosing parent (i.e. : this object)
+ putAttribute(nestedTag.getName(), attributeValue);
+ }
+
+ /**
+ * Process nested ≶putList> tag.
+ * Method is called from nested ≶putList> tags.
+ * Nested list is added to current list.
+ * If role is defined, nested attribute is wrapped into an untyped definition
+ * containing attribute value and role.
+ */
+ public void processNestedTag(PutListTag nestedTag) throws JspException {
+ // Get real value and check role
+ // If role is set, add it in attribute definition if any.
+ // If no attribute definition, create untyped one and set role.
+ Object attributeValue = nestedTag.getList();
+
+ if (nestedTag.getRole() != null) {
+ AttributeDefinition def = new UntypedAttribute(attributeValue);
+ def.setRole(nestedTag.getRole());
+ attributeValue = def;
+ }
+
+ // Check if a name is defined
+ if (nestedTag.getName() == null) {
+ throw new JspException("Error - PutList : attribute name is not defined. It is mandatory as the list is added to a 'definition'.");
+ }
+
+ // now add attribute to enclosing parent (i.e. : this object).
+ putAttribute(nestedTag.getName(), attributeValue);
+ }
+
+ /**
+ * Get the ID.
+ * @return ID
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Set the ID.
+ * @param id New ID.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Get the scope.
+ * @return Scope.
+ */
+ public String getScope() {
+ return scope;
+ }
+
+ /**
+ * Set the scope.
+ * @param aScope Scope.
+ */
+ public void setScope(String aScope) {
+ scope = aScope;
+ }
+
+ /**
+ * Set <code>extends</code> (parent) definition name.
+ * @param definitionName Name of parent definition.
+ */
+ public void setExtends(String definitionName) {
+ this.extendsDefinition = definitionName;
+ }
+
+ /**
+ * Get <code>extends</code> (parent) definition name.
+ * @return Name of parent definition.
+ */
+ public String getExtends() {
+ return extendsDefinition;
+ }
+
+ /**
+ * Process the start tag by creating a new definition.
+ * @throws JspException On errors processing tag.
+ */
+ public int doStartTag() throws JspException {
+ // Do we extend a definition ?
+ if (extendsDefinition != null && !extendsDefinition.equals("")) {
+ ComponentDefinition parentDef =
+ TagUtils.getComponentDefinition(extendsDefinition, pageContext);
+
+ definition = new ComponentDefinition(parentDef);
+
+ } else {
+ definition = new ComponentDefinition();
+ }
+
+ // Set definitions attributes
+ if (page != null) {
+ definition.setTemplate(page);
+ }
+
+ if (role != null) {
+ definition.setRole(role);
+ }
+
+ return EVAL_BODY_INCLUDE;
+ }
+
+ /**
+ * Process the end tag by putting the definition in appropriate context.
+ * @throws JspException On errors processing tag.
+ */
+ public int doEndTag() throws JspException {
+ TagUtils.setAttribute(pageContext, id, definition, scope);
+
+ releaseInternal();
+ return EVAL_PAGE;
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/DefinitionTagSupport.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/DefinitionTagSupport.java
new file mode 100644
index 0000000..95d40d4
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/DefinitionTagSupport.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import java.io.Serializable;
+
+import javax.servlet.jsp.tagext.TagSupport;
+
+ /**
+ * Common base class for tags dealing with Tiles definitions.
+ * This class defines properties used in Definition Tags.
+ * It also extends TagSupport.
+ */
+public class DefinitionTagSupport extends TagSupport implements Serializable
+{
+ /** Associated Controller type */
+ protected String controllerType;
+ /** Associated Controller name (classname or url) */
+ protected String controllerName;
+
+ /**
+ * Role associated to definition.
+ */
+ protected String role;
+
+ /**
+ * Uri of page assoicated to this definition.
+ */
+ protected String page;
+
+ /**
+ * Release class properties.
+ */
+ public void release() {
+ super.release();
+ controllerType = null;
+ controllerName = null;
+ role = null;
+ page = null;
+ }
+
+ /**
+ * Get controller type.
+ * Type can be 'classname', 'url'.
+ * @return Controller type.
+ */
+ public String getControllerType()
+ {
+ return controllerType;
+ }
+
+ /**
+ * Get controller name.
+ * Name denotes a fully qualified classname, or an url.
+ * Exact type can be specified with {@link #setControllerType}.
+ * @return Controller name.
+ */
+ public String getControllerName()
+ {
+ return controllerName;
+ }
+
+ /**
+ * Set associated controller type.
+ * Type denotes a fully qualified classname.
+ * @param controllerType Type of associated controller.
+ */
+ public void setControllerType(String controllerType)
+ {
+ this.controllerType = controllerType;
+ }
+
+ /**
+ * Set associated controller name.
+ * Name denotes a fully qualified classname, or an url.
+ * Exact type can be specified with {@link #setControllerType}.
+ * @param controller Controller classname or url.
+ */
+ public void setController(String controller)
+ {
+ setControllerName(controller); ;
+ }
+
+ /**
+ * Set associated controller name.
+ * Name denote a fully qualified classname, or an url.
+ * Exact type can be specified with setControllerType.
+ * @param controller Controller classname or url
+ */
+ public void setControllerName(String controller)
+ {
+ this.controllerName = controller;
+ }
+
+ /**
+ * Set associated controller name as an url, and controller
+ * type as "url".
+ * Name must be an url (not checked).
+ * Convenience method.
+ * @param controller Controller url
+ */
+ public void setControllerUrl(String controller)
+ {
+ setControllerName( controller);
+ setControllerType( "url" );
+ }
+
+ /**
+ * Set associated controller name as a classtype and controller
+ * type as "classname".
+ * Name denotes a fully qualified classname.
+ * Convenience method.
+ * @param controller Controller classname.
+ */
+ public void setControllerClass(String controller)
+ {
+ setControllerName( controller);
+ setControllerType( "classname" );
+ }
+
+ /**
+ * Get associated role.
+ * @return Associated role.
+ */
+ public String getRole()
+ {
+ return role;
+ }
+
+ /**
+ * Set associated role.
+ * @param role Associated role.
+ */
+ public void setRole(String role)
+ {
+ this.role = role;
+ }
+
+ /**
+ * Set the page.
+ * @param page Page.
+ */
+ public void setPage(String page)
+ {
+ this.page = page;
+ }
+
+ /**
+ * Get the page.
+ * @return Page.
+ */
+ public String getPage()
+ {
+ return page;
+ }
+
+ /**
+ * Get the template.
+ * Same as getPage().
+ * @return Template.
+ */
+ public String getTemplate()
+ {
+ return page;
+ }
+
+ /**
+ * Set the template.
+ * Same as setPage().
+ * @param template Template.
+ */
+ public void setTemplate(String template)
+ {
+ this.page = template;
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/GetAttributeTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/GetAttributeTag.java
new file mode 100644
index 0000000..5644cc8
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/GetAttributeTag.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.tiles.ComponentContext;
+
+ /**
+ * Retrieve the value of the specified component/template attribute property,
+ * and render it to the current JspWriter as a String.
+ * The usual toString() conversion is applied on the found value.
+ */
+public class GetAttributeTag extends TagSupport implements ComponentConstants {
+
+ private String attribute = null;
+ /** Role attribute */
+ private String role = null;
+ /**
+ * Do we ignore error if attribute is not found.
+ * Default value is <code>false</code>, which will throw an exception.
+ */
+ private boolean isErrorIgnored = false;
+
+ /**
+ * Default constructor.
+ */
+ public GetAttributeTag() {
+ super();
+ }
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+
+ super.release();
+ attribute = null;
+ role = null;
+ isErrorIgnored = false;
+ }
+
+ /**
+ * Set attribute.
+ * @param attribute Attribute.
+ */
+ public void setAttribute(String attribute){
+ this.attribute = attribute;
+ }
+
+ /**
+ * Get attribute.
+ * @return Attribute.
+ */
+ public String getAttribute()
+ {
+ return attribute;
+ }
+
+ /**
+ * Set Name.
+ * Same as setAttribute().
+ * @param value Attribute.
+ */
+ public void setName(String value)
+ {
+ this.attribute = value;
+ }
+
+ /**
+ * Get Name.
+ * Set as getAttribute().
+ * @return Attribute.
+ */
+ public String getName()
+ {
+ return attribute;
+ }
+
+ /**
+ * Set ignoring flag when attribute is not found.
+ * @param ignore default: <code>false</code>: Exception is thrown when attribute is not found, set to <code>
+ * true</code> to ignore missing attributes silently
+ */
+ public void setIgnore(boolean ignore)
+ {
+ this.isErrorIgnored = ignore;
+ }
+
+ /**
+ * Get ignore flag.
+ * @return <code>false</code>: Exception is thrown when attribute is not found, set to <code>
+ * true</code> to ignore missing attributes silently
+ */
+ public boolean getIgnore()
+ {
+ return isErrorIgnored;
+ }
+
+ /**
+ * Set role.
+ * @param role The role the user must be in to store content.
+ */
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ /**
+ * Get role.
+ * @return Role.
+ */
+ public String getRole()
+ {
+ return role;
+ }
+
+ /**
+ * Close tag.
+ * @throws JspException On error processing tag.
+ */
+ public int doEndTag() throws JspException {
+
+ // Check role
+ if(role != null && !((HttpServletRequest)pageContext.getRequest()).isUserInRole(role) )
+ {
+ return EVAL_PAGE;
+ } // end if
+
+ // Get context
+ ComponentContext compContext = (ComponentContext)pageContext.getAttribute( ComponentConstants.COMPONENT_CONTEXT, PageContext.REQUEST_SCOPE);
+
+ if( compContext == null )
+ throw new JspException ( "Error - tag.getAsString : component context is not defined. Check tag syntax" );
+
+ Object value = compContext.getAttribute(attribute);
+ if( value == null)
+ { // no value : throw error or fail silently according to ignore
+ if(isErrorIgnored == false )
+ throw new JspException ( "Error - tag.getAsString : attribute '"+ attribute + "' not found in context. Check tag syntax" );
+ else
+ return EVAL_PAGE;
+ } // end if
+
+
+ try
+ {
+ pageContext.getOut().print( value );
+ }
+ catch( IOException ex )
+ {
+ ex.printStackTrace();
+ throw new JspException ( "Error - tag.getProperty : IOException ");
+ }
+
+ return EVAL_PAGE;
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/GetTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/GetTag.java
new file mode 100644
index 0000000..5ea64cc
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/GetTag.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+/**
+ * This is the tag handler for <tiles:get>, which gets
+ * content from the request scope and either includes the content or prints
+ * it, depending upon the value of the content's <code>direct</code> attribute.
+ *
+ * This tag is intended to be compatible with the same tag from Templates (David Geary).
+ * Implementation extends InsertTag for facility (no so well).
+ * The only difference is the default value of attribute 'ignore', which is <code>true</code>
+ * for this tag (default behavior of David Geary's templates).
+ *
+ * @author David Geary
+ * @author Cedric Dumoulin
+ */
+public class GetTag extends InsertTag {
+
+
+ /**
+ * Constructor.
+ * Set default value for 'isErrorIgnored' to <code>true</code>.
+ */
+ public GetTag() {
+ isErrorIgnored = true;
+ }
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+
+ super.release();
+ isErrorIgnored = true;
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/ImportAttributeTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/ImportAttributeTag.java
new file mode 100644
index 0000000..eaed2d9
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/ImportAttributeTag.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import java.util.Iterator;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.taglib.tiles.util.TagUtils;
+import org.apache.tiles.ComponentContext;
+
+
+/**
+ * Import attribute from component to requested scope.
+ * Attribute name and scope are optional. If not specified, all component
+ * attributes are imported in page scope.
+ */
+
+public final class ImportAttributeTag extends TagSupport {
+
+ /**
+ * Class name of object.
+ */
+ private String name = null;
+
+
+ /**
+ * The scope name.
+ */
+ private String scopeName = null;
+
+ /**
+ * The scope value.
+ */
+ private int scope = PageContext.PAGE_SCOPE;
+ /**
+ * Are errors ignored. This is the property for attribute <code>ignore</code>.
+ * Default value is <code>false</code>, which throws an exception.
+ * Only "attribute not found" - errors are ignored.
+ */
+ protected boolean isErrorIgnored = false;
+
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+
+ super.release();
+ name = null;
+ scopeName = null;
+ scope = PageContext.PAGE_SCOPE;
+ isErrorIgnored = false;
+ }
+
+ /**
+ * Get the name.
+ * @return Name.
+ */
+ public String getName()
+ {
+ return (this.name);
+ }
+
+
+ /**
+ * Set the name.
+ * @param name The new name
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * Set the scope.
+ * @param scope Scope.
+ */
+ public void setScope(String scope)
+ {
+ this.scopeName = scope;
+ }
+
+ /**
+ * Get scope.
+ * @return Scope.
+ */
+ public String getScope()
+ {
+ return scopeName;
+ }
+
+ /**
+ * Set ignore flag.
+ * @param ignore default: <code>false</code>: Exception is thrown when attribute is not found, set to <code>
+ * true</code> to ignore missing attributes silently
+ */
+ public void setIgnore(boolean ignore)
+ {
+ this.isErrorIgnored = ignore;
+ }
+
+ /**
+ * Get ignore flag.
+ * @return default: <code>false</code>: Exception is thrown when attribute is not found, set to <code>
+ * true</code> to ignore missing attributes silently
+ */
+ public boolean getIgnore()
+ {
+ return isErrorIgnored;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Expose the requested property from component context.
+ *
+ * @exception JspException On errors processing tag.
+ */
+ public int doStartTag() throws JspException
+ {
+ // retrieve component context
+ ComponentContext compContext = (ComponentContext)pageContext.getAttribute( ComponentConstants.COMPONENT_CONTEXT, PageContext.REQUEST_SCOPE);
+ if( compContext == null )
+ throw new JspException ( "Error - tag importAttribute : no tiles context found." );
+
+ // set scope
+ scope = TagUtils.getScope( scopeName, PageContext.PAGE_SCOPE );
+
+ // push attribute in requested context.
+ if( name != null )
+ {
+ Object value = compContext.getAttribute(name);
+ // Check if value exist and if we must send a runtime exception
+ if( value == null )
+ if(!isErrorIgnored)
+ throw new JspException ( "Error - tag importAttribute : property '"+ name + "' not found in context. Check tag syntax" );
+ else
+ return SKIP_BODY;
+
+ pageContext.setAttribute(name, value, scope);
+ }
+ else
+ { // set all attributes
+ Iterator names = compContext.getAttributeNames();
+ while(names.hasNext())
+ {
+ String name = (String)names.next();
+ pageContext.setAttribute(name, compContext.getAttribute(name), scope);
+ } // end loop
+ } // end if
+
+ // Continue processing this page
+ return SKIP_BODY;
+ }
+
+
+
+
+ /**
+ * Clean up after processing this enumeration.
+ *
+ * @exception JspException On errors processing tag.
+ */
+ public int doEndTag() throws JspException
+ {
+ return (EVAL_PAGE);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/InitDefinitionsTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/InitDefinitionsTag.java
new file mode 100644
index 0000000..035cf61
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/InitDefinitionsTag.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.tiles.DefinitionsFactory;
+import org.apache.tiles.DefinitionsFactoryConfig;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.TilesUtil;
+
+ /**
+ * Init definitions factory.
+ */
+public class InitDefinitionsTag extends TagSupport implements ComponentConstants {
+
+
+ private String filename = null;
+ private String classname = null;
+
+ /**
+ * Default constructor.
+ */
+ public InitDefinitionsTag() {
+ super();
+ }
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+
+ super.release();
+ filename = null;
+ }
+
+ /**
+ * Set file.
+ */
+ public void setFile(String name){
+ this.filename = name;
+ }
+
+ /**
+ * Set classname.
+ */
+ public void setClassname(String classname){
+ this.classname = classname;
+ }
+
+ /**
+ * Do start tag.
+ */
+ public int doStartTag() throws JspException
+ {
+ DefinitionsFactory factory = TilesUtil.getDefinitionsFactory(pageContext.getRequest(),pageContext.getServletContext());
+ if(factory != null )
+ return SKIP_BODY;
+
+ DefinitionsFactoryConfig factoryConfig = new DefinitionsFactoryConfig();
+ factoryConfig.setFactoryClassname( classname );
+ factoryConfig.setDefinitionConfigFiles( filename );
+
+ try
+ {
+ factory = TilesUtil.createDefinitionsFactory(pageContext.getServletContext(), factoryConfig);
+ }
+ catch( DefinitionsFactoryException ex )
+ {
+ ex.printStackTrace();
+ throw new JspException( ex.getMessage() + " See console for details" );
+ }
+ return SKIP_BODY;
+ }
+
+ /**
+ * Do end tag.
+ */
+ public int doEndTag() throws JspException {
+ return EVAL_PAGE;
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/InsertTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/InsertTag.java
new file mode 100644
index 0000000..f440ef6
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/InsertTag.java
@@ -0,0 +1,1031 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tiles.Globals;
+import org.apache.taglib.tiles.util.TagUtils;
+import org.apache.tiles.AttributeDefinition;
+import org.apache.tiles.ComponentContext;
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.Controller;
+import org.apache.tiles.DefinitionAttribute;
+import org.apache.tiles.DefinitionNameAttribute;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.DirectStringAttribute;
+import org.apache.tiles.FactoryNotFoundException;
+import org.apache.tiles.NoSuchDefinitionException;
+import org.apache.tiles.TilesUtil;
+
+/**
+ * This is the tag handler for <tiles:insert>, which includes
+ * a template. The tag's body content consists of <tiles:put>
+ * tags, which are accessed by <tiles:get> in the template.
+ *
+ * @author David Geary
+ * @author Cedric Dumoulin
+ * @version $Revision: 1.20 $ $Date: 2003/07/07 23:40:12 $
+ */
+public class InsertTag
+ extends DefinitionTagSupport
+ implements PutTagParent, ComponentConstants, PutListTagParent {
+
+ /**
+ * The role delimiter.
+ * @deprecated This will be removed in a release after Struts 1.2.
+ */
+ public static final String ROLE_DELIMITER = ",";
+
+ /**
+ * Commons Logging instance.
+ */
+ protected static Log log = LogFactory.getLog(InsertTag.class);
+
+ /* JSP Tag attributes */
+
+ /**
+ * Flush attribute value.
+ */
+ protected boolean flush = true;
+
+ /**
+ * Name to insert.
+ */
+ protected String name = null;
+
+ /**
+ * Name of attribute from which to read page name to include.
+ */
+ protected String attribute = null;
+
+ /**
+ * Name of bean used as entity to include.
+ */
+ protected String beanName = null;
+
+ /**
+ * Name of bean property, if any.
+ */
+ protected String beanProperty = null;
+
+ /**
+ * Scope of bean, if any.
+ */
+ protected String beanScope = null;
+
+ /**
+ * Are errors ignored. This is the property for attribute 'ignore'.
+ * Default value is false, which throw an exception.
+ * Only 'attribute not found' errors are ignored.
+ */
+ protected boolean isErrorIgnored = false;
+
+ /**
+ * Name of component instance to include.
+ */
+ protected String definitionName = null;
+
+ /* Internal properties */
+ /**
+ * Does the end tag need to be processed.
+ * Default value is true. Boolean set in case of ignored errors.
+ */
+ protected boolean processEndTag = true;
+
+ /**
+ * Current component context.
+ */
+ protected ComponentContext cachedCurrentContext;
+
+ /**
+ * Final handler of tag methods.
+ */
+ protected TagHandler tagHandler = null;
+
+ /**
+ * Trick to allows inner classes to access pageContext.
+ */
+ protected PageContext pageContext = null;
+
+ /**
+ * Reset member values for reuse. This method calls super.release(),
+ * which invokes TagSupport.release(), which typically does nothing.
+ */
+ public void release() {
+
+ super.release();
+ attribute = null;
+ beanName = null;
+ beanProperty = null;
+ beanScope = null;
+
+ definitionName = null;
+ flush = true;
+ name = null;
+ page = null;
+ role = null;
+ isErrorIgnored = false;
+
+ releaseInternal();
+ }
+
+ /**
+ * Reset internal member values for reuse.
+ */
+ protected void releaseInternal() {
+ cachedCurrentContext = null;
+ processEndTag = true;
+ // pageContext = null; // orion doesn't set it between two tags
+ tagHandler = null;
+ }
+
+ /**
+ * Set the current page context.
+ * Called by the page implementation prior to doStartTag().
+ * <p>
+ * Needed to allow inner classes to access pageContext.
+ */
+ public void setPageContext(PageContext pc) {
+ this.pageContext = pc;
+ super.setPageContext(pc);
+ }
+
+ /**
+ * Get the pageContext property.
+ */
+ public PageContext getPageContext() {
+ return pageContext;
+ }
+
+ /**
+ * Set name.
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ /**
+ * Get name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set component.
+ */
+ public void setComponent(String name) {
+ this.page = name;
+ }
+
+ /**
+ * Set definition.
+ */
+ public void setDefinition(String name) {
+ this.definitionName = name;
+ }
+
+ /**
+ * Get definition name.
+ */
+ public String getDefinitionName() {
+ return definitionName;
+ }
+
+ /**
+ * Set attribute.
+ */
+ public void setAttribute(String value) {
+ this.attribute = value;
+ }
+
+ /**
+ * Set bean name.
+ */
+ public void setBeanName(String value) {
+ this.beanName = value;
+ }
+
+ /**
+ * Get bean name.
+ */
+ public String getBeanName() {
+ return beanName;
+ }
+
+ /**
+ * Set bean property.
+ */
+ public void setBeanProperty(String value) {
+ this.beanProperty = value;
+ }
+
+ /**
+ * Get bean property.
+ */
+ public String getBeanProperty() {
+ return beanProperty;
+ }
+
+ /**
+ * Set bean scope.
+ */
+ public void setBeanScope(String value) {
+ this.beanScope = value;
+ }
+
+ /**
+ * Get bean scope.
+ */
+ public String getBeanScope() {
+ return beanScope;
+ }
+
+ /**
+ * Set flush.
+ */
+ public void setFlush(boolean flush) {
+ this.flush = flush;
+ }
+
+ /**
+ * Get flush.
+ */
+ public boolean getFlush() {
+ return flush;
+ }
+
+ /**
+ * Set flush.
+ * Method added for compatibility with JSP1.1
+ */
+ public void setFlush(String flush) {
+ this.flush = (Boolean.valueOf(flush).booleanValue());
+ }
+
+ /**
+ * Set ignore.
+ */
+ public void setIgnore(boolean ignore) {
+ this.isErrorIgnored = ignore;
+ }
+
+ /**
+ * Get ignore.
+ */
+ public boolean getIgnore() {
+ return isErrorIgnored;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Add a body attribute.
+ * Erase any attribute with same name previously set.
+ */
+ public void putAttribute(String name, Object value) {
+ tagHandler.putAttribute(name, value);
+ }
+
+ /**
+ * Process nested ≶put> tag.
+ * Method calls by nested ≶put> tags.
+ * Nested list is added to current list.
+ * If role is defined, it is checked immediately.
+ */
+ public void processNestedTag(PutTag nestedTag) throws JspException {
+ // Check role
+ HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
+ String role = nestedTag.getRole();
+ if (role != null && !request.isUserInRole(role)) {
+ // not allowed : skip attribute
+ return;
+ }
+
+ putAttribute(nestedTag.getName(), nestedTag.getRealValue());
+ }
+
+ /**
+ * Process nested ≶putList> tag.
+ * Method calls by nested ≶putList> tags.
+ * Nested list is added to sub-component attributes
+ * If role is defined, it is checked immediately.
+ */
+ public void processNestedTag(PutListTag nestedTag) throws JspException {
+ // Check role
+ HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
+ String role = nestedTag.getRole();
+ if (role != null && !request.isUserInRole(role)) {
+ // not allowed : skip attribute
+ return;
+ }
+
+ // Check if a name is defined
+ if (nestedTag.getName() == null) {
+ throw new JspException("Error - PutList : attribute name is not defined. It is mandatory as the list is added as attribute of 'insert'.");
+ }
+
+ // now add attribute to enclosing parent (i.e. : this object).
+ putAttribute(nestedTag.getName(), nestedTag.getList());
+ }
+
+ /**
+ * Method calls by nested ≶putList> tags.
+ * A new list is added to current insert object.
+ */
+ public void putAttribute(PutListTag nestedTag) throws JspException {
+ // Check role
+ HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
+ String role = nestedTag.getRole();
+ if (role != null && !request.isUserInRole(role)) {
+ // not allowed : skip attribute
+ return;
+ }
+
+ putAttribute(nestedTag.getName(), nestedTag.getList());
+ }
+
+ /**
+ * Get current component context.
+ */
+ private ComponentContext getCurrentContext() {
+ if (cachedCurrentContext == null) {
+ cachedCurrentContext =
+ (ComponentContext) pageContext.getAttribute(
+ ComponentConstants.COMPONENT_CONTEXT,
+ PageContext.REQUEST_SCOPE);
+ }
+
+ return cachedCurrentContext;
+ }
+
+ /**
+ * Get instantiated Controller.
+ * Return controller denoted by controllerType, or <code>null</code> if controllerType
+ * is null.
+ * @throws JspException If controller can't be created.
+ */
+ private Controller getController() throws JspException {
+ if (controllerType == null) {
+ return null;
+ }
+
+ try {
+ return ComponentDefinition.createController(
+ controllerName,
+ controllerType);
+
+ } catch (InstantiationException ex) {
+ throw new JspException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Process the start tag by checking tag's attributes and creating appropriate handler.
+ * Possible handlers :
+ * <ul>
+ * <li> URL
+ * <li> definition
+ * <li> direct String
+ * </ul>
+ * Handlers also contain sub-component context.
+ */
+ public int doStartTag() throws JspException {
+ // Check role immediatly to avoid useless stuff.
+ // In case of insertion of a "definition", definition's role still checked later.
+ // This lead to a double check of "role" ;-(
+ HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
+ if (role != null && !request.isUserInRole(role)) {
+ processEndTag = false;
+ return SKIP_BODY;
+ }
+
+ try {
+ tagHandler = createTagHandler();
+
+ } catch (JspException e) {
+ if (isErrorIgnored) {
+ processEndTag = false;
+ return SKIP_BODY;
+ } else {
+ throw e;
+ }
+ }
+
+ return tagHandler.doStartTag();
+ }
+
+ /**
+ * Process the end tag by including the template.
+ * Simply call the handler doEndTag
+ */
+ public int doEndTag() throws JspException {
+ if (!processEndTag) {
+ releaseInternal();
+ return EVAL_PAGE;
+ }
+
+ int res = tagHandler.doEndTag();
+ // Reset properties used by object, in order to be able to reuse object.
+ releaseInternal();
+ return res;
+ }
+
+ /**
+ * Process tag attribute and create corresponding tag handler.
+ */
+ public TagHandler createTagHandler() throws JspException {
+ // Check each tag attribute.
+ // page Url attribute must be the last checked because it can appears concurrently
+ // with others attributes.
+ if (definitionName != null) {
+ return processDefinitionName(definitionName);
+ } else if (attribute != null) {
+ return processAttribute(attribute);
+ } else if (beanName != null) {
+ return processBean(beanName, beanProperty, beanScope);
+ } else if (name != null) {
+ return processName(name);
+ } else if (page != null) {
+ return processUrl(page);
+ } else {
+ throw new JspException("Error - Tag Insert : At least one of the following attribute must be defined : template|page|attribute|definition|name|beanName. Check tag syntax");
+ }
+ }
+
+ /**
+ * Process an object retrieved as a bean or attribute.
+ * Object can be a typed attribute, a String, or anything else.
+ * If typed attribute, use associated type.
+ * Otherwise, apply toString() on object, and use returned string as a name.
+ * @throws JspException - Throws by underlying nested call to
+ * processDefinitionName()
+ */
+ public TagHandler processObjectValue(Object value) throws JspException {
+ // First, check if value is one of the Typed Attribute
+ if (value instanceof AttributeDefinition) {
+ // We have a type => return appropriate IncludeType
+ return processTypedAttribute((AttributeDefinition) value);
+
+ } else if (value instanceof ComponentDefinition) {
+ return processDefinition((ComponentDefinition) value);
+ }
+
+ // Value must denote a valid String
+ return processAsDefinitionOrURL(value.toString());
+ }
+
+ /**
+ * Process name.
+ * Search in following order :
+ * <ul>
+ * <li>Component context - if found, process it as value.</li>
+ * <li>definitions factory</li>
+ * <li>URL</li>
+ * <li></li>
+ * </ul>
+ *
+ * @return appropriate tag handler.
+ * @throws JspException - Throws by underlying nested call to
+ * processDefinitionName()
+ */
+ public TagHandler processName(String name) throws JspException {
+ Object attrValue = getCurrentContext().getAttribute(name);
+
+ if (attrValue != null) {
+ return processObjectValue(attrValue);
+ }
+
+ return processAsDefinitionOrURL(name);
+ }
+
+ /**
+ * Process the url.
+ * @throws JspException If failed to create controller
+ */
+ public TagHandler processUrl(String url) throws JspException {
+ return new InsertHandler(url, role, getController());
+ }
+
+ /**
+ * Process tag attribute "definition".
+ * First, search definition in the factory, then create handler from this definition.
+ * @param name Name of the definition.
+ * @return Appropriate TagHandler.
+ * @throws JspException- NoSuchDefinitionException No Definition found for name.
+ * @throws JspException- FactoryNotFoundException Can't find Definitions factory.
+ * @throws JspException- DefinedComponentFactoryException General error in factory.
+ * @throws JspException InstantiationException Can't create requested controller
+ */
+ protected TagHandler processDefinitionName(String name) throws JspException {
+
+ try {
+ ComponentDefinition definition =
+ TilesUtil.getDefinition(
+ name,
+ (HttpServletRequest) pageContext.getRequest(),
+ pageContext.getServletContext());
+
+ if (definition == null) { // is it possible ?
+ throw new NoSuchDefinitionException();
+ }
+
+ return processDefinition(definition);
+
+ } catch (NoSuchDefinitionException ex) {
+ throw new JspException(
+ "Error - Tag Insert : Can't get definition '"
+ + definitionName
+ + "'. Check if this name exist in definitions factory.");
+
+ } catch (FactoryNotFoundException ex) {
+ log.info("FACTORY NOT FOUND");
+ String msg = (String)pageContext.getServletContext()
+ .getAttribute(Globals.TILES_INIT_EXCEPTION);
+ throw new JspException(msg);
+
+ } catch (DefinitionsFactoryException ex) {
+ log.info("DEFINITIONS FACTORY EXCEPTION");
+ if (log.isDebugEnabled()) {
+ ex.printStackTrace();
+ }
+
+ // Save exception to be able to show it later
+ pageContext.setAttribute(
+ Globals.EXCEPTION_KEY,
+ ex,
+ PageContext.REQUEST_SCOPE);
+ throw new JspException(ex.getMessage());
+ }
+ }
+
+ /**
+ * End of Process tag attribute "definition".
+ * Overload definition with tag attributes "template" and "role".
+ * Then, create appropriate tag handler.
+ * @param definition Definition to process.
+ * @return Appropriate TagHandler.
+ * @throws JspException InstantiationException Can't create requested controller
+ */
+ protected TagHandler processDefinition(ComponentDefinition definition)
+ throws JspException {
+ // Declare local variable in order to not change Tag attribute values.
+ String role = this.role;
+ String page = this.page;
+ Controller controller = null;
+
+ try {
+ controller = definition.getOrCreateController();
+
+ // Overload definition with tag's template and role.
+ if (role == null) {
+ role = definition.getRole();
+ }
+
+ if (page == null) {
+ page = definition.getTemplate();
+ }
+
+ if (controllerName != null) {
+ controller =
+ ComponentDefinition.createController(
+ controllerName,
+ controllerType);
+ }
+
+ // Can check if page is set
+ return new InsertHandler(
+ definition.getAttributes(),
+ page,
+ role,
+ controller);
+
+ } catch (InstantiationException ex) {
+ throw new JspException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Process a bean.
+ * Get bean value, eventually using property and scope. Found value is process by processObjectValue().
+ * @param beanName Name of the bean
+ * @param beanProperty Property in the bean, or null.
+ * @param beanScope bean scope, or null.
+ * @return Appropriate TagHandler.
+ * @throws JspException - NoSuchDefinitionException No value associated to bean.
+ * @throws JspException an error occur while reading bean, or no definition found.
+ * @throws JspException - Throws by underlying nested call to processDefinitionName()
+ */
+ protected TagHandler processBean(
+ String beanName,
+ String beanProperty,
+ String beanScope)
+ throws JspException {
+
+ Object beanValue =
+ TagUtils.getRealValueFromBean(
+ beanName,
+ beanProperty,
+ beanScope,
+ pageContext);
+
+ if (beanValue == null) {
+ throw new JspException(
+ "Error - Tag Insert : No value defined for bean '"
+ + beanName
+ + "' with property '"
+ + beanProperty
+ + "' in scope '"
+ + beanScope
+ + "'.");
+ }
+
+ return processObjectValue(beanValue);
+ }
+
+ /**
+ * Process tag attribute "attribute".
+ * Get value from component attribute.
+ * Found value is process by processObjectValue().
+ * @param name Name of the attribute.
+ * @return Appropriate TagHandler.
+ * @throws JspException - NoSuchDefinitionException No Definition found for name.
+ * @throws JspException - Throws by underlying nested call to processDefinitionName()
+ */
+ public TagHandler processAttribute(String name) throws JspException {
+ Object attrValue = getCurrentContext().getAttribute(name);
+
+ if (attrValue == null) {
+ throw new JspException(
+ "Error - Tag Insert : No value found for attribute '" + name + "'.");
+ }
+
+ return processObjectValue(attrValue);
+ }
+
+ /**
+ * Try to process name as a definition, or as an URL if not found.
+ * @param name Name to process.
+ * @return appropriate TagHandler
+ * @throws JspException InstantiationException Can't create requested controller
+ */
+ public TagHandler processAsDefinitionOrURL(String name) throws JspException {
+ try {
+ ComponentDefinition definition =
+ TilesUtil.getDefinition(
+ name,
+ pageContext.getRequest(),
+ pageContext.getServletContext());
+
+ if (definition != null) {
+ return processDefinition(definition);
+ }
+
+ } catch (DefinitionsFactoryException ex) {
+ // silently failed, because we can choose to not define a factory.
+ }
+
+ // no definition found, try as url
+ return processUrl(name);
+ }
+
+ /**
+ * Process typed attribute according to its type.
+ * @param value Typed attribute to process.
+ * @return appropriate TagHandler.
+ * @throws JspException - Throws by underlying nested call to processDefinitionName()
+ */
+ public TagHandler processTypedAttribute(AttributeDefinition value)
+ throws JspException {
+ if (value instanceof DirectStringAttribute) {
+ return new DirectStringHandler((String) value.getValue());
+
+ } else if (value instanceof DefinitionAttribute) {
+ return processDefinition((ComponentDefinition) value.getValue());
+
+ } else if (value instanceof DefinitionNameAttribute) {
+ return processDefinitionName((String) value.getValue());
+ }
+
+ return new InsertHandler((String) value.getValue(), role, getController());
+ }
+
+ /**
+ * Do an include of specified page.
+ * This method is used internally to do all includes from this class. It delegates
+ * the include call to the TilesUtil.doInclude().
+ * @param page The page that will be included
+ * @throws ServletException - Thrown by call to pageContext.include()
+ * @throws IOException - Thrown by call to pageContext.include()
+ */
+ protected void doInclude(String page) throws ServletException, IOException {
+ TilesUtil.doInclude(page, pageContext);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Inner Interface.
+ * Sub handler for tag.
+ */
+ protected interface TagHandler {
+ /**
+ * Create ComponentContext for type depicted by implementation class.
+ */
+ public int doStartTag() throws JspException;
+ /**
+ * Do include for type depicted by implementation class.
+ */
+ public int doEndTag() throws JspException;
+ /**
+ * Add a component parameter (attribute) to subContext.
+ */
+ public void putAttribute(String name, Object value);
+ } // end inner interface
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Real handler, after attribute resolution.
+ * Handle include sub-component.
+ */
+ protected class InsertHandler implements TagHandler {
+ protected String page;
+ protected ComponentContext currentContext;
+ protected ComponentContext subCompContext;
+ protected String role;
+ protected Controller controller;
+
+ /**
+ * Constructor.
+ * Create insert handler using Component definition.
+ */
+ public InsertHandler(
+ Map attributes,
+ String page,
+ String role,
+ Controller controller) {
+
+ this.page = page;
+ this.role = role;
+ this.controller = controller;
+ subCompContext = new ComponentContext(attributes);
+ }
+
+ /**
+ * Constructor.
+ * Create insert handler to insert page at specified location.
+ */
+ public InsertHandler(String page, String role, Controller controller) {
+ this.page = page;
+ this.role = role;
+ this.controller = controller;
+ subCompContext = new ComponentContext();
+ }
+
+ /**
+ * Create a new empty context.
+ */
+ public int doStartTag() throws JspException {
+ // Check role
+ HttpServletRequest request =
+ (HttpServletRequest) pageContext.getRequest();
+
+ if (role != null && !request.isUserInRole(role)) {
+ return SKIP_BODY;
+ }
+
+ // save current context
+ this.currentContext = getCurrentContext();
+ return EVAL_BODY_INCLUDE;
+ }
+
+ /**
+ * Add attribute to sub context.
+ * Do nothing.
+ */
+ public void putAttribute(String name, Object value) {
+ subCompContext.putAttribute(name, value);
+ }
+
+ /**
+ * Include requested page.
+ */
+ public int doEndTag() throws JspException {
+ // Check role
+ HttpServletRequest request =
+ (HttpServletRequest) pageContext.getRequest();
+
+ if (role != null && !request.isUserInRole(role)) {
+ return EVAL_PAGE;
+ }
+
+ try {
+ if (log.isDebugEnabled()) {
+ log.debug("insert page='" + page + "'.");
+ }
+
+ // set new context for included component.
+ pageContext.setAttribute(
+ ComponentConstants.COMPONENT_CONTEXT,
+ subCompContext,
+ PageContext.REQUEST_SCOPE);
+
+ // Call controller if any
+ if (controller != null) {
+ controller.perform(
+ subCompContext,
+ (HttpServletRequest) pageContext.getRequest(),
+ (HttpServletResponse) pageContext.getResponse(),
+ pageContext.getServletContext());
+ }
+
+ // include requested component.
+ //if (flush) {
+ // pageContext.getOut().flush();
+ //}
+
+ System.out.println("INCLUDING " + page);
+ doInclude(page);
+
+ } catch (IOException e) {
+ String msg = "Can't insert page '" + page + "' : " + e.getMessage();
+ log.error(msg, e);
+ throw new JspException(msg);
+
+ } catch (IllegalArgumentException e) {
+ // Can't resolve page uri, should we ignore it?
+ if (!(page == null && isErrorIgnored)) {
+ String msg =
+ "Can't insert page '"
+ + page
+ + "'. Check if it exists.\n"
+ + e.getMessage();
+
+ log.error(msg, e);
+ throw new JspException(msg);
+ }
+
+ } catch (ServletException e) {
+ Throwable cause = e;
+ if (e.getRootCause() != null) {
+ cause = e.getRootCause();
+ }
+
+ String msg =
+ "ServletException in '" + page + "': " + cause.getMessage();
+
+ log.error(msg, e);
+ throw new JspException(msg);
+
+
+ } finally {
+ // restore old context only if currentContext not null
+ // (bug with Silverstream ?; related by Arvindra Sehmi 20010712)
+ if (currentContext != null) {
+ pageContext.setAttribute(
+ ComponentConstants.COMPONENT_CONTEXT,
+ currentContext,
+ PageContext.REQUEST_SCOPE);
+ }
+ }
+
+ return EVAL_PAGE;
+ }
+
+ /**
+ * Process an exception.
+ * Depending of debug attribute, print full exception trace or only
+ * its message in output page.
+ * @param ex Exception
+ * @param msg An additional message to show in console and to propagate if we can't output exception.
+ * @deprecated This method will be removed in a release after Struts 1.2.
+ */
+ protected void processException(Throwable ex, String msg)
+ throws JspException {
+
+ try {
+ if (msg == null) {
+ msg = ex.getMessage();
+ }
+
+ if (log.isDebugEnabled()) { // show full trace
+ log.debug(msg, ex);
+ pageContext.getOut().println(msg);
+ ex.printStackTrace(new PrintWriter(pageContext.getOut(), true));
+ } else { // show only message
+ pageContext.getOut().println(msg);
+ }
+
+ } catch (IOException ioex) { // problems. Propagate original exception
+ pageContext.setAttribute(
+ ComponentConstants.EXCEPTION_KEY,
+ ex,
+ PageContext.REQUEST_SCOPE);
+ throw new JspException(msg);
+ }
+ }
+ }
+
+ /**
+ * Parse the list of roles and return <code>true</code> or <code>false</code> based on whether
+ * the user has that role or not.
+ * @param role Comma-delimited list of roles.
+ * @param request The request.
+ */
+ static public boolean userHasRole(HttpServletRequest request, String role) {
+ StringTokenizer st = new StringTokenizer(role, ",");
+ while (st.hasMoreTokens()) {
+ if (request.isUserInRole(st.nextToken())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Handle insert direct string.
+ */
+ protected class DirectStringHandler implements TagHandler {
+ /** Object to print as a direct string */
+ private Object value;
+
+ /**
+ * Constructor.
+ */
+ public DirectStringHandler(Object value) {
+ this.value = value;
+ }
+
+ /**
+ * Do nothing, there is no context for a direct string.
+ */
+ public int doStartTag() throws JspException {
+ return SKIP_BODY;
+ }
+
+ /**
+ * Add attribute to sub context.
+ * Do nothing.
+ */
+ public void putAttribute(String name, Object value) {
+ }
+
+ /**
+ * Print String in page output stream.
+ */
+ public int doEndTag() throws JspException {
+ try {
+ if (flush) {
+ pageContext.getOut().flush();
+ }
+
+ pageContext.getOut().print(value);
+
+ } catch (IOException ex) {
+ if (log.isDebugEnabled()) {
+ log.debug("Can't write string '" + value + "' : ", ex);
+ }
+
+ pageContext.setAttribute(
+ ComponentConstants.EXCEPTION_KEY,
+ ex,
+ PageContext.REQUEST_SCOPE);
+
+ throw new JspException(
+ "Can't write string '" + value + "' : " + ex.getMessage());
+ }
+
+ return EVAL_PAGE;
+ }
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutListTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutListTag.java
new file mode 100644
index 0000000..67fcdf8
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutListTag.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.tiles.AttributeDefinition;
+import org.apache.tiles.UntypedAttribute;
+
+/**
+ * PutList tag implementation.
+ */
+public class PutListTag
+ extends TagSupport
+ implements ComponentConstants, AddTagParent, PutListTagParent {
+
+ /**
+ * Name of this attribute.
+ */
+ private String attributeName = null;
+
+ /**
+ * The list itself.
+ */
+ private List list = null;
+
+ /**
+ * Role attribute.
+ */
+ private String role = null;
+
+ /**
+ * Default constructor.
+ */
+ public PutListTag() {
+ super();
+ }
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+ super.release();
+ attributeName = null;
+ role = null;
+ }
+
+ /**
+ * Release all internal resources.
+ */
+ protected void releaseInternal() {
+ list = null;
+ }
+
+ /**
+ * Set property.
+ */
+ public void setName(String name) {
+ this.attributeName = name;
+ }
+
+ /**
+ * Get property.
+ */
+ public String getName() {
+ return attributeName;
+ }
+
+ /**
+ * Set role attribute.
+ * @param role The role the user must be in to store content.
+ */
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ /**
+ * Get role attribute.
+ */
+ public String getRole() {
+ return role;
+ }
+
+ /**
+ * Get list defined in tag.
+ */
+ public List getList() {
+ return list;
+ }
+
+ /**
+ * Set property.
+ */
+ public void addElement(Object value) {
+ if (list == null) {
+ list = new ArrayList();
+ }
+
+ list.add(value);
+ }
+
+ /**
+ * Process nested ≶putList> tag.
+ * Method calls by nested ≶putList> tags.
+ * Nested list is added to current list.
+ * If role is defined, nested attribute is wrapped into an untypped definition
+ * containing attribute value and role.
+ */
+ public void processNestedTag(PutListTag nestedTag) throws JspException {
+ // Get real value and check role
+ // If role is set, add it in attribute definition if any.
+ // If no attribute definition, create untyped one, and set role.
+ Object attributeValue = nestedTag.getList();
+
+ if (nestedTag.getRole() != null) {
+ AttributeDefinition def = new UntypedAttribute(attributeValue);
+ def.setRole(nestedTag.getRole());
+ attributeValue = def;
+ }
+
+ // now add attribute to enclosing parent (i.e. : this object)
+ addElement(attributeValue);
+ }
+
+ /**
+ * Process nested ≶add> tag.
+ * Method calls by nested ≶add> tags.
+ * Nested attribute is added to current list.
+ * If role is defined, nested attribute is wrapped into an untypped definition
+ * containing attribute value and role.
+ */
+ public void processNestedTag(AddTag nestedTag) throws JspException {
+ // Get real value and check role
+ // If role is set, add it in attribute definition if any.
+ // If no attribute definition, create untyped one, and set role.
+ Object attributeValue = nestedTag.getRealValue();
+ AttributeDefinition def;
+
+ if (nestedTag.getRole() != null) {
+ try {
+ def = ((AttributeDefinition) attributeValue);
+ } catch (ClassCastException ex) {
+ def = new UntypedAttribute(attributeValue);
+ }
+ def.setRole(nestedTag.getRole());
+ attributeValue = def;
+ }
+
+ // now add attribute to enclosing parent (i.e. : this object)
+ addElement(attributeValue);
+ }
+
+ /**
+ * Do start tag.
+ */
+ public int doStartTag() throws JspException {
+ return EVAL_BODY_INCLUDE;
+ }
+
+ /**
+ * Do end tag.
+ */
+ public int doEndTag() throws JspException {
+ PutListTagParent enclosingParent = findEnclosingParent();
+ enclosingParent.processNestedTag(this);
+ // Clear list to avoid reuse
+ releaseInternal();
+ return EVAL_PAGE;
+ }
+
+ /**
+ * Find enclosing parent tag accepting this tag.
+ * @throws JspException If we can't find an appropriate enclosing tag.
+ */
+ protected PutListTagParent findEnclosingParent() throws JspException {
+ try {
+ PutListTagParent parent =
+ (PutListTagParent) findAncestorWithClass(this,
+ PutListTagParent.class);
+
+ if (parent == null) {
+ throw new JspException("Error - tag putList : enclosing tag doesn't accept 'putList' tag.");
+ }
+
+ return parent;
+
+ } catch (ClassCastException ex) {
+ throw new JspException("Error - tag putList : enclosing tag doesn't accept 'putList' tag.");
+ }
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutListTagParent.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutListTagParent.java
new file mode 100644
index 0000000..8c3a517
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutListTagParent.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+
+/**
+ * Tag classes implementing this interface can contains nested PutTag.
+ * This interface defines a method called by nested tags.
+ */
+public interface PutListTagParent {
+ /**
+ * Add an attribute to container.
+ * @param nestedTag Nested PutTag defining the attribute.
+ */
+ void processNestedTag(PutListTag nestedTag) throws JspException;
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutTag.java
new file mode 100644
index 0000000..1bdef18
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutTag.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.BodyTagSupport;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.taglib.tiles.util.TagUtils;
+import org.apache.tiles.AttributeDefinition;
+import org.apache.tiles.DefinitionNameAttribute;
+import org.apache.tiles.DirectStringAttribute;
+import org.apache.tiles.PathAttribute;
+
+/**
+ * Put an attribute in enclosing attribute container tag.
+ * Enclosing attribute container tag can be : <insert> or <definition>.
+ * Exception is thrown if no appropriate tag can be found.
+ * Put tag can have following atributes :
+ * <li>
+ * <ul>name : Name of the attribute</ul>
+ * <ul>value | content : value to put as attribute</ul>
+ * <ul>type : value type. Only valid if value is a String and is set by
+ * value="something" or by a bean.
+ * Possible type are : string (value is used as direct string),
+ * page | template (value is used as a page url to insert),
+ * definition (value is used as a definition name to insert)</ul>
+ * <ul>direct : Specify if value is to be used as a direct string or as a
+ * page url to insert. This is another way to specify the type. It only apply
+ * if value is set as a string, and type is not present.</ul>
+ * <ul>beanName : Name of a bean used for setting value. Only valid if value is not set.
+ * If property is specified, value come from bean's property. Otherwise, bean
+ * itself is used for value.</ul>
+ * <ul>beanProperty : Name of the property used for retrieving value.</ul>
+ * <ul>beanScope : Scope containing bean. </ul>
+ * <ul>role : Role to check when 'insert' will be called. If enclosing tag is
+ * <insert>, role is checked immediately. If enclosing tag is
+ * <definition>, role will be checked when this definition will be
+ * inserted.</ul>
+ * </li>
+ * Value can also come from tag body. Tag body is taken into account only if
+ * value is not set by one of the tag attributes. In this case Attribute type is
+ * "string", unless tag body define another type.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ */
+public class PutTag extends BodyTagSupport implements ComponentConstants {
+
+ /* JSP Tag attributes */
+
+ /**
+ * Name of attribute to put in component context.
+ */
+ protected String attributeName = null;
+
+ /**
+ * Associated attribute value.
+ */
+ private Object value = null;
+
+ /**
+ * JSP Template compatibility.
+ */
+ private String direct = null;
+
+ /**
+ * Requested type for the value.
+ */
+ private String valueType = null;
+
+ /**
+ * Bean name attribute.
+ */
+ private String beanName = null;
+
+ /**
+ * Bean property attribute.
+ */
+ private String beanProperty = null;
+
+ /**
+ * Bean scope attribute.
+ */
+ private String beanScope = null;
+
+ /**
+ * Role attribute.
+ */
+ private String role = null;
+
+ /* Internal properties */
+
+ /**
+ * Cached real value computed from tag attributes.
+ */
+ protected Object realValue = null;
+
+ /**
+ * Default constructor.
+ */
+ public PutTag() {
+ super();
+ }
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+
+ super.release();
+
+ attributeName = null;
+ valueType = null;
+ direct = null;
+ value = null;
+ beanName = null;
+ beanProperty = null;
+ beanScope = null;
+ role = null;
+ }
+
+ /**
+ * Release internal properties.
+ */
+ protected void releaseInternal() {
+ realValue = null;
+ }
+
+ /**
+ * Set name.
+ */
+ public void setName(String value) {
+ this.attributeName = value;
+ }
+
+ /**
+ * Get name.
+ */
+ public String getName() {
+ return attributeName;
+ }
+
+ /**
+ * Set value.
+ * Method added to satisfy Tomcat (bug ?).
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Get value.
+ * Method added to satisfy Tomcat (bug ?).
+ */
+ public String getValue() {
+ return (String) this.value;
+ }
+
+ /**
+ * Set value.
+ */
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ /**
+ * Set property value as an object.
+ * Added because some web containers react badly to value as <code>Object</code>.
+ */
+ public void setObjectValue(Object value) {
+ this.value = value;
+ }
+
+ /**
+ * Set content.
+ * Method added to satisfy Tomcat (bug ?).
+ */
+ public void setContent(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Get content.
+ * Method added to satisfy Tomcat (bug ?).
+ */
+ public String getContent() {
+ return (String) value;
+ }
+
+ /**
+ * Set content.
+ */
+ public void setContent(Object value) {
+ this.value = value;
+ }
+
+ /**
+ * Set direct.
+ * Method added for compatibility with JSP1.1.
+ */
+ public void setDirect(String isDirect) {
+ this.direct = isDirect;
+ }
+
+ /**
+ * Set type.
+ */
+ public void setType(String value) {
+ this.valueType = value;
+ }
+
+ /**
+ * Get type.
+ */
+ public String getType() {
+ return this.valueType;
+ }
+
+ /**
+ * Set bean name.
+ */
+ public void setBeanName(String value) {
+ this.beanName = value;
+ }
+
+ /**
+ * Get bean name.
+ */
+ public String getBeanName() {
+ return beanName;
+ }
+
+ /**
+ * Set bean property.
+ */
+ public void setBeanProperty(String value) {
+ this.beanProperty = value;
+ }
+
+ /**
+ * Get bean property.
+ */
+ public String getBeanProperty() {
+ return beanProperty;
+ }
+
+ /**
+ * Set bean scope.
+ */
+ public void setBeanScope(String value) {
+ this.beanScope = value;
+ }
+
+ /**
+ * Get bean scope.
+ */
+ public String getBeanScope() {
+ return beanScope;
+ }
+
+ /**
+ * Set role attribute.
+ * @param role The role the user must be in to store content.
+ */
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ /**
+ * Get role attribute
+ * @return The role defined in the tag or <code>null</code>.
+ */
+ public String getRole() {
+ return role;
+ }
+
+ /**
+ * Get real value according to tag attribute.
+ * Real value is the value computed after attribute processing.
+ * @return Real value.
+ * @throws JspException If something goes wrong while getting value from bean.
+ */
+ public Object getRealValue() throws JspException {
+ if (realValue == null) {
+ computeRealValue();
+ }
+
+ return realValue;
+ }
+
+ /**
+ * Compute real value according to tag attributes.
+ * @throws JspException If something goes wrong while getting value from bean.
+ */
+ protected void computeRealValue() throws JspException {
+ // Compute real value from attributes set.
+ realValue = value;
+
+ // If realValue is not set, value must come from body
+ if (value == null && beanName == null) {
+ // Test body content in case of empty body.
+ if (bodyContent != null) {
+ realValue = bodyContent.getString();
+ } else {
+ realValue = "";
+ }
+ }
+
+ // Does value comes from a bean ?
+ if (realValue == null && beanName != null) {
+ getRealValueFromBean();
+ return;
+ }
+
+ // Is there a type set ?
+ // First check direct attribute, and translate it to a valueType.
+ // Then, evaluate valueType, and create requested typed attribute.
+ // If valueType is not set, use the value "as is".
+ if (valueType == null && direct != null) {
+ if (Boolean.valueOf(direct).booleanValue() == true) {
+ valueType = "string";
+ } else {
+ valueType = "path";
+ }
+ }
+
+ if (realValue != null
+ && valueType != null
+ && !(value instanceof AttributeDefinition)) {
+
+ String strValue = realValue.toString();
+ if (valueType.equalsIgnoreCase("string")) {
+ realValue = new DirectStringAttribute(strValue);
+
+ } else if (valueType.equalsIgnoreCase("page")) {
+ realValue = new PathAttribute(strValue);
+
+ } else if (valueType.equalsIgnoreCase("template")) {
+ realValue = new PathAttribute(strValue);
+
+ } else if (valueType.equalsIgnoreCase("instance")) {
+ realValue = new DefinitionNameAttribute(strValue);
+
+ } else if (valueType.equalsIgnoreCase("definition")) {
+ realValue = new DefinitionNameAttribute(strValue);
+
+ } else { // bad type
+ throw new JspException(
+ "Warning - Tag put : Bad type '" + valueType + "'.");
+ }
+ }
+
+ }
+
+ /**
+ * Extract real value from specified bean.
+ * @throws JspException If something goes wrong while getting value from bean.
+ */
+ protected void getRealValueFromBean() throws JspException {
+ try {
+ Object bean = TagUtils.retrieveBean(beanName, beanScope, pageContext);
+ if (bean != null && beanProperty != null) {
+ realValue = PropertyUtils.getProperty(bean, beanProperty);
+ } else {
+ realValue = bean; // value can be null
+ }
+
+ } catch (NoSuchMethodException ex) {
+ throw new JspException(
+ "Error - component.PutAttributeTag : Error while retrieving value from bean '"
+ + beanName
+ + "' with property '"
+ + beanProperty
+ + "' in scope '"
+ + beanScope
+ + "'. (exception : "
+ + ex.getMessage());
+
+ } catch (InvocationTargetException ex) {
+ throw new JspException(
+ "Error - component.PutAttributeTag : Error while retrieving value from bean '"
+ + beanName
+ + "' with property '"
+ + beanProperty
+ + "' in scope '"
+ + beanScope
+ + "'. (exception : "
+ + ex.getMessage());
+
+ } catch (IllegalAccessException ex) {
+ throw new JspException(
+ "Error - component.PutAttributeTag : Error while retrieving value from bean '"
+ + beanName
+ + "' with property '"
+ + beanProperty
+ + "' in scope '"
+ + beanScope
+ + "'. (exception : "
+ + ex.getMessage());
+ }
+ }
+
+ /**
+ * Do start tag.
+ */
+ public int doStartTag() throws JspException {
+ // Do we need to evaluate body ?
+ if (value == null && beanName == null) {
+ return EVAL_BODY_TAG;
+ }
+
+ // Value is set, don't evaluate body.
+ return SKIP_BODY;
+ }
+
+ /**
+ * Do end tag.
+ */
+ public int doEndTag() throws JspException {
+ // Call parent tag which in turn does what it want
+ callParent();
+
+ // clean up tag handler for reuse.
+ releaseInternal();
+
+ return EVAL_PAGE;
+ }
+
+ /**
+ * Find parent tag which must implement AttributeContainer.
+ * @throws JspException If we can't find an appropriate enclosing tag.
+ */
+ protected void callParent() throws JspException {
+ // Get enclosing parent
+ PutTagParent enclosingParent = findEnclosingPutTagParent();
+ enclosingParent.processNestedTag(this);
+ }
+
+ /**
+ * Find parent tag which must implement AttributeContainer.
+ * @throws JspException If we can't find an appropriate enclosing tag.
+ */
+ protected PutTagParent findEnclosingPutTagParent() throws JspException {
+ try {
+ PutTagParent parent =
+ (PutTagParent) findAncestorWithClass(this, PutTagParent.class);
+
+ if (parent == null) {
+ throw new JspException("Error - tag put : enclosing tag doesn't accept 'put' tag.");
+ }
+
+ return parent;
+
+ } catch (ClassCastException ex) {
+ throw new JspException("Error - tag put : enclosing tag doesn't accept 'put' tag.");
+ }
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutTagParent.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutTagParent.java
new file mode 100644
index 0000000..0a249bf
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/PutTagParent.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+
+/**
+ * Tag classes implementing this interface can contain nested PutTag.
+ * This interface defines a method called by nested tags.
+ */
+public interface PutTagParent {
+ /**
+ * Process the nested tag.
+ * @param nestedTag Nested tag to process.
+ */
+ void processNestedTag(PutTag nestedTag ) throws JspException;
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/UseAttributeTag.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/UseAttributeTag.java
new file mode 100644
index 0000000..715ec39
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/UseAttributeTag.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.taglib.tiles.util.TagUtils;
+import org.apache.tiles.ComponentContext;
+
+
+/**
+ * Custom tag exposing a component attribute to page.
+ *
+ */
+public final class UseAttributeTag extends TagSupport {
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * Class name of object.
+ */
+ private String classname = null;
+
+
+ /**
+ * The scope name.
+ */
+ private String scopeName = null;
+
+ /**
+ * The scope value.
+ */
+ private int scope = PageContext.PAGE_SCOPE;
+
+
+
+ /**
+ * The attribute name to be exposed.
+ */
+ private String attributeName = null;
+
+ /**
+ * Are errors ignored. This is the property for attribute 'ignore'.
+ * Default value is <code>false</code>, which throws an exception.
+ * Only "attribute not found" - errors are ignored.
+ */
+ protected boolean isErrorIgnored = false;
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Release all allocated resources.
+ */
+ public void release() {
+
+ super.release();
+ attributeName = null;
+ classname = null;
+ scope = PageContext.PAGE_SCOPE;
+ scopeName = null;
+ isErrorIgnored = false;
+ // Parent doesn't clear id, so we do it
+ // bug reported by Heath Chiavettone on 18 Mar 2002
+ id = null;
+ }
+
+ /**
+ * Get class name.
+ */
+ public String getClassname() {
+
+ return (this.classname);
+
+ }
+
+
+ /**
+ * Set the class name.
+ *
+ * @param name The new class name.
+ */
+ public void setClassname(String name) {
+
+ this.classname = name;
+
+ }
+
+ /**
+ * Set name.
+ */
+ public void setName(String value){
+ this.attributeName = value;
+ }
+
+ /**
+ * Get name.
+ */
+ public String getName()
+ {
+ return attributeName;
+ }
+
+ /**
+ * Set the scope.
+ *
+ * @param scope The new scope.
+ */
+ public void setScope(String scope) {
+ this.scopeName = scope;
+ }
+
+ /**
+ * Get scope.
+ */
+ public String getScope()
+ {
+ return scopeName;
+ }
+
+ /**
+ * Set ignore.
+ */
+ public void setIgnore(boolean ignore)
+ {
+ this.isErrorIgnored = ignore;
+ }
+
+ /**
+ * Get ignore.
+ */
+ public boolean getIgnore()
+ {
+ return isErrorIgnored;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Expose the requested attribute from component context.
+ *
+ * @exception JspException if a JSP exception has occurred
+ */
+ public int doStartTag() throws JspException
+ {
+ // Do a local copy of id
+ String localId=this.id;
+ if( localId==null )
+ localId=attributeName;
+
+ ComponentContext compContext = (ComponentContext)pageContext.getAttribute( ComponentConstants.COMPONENT_CONTEXT, PageContext.REQUEST_SCOPE);
+ if( compContext == null )
+ throw new JspException ( "Error - tag useAttribute : no tiles context found." );
+
+ Object value = compContext.getAttribute(attributeName);
+ // Check if value exists and if we must send a runtime exception
+ if( value == null )
+ if(!isErrorIgnored)
+ throw new JspException ( "Error - tag useAttribute : attribute '"+ attributeName + "' not found in context. Check tag syntax" );
+ else
+ return SKIP_BODY;
+
+ if( scopeName != null )
+ {
+ scope = TagUtils.getScope( scopeName, PageContext.PAGE_SCOPE );
+ if(scope!=ComponentConstants.COMPONENT_SCOPE)
+ pageContext.setAttribute(localId, value, scope);
+ }
+ else
+ pageContext.setAttribute(localId, value);
+
+ // Continue processing this page
+ return SKIP_BODY;
+ }
+
+
+
+
+ /**
+ * Clean up after processing this enumeration.
+ *
+ * @exception JspException if a JSP exception has occurred
+ */
+ public int doEndTag() throws JspException
+ {
+ return (EVAL_PAGE);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/UseAttributeTei.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/UseAttributeTei.java
new file mode 100644
index 0000000..c80fbf0
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/UseAttributeTei.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletContext;
+
+import javax.servlet.jsp.tagext.TagData;
+import javax.servlet.jsp.tagext.TagExtraInfo;
+import javax.servlet.jsp.tagext.VariableInfo;
+
+/**
+ * Implementation of <code>TagExtraInfo</code> for the <b>UseAttribute</b>
+ * tag, identifying the scripting object(s) to be made visible.
+ *
+ */
+public final class UseAttributeTei extends TagExtraInfo {
+
+ /**
+ * Return information about the scripting variables to be created.
+ */
+ public VariableInfo[] getVariableInfo(TagData data) {
+
+ String classname = data.getAttributeString("classname");
+ if( classname == null )
+ classname = "java.lang.Object";
+ String id = data.getAttributeString("id");
+ if( id == null )
+ id = data.getAttributeString("name");
+
+ return new VariableInfo[] {
+ new VariableInfo(id,
+ classname,
+ true,
+ VariableInfo.AT_END)
+ };
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/doc-files/tilesUML.gif b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/doc-files/tilesUML.gif
new file mode 100644
index 0000000..9a8dfae
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/doc-files/tilesUML.gif
Binary files differ
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/package.html b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/package.html
new file mode 100644
index 0000000..70833d2
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/package.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <title>Package Documentation for org.apache.struts.taglib.tiles Package</title>
+</head>
+ <body bgcolor="white">
+
+
+<p>The "tiles" tag library contains tags that are useful in
+creating dynamic reusable components. </p>
+<img src="doc-files/tilesUML.gif" alt="TagLib Tiles UML">
+ </body>
+</html>
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/util/TagUtils.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/util/TagUtils.java
new file mode 100644
index 0000000..32fa006
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/taglib/tiles/util/TagUtils.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.taglib.tiles.util;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.util.MessageResources;
+import org.apache.tiles.Globals;
+import org.apache.taglib.tiles.ComponentConstants;
+import org.apache.tiles.ComponentContext;
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.FactoryNotFoundException;
+import org.apache.tiles.NoSuchDefinitionException;
+import org.apache.tiles.TilesUtil;
+
+/**
+ * Collection of utilities.
+ * This class also serves as an interface between Components and Struts. If
+ * you want to rip away Struts, simply reimplement some methods in this class.
+ * You can copy them from Struts.
+ * <p\>
+ * <i>Thanks for the tip. That's exactly what I did! (David Geary)</i>
+ *
+ * @author Cedric Dumoulin
+ * @author David Graham
+ * @author David Geary
+ */
+public class TagUtils {
+ /**
+ * The message resources for this package.
+ * TODO We need to move the relevant messages out of this properties file.
+ */
+ private static final MessageResources messages =
+ MessageResources.getMessageResources("org.apache.tiles.taglib.LocalStrings");
+
+ /**
+ * Maps lowercase JSP scope names to their PageContext integer constant
+ * values.
+ */
+ private static final Map scopes = new HashMap();
+
+ /**
+ * Initialize the scope names map and the encode variable with the
+ * Java 1.4 method if available.
+ */
+ static {
+ scopes.put("page", new Integer(PageContext.PAGE_SCOPE));
+ scopes.put("request", new Integer(PageContext.REQUEST_SCOPE));
+ scopes.put("session", new Integer(PageContext.SESSION_SCOPE));
+ scopes.put("application", new Integer(PageContext.APPLICATION_SCOPE));
+ }
+
+ /** Debug flag */
+ public static final boolean debug = true;
+
+ /**
+ * Get scope value from string value
+ * @param scopeName Scope as a String.
+ * @param defaultValue Returned default value, if not found.
+ * @return Scope as an <code>int</code>, or <code>defaultValue</code> if scope is <code>null</code>.
+ * @throws JspException Scope name is not recognized as a valid scope.
+ */
+ public static int getScope(String scopeName, int defaultValue) throws JspException {
+ if (scopeName == null) {
+ return defaultValue;
+ }
+
+ if (scopeName.equalsIgnoreCase("component")) {
+ return ComponentConstants.COMPONENT_SCOPE;
+
+ } else if (scopeName.equalsIgnoreCase("template")) {
+ return ComponentConstants.COMPONENT_SCOPE;
+
+ } else if (scopeName.equalsIgnoreCase("tile")) {
+ return ComponentConstants.COMPONENT_SCOPE;
+
+ } else {
+ return getScope(scopeName);
+ }
+ }
+
+ /**
+ * Return the value of the specified property of the specified bean,
+ * no matter which property reference format is used, with no
+ * type conversions.
+ *
+ * @param bean Bean whose property is to be extracted.
+ * @param name Possibly indexed and/or nested name of the property
+ * to be extracted.
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception
+ * @exception NoSuchMethodException if an accessor method for this
+ * propety cannot be found.
+ * @deprecated Use PropertyUtils.getProperty() directly. This will be removed
+ * after Struts 1.2.
+ */
+ public static Object getProperty(Object bean, String name)
+ throws
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchMethodException {
+
+ return PropertyUtils.getProperty(bean, name);
+ }
+
+ /**
+ * Retrieve bean from page context, using specified scope.
+ * If scope is not set, use <code>findAttribute()</code>.
+ *
+ * @param beanName Name of bean to retrieve.
+ * @param scopeName Scope or <code>null</code>. If <code>null</code>, bean is searched using
+ * findAttribute().
+ * @param pageContext Current pageContext.
+ * @return Requested bean or <code>null</code> if not found.
+ * @throws JspException Scope name is not recognized as a valid scope.
+ */
+ public static Object retrieveBean(String beanName, String scopeName, PageContext pageContext)
+ throws JspException {
+
+ if (scopeName == null) {
+ return findAttribute(beanName, pageContext);
+ }
+
+ // Default value doesn't matter because we have already check it
+ int scope = getScope(scopeName, PageContext.PAGE_SCOPE);
+
+ //return pageContext.getAttribute( beanName, scope );
+ return getAttribute(beanName, scope, pageContext);
+ }
+
+ /**
+ * Search attribute in different contexts.
+ * First, check in component context, then use pageContext.findAttribute().
+ * @param beanName Name of bean to retrieve.
+ * @param pageContext Current pageContext.
+ * @return Requested bean or <code>null</code> if not found.
+ */
+ public static Object findAttribute(String beanName, PageContext pageContext) {
+ ComponentContext compContext = ComponentContext.getContext(pageContext.getRequest());
+
+ if (compContext != null) {
+ Object attribute = compContext.findAttribute(beanName, pageContext);
+ if (attribute != null) {
+ return attribute;
+ }
+ }
+
+ // Search in pageContext scopes
+ return pageContext.findAttribute(beanName);
+ }
+
+ /**
+ * Get object from requested context. Return <code>null</code> if not found.
+ * Context can be "component" or normal JSP contexts.
+ * @param beanName Name of bean to retrieve.
+ * @param scope Scope from which bean must be retrieved.
+ * @param pageContext Current pageContext.
+ * @return Requested bean or <code>null</code> if not found.
+ */
+ public static Object getAttribute(String beanName, int scope, PageContext pageContext) {
+ if (scope == ComponentConstants.COMPONENT_SCOPE) {
+ ComponentContext compContext = ComponentContext.getContext(pageContext.getRequest());
+ return compContext.getAttribute(beanName);
+ }
+ return pageContext.getAttribute(beanName, scope);
+ }
+
+ /**
+ * Locate and return the specified property of the specified bean, from
+ * an optionally specified scope, in the specified page context.
+ *
+ * @param pageContext Page context to be searched.
+ * @param beanName Name of the bean to be retrieved.
+ * @param beanProperty Name of the property to be retrieved, or
+ * <code>null</code> to retrieve the bean itself.
+ * @param beanScope Scope to be searched (page, request, session, application)
+ * or <code>null</code> to use <code>findAttribute()</code> instead.
+ *
+ * @exception JspException Scope name is not recognized as a valid scope
+ * @exception JspException if the specified bean is not found
+ * @exception JspException if accessing this property causes an
+ * IllegalAccessException, IllegalArgumentException,
+ * InvocationTargetException, or NoSuchMethodException
+ */
+ public static Object getRealValueFromBean(
+ String beanName,
+ String beanProperty,
+ String beanScope,
+ PageContext pageContext)
+ throws JspException {
+
+ try {
+ Object realValue;
+ Object bean = retrieveBean(beanName, beanScope, pageContext);
+ if (bean != null && beanProperty != null) {
+ realValue = PropertyUtils.getProperty(bean, beanProperty);
+ } else {
+ realValue = bean; // value can be null
+ }
+ return realValue;
+
+ } catch (NoSuchMethodException ex) {
+ throw new JspException(
+ "Error - component.PutAttributeTag : Error while retrieving value from bean '"
+ + beanName
+ + "' with property '"
+ + beanProperty
+ + "' in scope '"
+ + beanScope
+ + "'. (exception : "
+ + ex.getMessage());
+
+ } catch (InvocationTargetException ex) {
+ throw new JspException(
+ "Error - component.PutAttributeTag : Error while retrieving value from bean '"
+ + beanName
+ + "' with property '"
+ + beanProperty
+ + "' in scope '"
+ + beanScope
+ + "'. (exception : "
+ + ex.getMessage());
+
+ } catch (IllegalAccessException ex) {
+ throw new JspException(
+ "Error - component.PutAttributeTag : Error while retrieving value from bean '"
+ + beanName
+ + "' with property '"
+ + beanProperty
+ + "' in scope '"
+ + beanScope
+ + "'. (exception : "
+ + ex.getMessage());
+ }
+ }
+
+ /**
+ * Store bean in requested context.
+ * If scope is <code>null</code>, save it in REQUEST_SCOPE context.
+ *
+ * @param pageContext Current pageContext.
+ * @param name Name of the bean.
+ * @param scope Scope under which bean is saved (page, request, session, application)
+ * or <code>null</code> to store in <code>request()</code> instead.
+ * @param value Bean value to store.
+ *
+ * @exception JspException Scope name is not recognized as a valid scope
+ */
+ public static void setAttribute(
+ PageContext pageContext,
+ String name,
+ Object value,
+ String scope)
+ throws JspException {
+
+ if (scope == null)
+ pageContext.setAttribute(name, value, PageContext.REQUEST_SCOPE);
+ else if (scope.equalsIgnoreCase("page"))
+ pageContext.setAttribute(name, value, PageContext.PAGE_SCOPE);
+ else if (scope.equalsIgnoreCase("request"))
+ pageContext.setAttribute(name, value, PageContext.REQUEST_SCOPE);
+ else if (scope.equalsIgnoreCase("session"))
+ pageContext.setAttribute(name, value, PageContext.SESSION_SCOPE);
+ else if (scope.equalsIgnoreCase("application"))
+ pageContext.setAttribute(name, value, PageContext.APPLICATION_SCOPE);
+ else {
+ throw new JspException("Error - bad scope name '" + scope + "'");
+ }
+ }
+
+ /**
+ * Store bean in REQUEST_SCOPE context.
+ *
+ * @param pageContext Current pageContext.
+ * @param name Name of the bean.
+ * @param beanValue Bean value to store.
+ *
+ * @exception JspException Scope name is not recognized as a valid scope
+ */
+ public static void setAttribute(PageContext pageContext, String name, Object beanValue)
+ throws JspException {
+ pageContext.setAttribute(name, beanValue, PageContext.REQUEST_SCOPE);
+ }
+
+ /**
+ * Save the specified exception as a request attribute for later use.
+ *
+ * @param pageContext The PageContext for the current page.
+ * @param exception The exception to be saved.
+ */
+ public static void saveException(PageContext pageContext, Throwable exception) {
+ pageContext.setAttribute(Globals.EXCEPTION_KEY, exception, PageContext.REQUEST_SCOPE);
+ }
+
+ /**
+ * Get component definition by its name.
+ * @param name Definition name.
+ * @param pageContext The PageContext for the current page.
+ * @throws JspException -
+ */
+ public static ComponentDefinition getComponentDefinition(String name, PageContext pageContext)
+ throws JspException {
+
+ try {
+ return TilesUtil.getDefinition(
+ name,
+ pageContext.getRequest(),
+ pageContext.getServletContext());
+
+ } catch (NoSuchDefinitionException ex) {
+ throw new JspException(
+ "Error : Can't get component definition for '"
+ + name
+ + "'. Check if this name exist in component definitions.");
+ } catch (FactoryNotFoundException ex) { // factory not found.
+ throw new JspException(ex.getMessage());
+
+ } catch (DefinitionsFactoryException ex) {
+ if (debug)
+ ex.printStackTrace();
+ // Save exception to be able to show it later
+ saveException(pageContext, ex);
+ throw new JspException(ex.getMessage());
+ }
+ }
+ /**
+ * Converts the scope name into its corresponding PageContext constant value.
+ * @param scopeName Can be "page", "request", "session", or "application" in any
+ * case.
+ * @return The constant representing the scope (ie. PageContext.REQUEST_SCOPE).
+ * @throws JspException if the scopeName is not a valid name.
+ */
+ public static int getScope(String scopeName) throws JspException {
+ Integer scope = (Integer) scopes.get(scopeName.toLowerCase());
+
+ if (scope == null) {
+ throw new JspException(messages.getMessage("lookup.scope", scope));
+ }
+
+ return scope.intValue();
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/AttributeDefinition.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/AttributeDefinition.java
new file mode 100644
index 0000000..45c040a
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/AttributeDefinition.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.Serializable;
+
+ /**
+ * Attribute definition used in a component definition.
+ *
+ */
+public interface AttributeDefinition extends Serializable
+{
+
+ /**
+ * Return value hold by this typed attribute.
+ */
+ public Object getValue();
+
+ /**
+ * Set role attribute.
+ */
+ public void setRole(String role);
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentContext.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentContext.java
new file mode 100644
index 0000000..07142a2
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentContext.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.taglib.tiles.ComponentConstants;
+
+/**
+ * Component context.
+ */
+public class ComponentContext implements Serializable {
+
+ /**
+ * Component attributes.
+ */
+ private Map attributes=null;
+
+ /**
+ * Constructor.
+ */
+ public ComponentContext() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ * Create a context and set specified attributes.
+ * @param attributes Attributes to initialize context.
+ */
+ public ComponentContext(Map attributes) {
+ if (attributes != null) {
+ this.attributes = new HashMap(attributes);
+ }
+ }
+
+ /**
+ * Add all attributes to this context.
+ * Copies all of the mappings from the specified attribute map to this context.
+ * New attribute mappings will replace any mappings that this context had for any of the keys
+ * currently in the specified attribute map.
+ * @param newAttributes Attributes to add.
+ */
+ public void addAll(Map newAttributes) {
+ if (attributes == null) {
+ attributes = new HashMap(newAttributes);
+ return;
+ }
+
+ attributes.putAll(newAttributes);
+ }
+
+ /**
+ * Add all missing attributes to this context.
+ * Copies all of the mappings from the specified attributes map to this context.
+ * New attribute mappings will be added only if they don't already exist in
+ * this context.
+ * @param defaultAttributes Attributes to add.
+ */
+ public void addMissing(Map defaultAttributes) {
+ if (defaultAttributes == null) {
+ return;
+ }
+
+ if (attributes == null) {
+ attributes = new HashMap(defaultAttributes);
+ return;
+ }
+
+ Set entries = defaultAttributes.entrySet();
+ Iterator iterator = entries.iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ if (!attributes.containsKey(entry.getKey())) {
+ attributes.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * Get an attribute from context.
+ * @param name Name of the attribute.
+ * @return <{Object}>
+ */
+ public Object getAttribute(String name) {
+ if (attributes == null){
+ return null;
+ }
+
+ return attributes.get(name);
+ }
+
+ /**
+ * Get names of all attributes.
+ * @return <{Object}>
+ */
+ public Iterator getAttributeNames() {
+ if (attributes == null) {
+ return Collections.EMPTY_LIST.iterator();
+ }
+
+ return attributes.keySet().iterator();
+ }
+
+ /**
+ * Put a new attribute to context.
+ * @param name Name of the attribute.
+ * @param value Value of the attribute.
+ */
+ public void putAttribute(String name, Object value) {
+ if (attributes == null) {
+ attributes = new HashMap();
+ }
+
+ attributes.put(name, value);
+ }
+
+ /**
+ * Find object in one of the contexts.
+ * Order : component then pageContext.findAttribute()
+ * @param beanName Name of the bean to find.
+ * @param pageContext Page context.
+ * @return Requested bean or <code>null</code> if not found.
+ */
+ public Object findAttribute(String beanName, PageContext pageContext) {
+ Object attribute = getAttribute(beanName);
+ if (attribute == null) {
+ attribute = pageContext.findAttribute(beanName);
+ }
+
+ return attribute;
+ }
+
+ /**
+ * Get object from requested context.
+ * Context can be 'component'.
+ * @param beanName Name of the bean to find.
+ * @param scope Search scope (see {@link PageContext}).
+ * @param pageContext Page context.
+ * @return requested bean or <code>null</code> if not found.
+ */
+ public Object getAttribute(
+ String beanName,
+ int scope,
+ PageContext pageContext) {
+
+ if (scope == ComponentConstants.COMPONENT_SCOPE){
+ return getAttribute(beanName);
+ }
+
+ return pageContext.getAttribute(beanName, scope);
+ }
+
+ /**
+ * Get component context from request.
+ * @param request ServletRequest.
+ * @return ComponentContext
+ */
+ static public ComponentContext getContext(ServletRequest request) {
+ return (ComponentContext) request.getAttribute(
+ ComponentConstants.COMPONENT_CONTEXT);
+ }
+
+ /**
+ * Store component context into request.
+ * @param context ComponentContext to store.
+ * @param request Request to store ComponentContext.
+ */
+ static public void setContext(
+ ComponentContext context,
+ ServletRequest request) {
+
+ request.setAttribute(ComponentConstants.COMPONENT_CONTEXT, context);
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentDefinition.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentDefinition.java
new file mode 100644
index 0000000..cc1ec8a
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentDefinition.java
@@ -0,0 +1,545 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tiles.xmlDefinition.XmlDefinition;
+import org.apache.tiles.TilesUtil;
+
+/**
+ * Definition of a template / component attributes.
+ * Attributes of a component can be defined with the help of this class.
+ * An instance of this class can be used as a bean, and passed to 'insert' tag.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ */
+public class ComponentDefinition implements Serializable {
+
+ /**
+ * Commons Logging instance.
+ */
+ protected static Log log = LogFactory.getLog(ComponentDefinition.class);
+
+ /**
+ * Definition name
+ */
+ protected String name = null;
+
+ /**
+ * Component / template path (URL).
+ */
+ protected String path = null;
+
+ /**
+ * Attributes defined for the component.
+ */
+ protected Map attributes = null;
+
+ /**
+ * Role associated to definition.
+ */
+ protected String role = null;
+
+ /** Associated Controller URL or classname, if defined */
+ protected String controller = null;
+
+ /**
+ * Associated Controller typename, if controllerName defined.
+ * Can be CONTROLLER, ACTION or URL, or null.
+ */
+ protected String controllerType = null;
+
+ /**
+ * Controller name type.
+ */
+ public static final String URL = "url";
+
+ /**
+ * Controller name type.
+ */
+ public static final String CONTROLLER = "controller";
+
+ /**
+ * Controller name type.
+ */
+ public static final String ACTION = "action";
+
+ /**
+ * Controller associated to Definition.
+ * Lazy creation : only on first request
+ */
+ private Controller controllerInstance = null;
+
+ /**
+ * Constructor.
+ */
+ public ComponentDefinition() {
+ attributes = new HashMap();
+ }
+
+ /**
+ * Copy Constructor.
+ * Create a new definition initialized with parent definition.
+ * Do a shallow copy : attributes are shared between copies, but not the Map
+ * containing attributes.
+ */
+ public ComponentDefinition(ComponentDefinition definition) {
+ attributes = new HashMap(definition.getAttributes());
+ this.name = definition.getName();
+ this.path = definition.getPath();
+ this.role = definition.getRole();
+ this.controllerInstance = definition.getControllerInstance();
+ this.controller = definition.getController();
+ this.controllerType = definition.getControllerType();
+ }
+
+ /**
+ * Constructor.
+ * Create a new definition initialized from a RawDefinition.
+ * Raw definitions are used to read definition from a data source (xml file, db, ...).
+ * A RawDefinition mainly contains properties of type String, while Definition
+ * contains more complex type (ex : Controller).
+ * Do a shallow copy : attributes are shared between objects, but not the Map
+ * containing attributes.
+ * OO Design issues : Actually RawDefinition (XmlDefinition) extends ComponentDefinition.
+ * This must not be the case. I have do it because I am lazy.
+ * @throws InstantiationException if an error occur while instanciating Controller :
+ * (classname can't be instanciated, Illegal access with instanciated class,
+ * Error while instanciating class, classname can't be instanciated.
+ */
+ public ComponentDefinition(XmlDefinition definition) {
+
+ this((ComponentDefinition) definition);
+ }
+
+ /**
+ * Constructor.
+ */
+ public ComponentDefinition(String name, String path, Map attributes) {
+ this.name = name;
+ this.path = path;
+ this.attributes = attributes;
+ }
+
+ /**
+ * Access method for the name property.
+ *
+ * @return the current value of the name property
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param aName the new value of the name property
+ */
+ public void setName(String aName) {
+ name = aName;
+ }
+
+ /**
+ * Access method for the path property.
+ *
+ * @return The current value of the path property.
+ */
+ public String getPage() {
+ return path;
+ }
+
+ /**
+ * Sets the value of the path property.
+ *
+ * @param aPath the new value of the path property
+ */
+ public void setPage(String page) {
+ path = page;
+ }
+
+ /**
+ * Access method for the path property.
+ *
+ * @return the current value of the path property
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Sets the value of the path property.
+ *
+ * @param aPath the new value of the path property
+ */
+ public void setPath(String aPath) {
+ path = aPath;
+ }
+
+ /**
+ * Access method for the template property.
+ * Same as getPath()
+ * @return the current value of the template property
+ */
+ public String getTemplate() {
+ return path;
+ }
+
+ /**
+ * Sets the value of the template property.
+ * Same as setPath()
+ *
+ * @param template the new value of the path property
+ */
+ public void setTemplate(String template) {
+ path = template;
+ }
+
+ /**
+ * Access method for the role property.
+ * @return the current value of the role property
+ */
+ public String getRole() {
+ return role;
+ }
+
+ /**
+ * Sets the value of the role property.
+ *
+ * @param role the new value of the path property
+ */
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ /**
+ * Access method for the attributes property.
+ * If there is no attributes, return an empty map.
+ * @return the current value of the attributes property
+ */
+ public Map getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Returns the value of the named attribute as an Object, or null if no
+ * attribute of the given name exists.
+ *
+ * @return requested attribute or null if not found
+ */
+ public Object getAttribute(String key) {
+ return attributes.get(key);
+ }
+
+ /**
+ * Put a new attribute in this component
+ *
+ * @param key String key for attribute
+ * @param value Attibute value.
+ */
+ public void putAttribute(String key, Object value) {
+ attributes.put(key, value);
+ }
+
+ /**
+ * Put an attribute in component / template definition.
+ * Attribute can be used as content for tag get.
+ * @param name Attribute name
+ * @param content Attribute value
+ */
+ public void put(String name, Object content) {
+ put(name, content, false, null);
+ }
+
+ /**
+ * Put an attribute in template definition.
+ * Attribute can be used as content for tag get.
+ * @param name Attribute name
+ * @param content Attribute value µ
+ * @param direct Determines how content is handled by get tag: true means content is printed directly; false, the default, means content is included
+ */
+ public void put(String name, Object content, boolean direct) {
+ put(name, content, direct, null);
+ }
+
+ /**
+ * Put an attribute in template definition.
+ * Attribute can be used as content for tag get.
+ * @param name Attribute name
+ * @param content Attribute value
+ * @param direct Determines how content is handled by get tag: true means content is printed directly; false, the default, means content is included
+ * @param role Determine if content is used by get tag. If user is in role, content is used.
+ */
+ public void put(String name, Object content, boolean direct, String role) {
+ if (direct == true) { // direct String
+ put(name, content, "string", role);
+ } else {
+ put(name, content, "template", role);
+ }
+
+ }
+
+ /**
+ * Put an attribute in template definition.
+ * Attribute can be used as content for tag get.
+ * @param name Attribute name
+ * @param content Attribute value
+ * @param type attribute type: template, string, definition
+ * @param role Determine if content is used by get tag. If user is in role, content is used.
+ */
+ public void put(String name, Object content, String type, String role) {
+ // Is there a type set ?
+ // First check direct attribute, and translate it to a valueType.
+ // Then, evaluate valueType, and create requested typed attribute.
+ AttributeDefinition attribute = null;
+
+ if (content != null
+ && type != null
+ && !(content instanceof AttributeDefinition)) {
+
+ String strValue = content.toString();
+ if (type.equalsIgnoreCase("string")) {
+ attribute = new DirectStringAttribute(strValue);
+
+ } else if (type.equalsIgnoreCase("page")) {
+ attribute = new PathAttribute(strValue);
+
+ } else if (type.equalsIgnoreCase("template")) {
+ attribute = new PathAttribute(strValue);
+
+ } else if (type.equalsIgnoreCase("instance")) {
+ attribute = new DefinitionNameAttribute(strValue);
+
+ } else if (type.equalsIgnoreCase("definition")) {
+ attribute = new DefinitionNameAttribute(strValue);
+ }
+ }
+
+ putAttribute(name, attribute);
+ }
+
+ /**
+ * Returns a description of the attributes.
+ */
+ public String toString() {
+ return "{name="
+ + name
+ + ", path="
+ + path
+ + ", role="
+ + role
+ + ", controller="
+ + controller
+ + ", controllerType="
+ + controllerType
+ + ", controllerInstance="
+ + controllerInstance
+ + ", attributes="
+ + attributes
+ + "}\n";
+ }
+
+ /**
+ * Get associated controller type.
+ * Type denote a fully qualified classname.
+ */
+ public String getControllerType() {
+ return controllerType;
+ }
+
+ /**
+ * Set associated controller type.
+ * Type denote a fully qualified classname.
+ * @param controllerType Typeof associated controller
+ */
+ public void setControllerType(String controllerType) {
+ this.controllerType = controllerType;
+ }
+
+ /**
+ * Set associated controller name as an url, and controller
+ * type as "url".
+ * Name must be an url (not checked).
+ * Convenience method.
+ * @param controller Controller url
+ */
+ public void setControllerUrl(String controller) {
+ setController(controller);
+ setControllerType("url");
+ }
+
+ /**
+ * Set associated controller name as a classtype, and controller
+ * type as "classname".
+ * Name denote a fully qualified classname
+ * Convenience method.
+ * @param controller Controller classname.
+ */
+ public void setControllerClass(String controller) {
+ setController(controller);
+ setControllerType("classname");
+ }
+
+ /**
+ * Get associated controller local URL.
+ * URL should be local to webcontainer in order to allow request context followup.
+ * URL comes as a string.
+ */
+ public String getController() {
+ return controller;
+ }
+
+ /**
+ * Set associated controller URL.
+ * URL should be local to webcontainer in order to allow request context followup.
+ * URL is specified as a string.
+ * @param url Url called locally
+ */
+ public void setController(String url) {
+ this.controller = url;
+ }
+
+ /**
+ * Get controller instance.
+ * @return controller instance.
+ */
+ public Controller getControllerInstance() {
+ return controllerInstance;
+ }
+
+ /**
+ * Get or create controller.
+ * Get controller, create it if necessary.
+ * @return controller if controller or controllerType is set, null otherwise.
+ * @throws InstantiationException if an error occur while instanciating Controller :
+ * (classname can't be instanciated, Illegal access with instanciated class,
+ * Error while instanciating class, classname can't be instanciated.
+ */
+ public Controller getOrCreateController() throws InstantiationException {
+
+ if (controllerInstance != null) {
+ return controllerInstance;
+ }
+
+ // Do we define a controller ?
+ if (controller == null && controllerType == null) {
+ return null;
+ }
+
+ // check parameters
+ if (controllerType != null && controller == null) {
+ throw new InstantiationException("Controller name should be defined if controllerType is set");
+ }
+
+ controllerInstance = createController(controller, controllerType);
+
+ return controllerInstance;
+ }
+
+ /**
+ * Set controller.
+ */
+ public void setControllerInstance(Controller controller) {
+ this.controllerInstance = controller;
+ }
+
+ /**
+ * Create a new instance of controller named in parameter.
+ * If controllerType is specified, create controller accordingly.
+ * Otherwise, if name denote a classname, create an instance of it. If class is
+ * subclass of org.apache.struts.action.Action, wrap controller
+ * appropriately.
+ * Otherwise, consider name as an url.
+ * @param name Controller name (classname, url, ...)
+ * @param controllerType Expected Controller type
+ * @return org.apache.tiles.Controller
+ * @throws InstantiationException if an error occur while instanciating Controller :
+ * (classname can't be instanciated, Illegal access with instanciated class,
+ * Error while instanciating class, classname can't be instanciated.
+ */
+ public static Controller createController(String name, String controllerType)
+ throws InstantiationException {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Create controller name=" + name + ", type=" + controllerType);
+ }
+
+ Controller controller = null;
+
+ if (controllerType == null) { // first try as a classname
+ try {
+ return createControllerFromClassname(name);
+
+ } catch (InstantiationException ex) { // ok, try something else
+ controller = new UrlController(name);
+ }
+
+ } else if ("url".equalsIgnoreCase(controllerType)) {
+ controller = new UrlController(name);
+
+ } else if ("classname".equalsIgnoreCase(controllerType)) {
+ controller = createControllerFromClassname(name);
+ }
+
+ return controller;
+ }
+
+ /**
+ * Create a controller from specified classname
+ * @param classname Controller classname.
+ * @return org.apache.tiles.Controller
+ * @throws InstantiationException if an error occur while instanciating Controller :
+ * (classname can't be instanciated, Illegal access with instanciated class,
+ * Error while instanciating class, classname can't be instanciated.
+ */
+ public static Controller createControllerFromClassname(String classname)
+ throws InstantiationException {
+
+ try {
+ Class requestedClass = TilesUtil.applicationClass(classname);
+ Object instance = requestedClass.newInstance();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Controller created : " + instance);
+ }
+ return (Controller) instance;
+
+ } catch (java.lang.ClassNotFoundException ex) {
+ throw new InstantiationException(
+ "Error - Class not found :" + ex.getMessage());
+
+ } catch (java.lang.IllegalAccessException ex) {
+ throw new InstantiationException(
+ "Error - Illegal class access :" + ex.getMessage());
+
+ } catch (java.lang.InstantiationException ex) {
+ throw ex;
+
+ } catch (java.lang.ClassCastException ex) {
+ throw new InstantiationException(
+ "Controller of class '"
+ + classname
+ + "' should implements 'Controller' or extends 'Action'");
+ }
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentDefinitionsFactory.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentDefinitionsFactory.java
new file mode 100644
index 0000000..7c5d695
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ComponentDefinitionsFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.util.Map;
+import java.io.Serializable;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletContext;
+
+/**
+ * Component repository interface.
+ * This interface allows to retrieve an definition by its name, independently of the
+ * factory implementation.
+ * Implementation must be Serializable, in order to be compliant with web Container
+ * having this constraint (Weblogic 6.x).
+ * @deprecated Use DefinitionsFactory instead.
+*/
+public interface ComponentDefinitionsFactory extends Serializable
+{
+
+ /**
+ * Get a definition by its name.
+ * @param name Name of requested definition.
+ * @param request Current servelet request
+ * @param servletContext current servlet context
+ * @throws DefinitionsFactoryException An error occur while getting definition.
+ * @throws NoSuchDefinitionException No definition found for specified name
+ * Implementation can throw more accurate exception as a subclass of this exception
+ */
+ public ComponentDefinition getDefinition(String name, ServletRequest request, ServletContext servletContext) throws NoSuchDefinitionException,DefinitionsFactoryException;
+
+ /**
+ * Init factory.
+ * This method is called exactly once immediately after factory creation in
+ * case of internal creation (by DefinitionUtil).
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property passed to newly created factory.
+ * Map can contains more properties than requested.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ public void initFactory(ServletContext servletContext, Map properties) throws DefinitionsFactoryException;
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/Controller.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/Controller.java
new file mode 100644
index 0000000..1ef1ba0
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/Controller.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletContext;
+
+/**
+ * A controller is a piece of code called before rendering a jsp page.
+ * A controller can be associated to a tile. See <insert> or <definition> for
+ * association syntax.
+ */
+public interface Controller
+{
+
+ /**
+ * Method associated to a tile and called immediately before the tile is included.
+ * @param tileContext Current tile context.
+ * @param request Current request
+ * @param response Current response
+ * @param servletContext Current servlet context
+ */
+ public void perform(ComponentContext tileContext,
+ HttpServletRequest request, HttpServletResponse response,
+ ServletContext servletContext)
+ throws ServletException, IOException;
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ControllerSupport.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ControllerSupport.java
new file mode 100644
index 0000000..f96eb5c
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/ControllerSupport.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletContext;
+
+/**
+ * Basic implementation of Controller.
+ */
+public class ControllerSupport implements Controller {
+
+ /**
+ * Method associated with a tile and called immediately before tile is included.
+ * This implementation does nothing.
+ * @param tileContext Current tile context.
+ * @param request Current request
+ * @param response Current response
+ * @param servletContext Current servlet context
+ */
+ public void perform(ComponentContext tileContext,
+ HttpServletRequest request, HttpServletResponse response,
+ ServletContext servletContext)
+ throws ServletException, IOException {
+
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionAttribute.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionAttribute.java
new file mode 100644
index 0000000..e9b4900
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionAttribute.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+/**
+ * Attribute representing a Component Definition.
+ * This attribute definition contains a Component definition.
+ */
+public class DefinitionAttribute extends UntypedAttribute {
+
+ public DefinitionAttribute(String value) {
+ super(value);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionNameAttribute.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionNameAttribute.java
new file mode 100644
index 0000000..e8248e9
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionNameAttribute.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+/**
+ * Component attribute.
+ * Such attribute value represent an instance name.
+ */
+public class DefinitionNameAttribute extends UntypedAttribute {
+
+ /**
+ * Constructor.
+ */
+ public DefinitionNameAttribute(String value) {
+ super(value);
+ }
+
+ /**
+ * Constructor.
+ */
+ public DefinitionNameAttribute(String value, String role) {
+ super(value, role);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactory.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactory.java
new file mode 100644
index 0000000..43ef933
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactory.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.Serializable;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+
+/**
+ * Tiles Definition factory.
+ * This interface replace old ComponentDefinitionsFactory.
+ * Main method getDefinition() is exactly the same. Initialization method change.
+ * This interface allows to retrieve a definition by its name, independently of
+ * the factory implementation.
+ * Object life cycle is as follow:
+ * <ul>
+ * <li>Constructor: create object</li>
+ * <li>setConfig: set config and initialize factory. After first call to this
+ * method, factory is operational.</li>
+ * <li>destroy: factory is being shutdown.</li>
+ * </ul>
+ * Implementation must be Serializable, in order to be compliant with web Container
+ * having this constraint (Weblogic 6.x).
+ */
+public interface DefinitionsFactory extends Serializable
+{
+
+ /**
+ * Get a definition by its name.
+ * @param name Name of requested definition.
+ * @param request Current servelet request
+ * @param servletContext current servlet context
+ * @throws DefinitionsFactoryException An error occur while getting definition.
+ * @throws NoSuchDefinitionException No definition found for specified name
+ * Implementation can throw more accurate exception as a subclass of this exception
+ */
+ public ComponentDefinition getDefinition(String name, ServletRequest request, ServletContext servletContext)
+ throws NoSuchDefinitionException,DefinitionsFactoryException;
+
+ /**
+ * Init definition factory.
+ * This method is called immediately after factory creation, and prior any call
+ * to setConfig().
+ *
+ * @param config Configuration object used to set factory configuration.
+ * @param servletContext Servlet Context passed to factory.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ public void init(DefinitionsFactoryConfig config, ServletContext servletContext)
+ throws DefinitionsFactoryException;
+
+ /**
+ * <p>Receive notification that the factory is being
+ * shut down.</p>
+ */
+ public void destroy();
+
+ /**
+ * Set factory configuration.
+ * This method is used to change factory configuration.
+ * This method is optional, and can send an exception if implementation
+ * doesn't allow change in configuration.
+ *
+ * @param config Configuration object used to set factory configuration.
+ * @param servletContext Servlet Context passed to factory.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ public void setConfig(DefinitionsFactoryConfig config, ServletContext servletContext)
+ throws DefinitionsFactoryException;
+
+ /**
+ * Get factory configuration.
+ * @return TilesConfig
+ */
+ public DefinitionsFactoryConfig getConfig();
+
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactoryConfig.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactoryConfig.java
new file mode 100644
index 0000000..012a779
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactoryConfig.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.beanutils.BeanUtils;
+
+/**
+ * A TilesFactoryConfig object hold configuration attributes for a tile
+ * definition factory.
+ *
+ * @author Cedric Dumoulin
+ * @since Struts 1.1
+ * @version $Revision: 1.9 $ $Date: 2003/07/09 00:05:17 $
+ */
+public class DefinitionsFactoryConfig implements Serializable {
+
+ /**
+ * Fully qualified classname of the factory to create.
+ * If no classname is set, a default factory is created
+ * (of class "org.apache.tiles.xmlDefinition.I18nFactorySet").
+ */
+ protected String factoryClassname =
+ "org.apache.tiles.xmlDefinition.I18nFactorySet";
+
+ /**
+ * Specifies whether the parser will validate configuration files.
+ * Default value is true.
+ */
+ protected boolean parserValidate = true;
+
+ /**
+ * Definition configuration file specified by user.
+ */
+ protected String definitionConfigFiles = null;
+
+ /**
+ * Specifies whether the factory is "module-aware".
+ */
+ protected boolean moduleAware = true;
+
+ /**
+ * The name associated to this factory.
+ * <br>
+ * With Struts 1.1, this name is the module name to which this factory
+ * belong. It is set by the system.
+ * <br>
+ * In prior versions, this property is not used.
+ */
+ protected String factoryName;
+
+ /**
+ * Alternate name for parser debug details properties in configuration file.
+ * @deprecated This will be removed in a release after Struts 1.2.
+ */
+ public static final String PARSER_DETAILS_PARAMETER_NAME =
+ "definitions-parser-details";
+
+ /**
+ * Alternate name for parser validate properties in configuration file.
+ */
+ public static final String PARSER_VALIDATE_PARAMETER_NAME =
+ "definitions-parser-validate";
+
+ /**
+ * Alternate name for factory classname properties in configuration file.
+ */
+ public static final String FACTORY_CLASSNAME_PARAMETER_NAME =
+ "definitions-factory-class";
+
+ /**
+ * Alternate name for definition files properties in configuration file.
+ */
+ public static final String DEFINITIONS_CONFIG_PARAMETER_NAME =
+ "definitions-config";
+
+ /**
+ * Alternate name for definition debug details properties in configuration file.
+ * @deprecated This will be removed in a release after Struts 1.2.
+ */
+ public static final String TILES_DETAILS_PARAMETER_NAME = "definitions-debug";
+
+ /**
+ * Map of extra attribute available.
+ */
+ private Map extraAttributes = new HashMap();
+
+ /**
+ * Default constructor.
+ */
+ public DefinitionsFactoryConfig() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ * Create configuration object, and initialize it with parameters from Map.
+ * Parameters corresponding to an attribute are filtered and stored in appropriate
+ * attribute.
+ * @param initParameters Map.
+ */
+ public DefinitionsFactoryConfig(Map initParameters) {
+ super();
+ }
+
+ /**
+ * Get the module aware flag.
+ * @return <code>true</code>: user wants a single factory instance,
+ * <code>false</code>: user wants multiple factory instances (one per module with Struts)
+ */
+ public boolean isModuleAware() {
+ return moduleAware;
+ }
+ /**
+ * Set the module aware flag.
+ * @param moduleAware <code>true</code>: user wants a single factory instance,
+ * <code>false</code>: user wants multiple factory instances (one per module with Struts)
+ */
+ public void setModuleAware(boolean moduleAware) {
+ this.moduleAware = moduleAware;
+ }
+
+ /**
+ * Get the classname of the factory.
+ * @return Classname.
+ */
+ public String getFactoryClassname() {
+ return factoryClassname;
+ }
+
+ /**
+ * Set the classname of the factory..
+ * @param aFactoryClassname Classname of the factory.
+ */
+ public void setFactoryClassname(String aFactoryClassname) {
+ factoryClassname = aFactoryClassname;
+ }
+
+ /**
+ * Determines if the parser is validating.
+ * @return <code>true<code> when in validating mode.
+ */
+ public boolean getParserValidate() {
+ return parserValidate;
+ }
+
+ /**
+ * Set the validating mode for the parser.
+ * @param aParserValidate <code>true</code> for validation, <code>false</code> otherwise
+ */
+ public void setParserValidate(boolean aParserValidate) {
+ parserValidate = aParserValidate;
+ }
+
+ /**
+ * Get the definition config files.
+ * @return Defition config files.
+ */
+ public String getDefinitionConfigFiles() {
+ return definitionConfigFiles;
+ }
+
+ /**
+ * Set the definition config files.
+ * @param aDefinitionConfigFiles Definition config files.
+ */
+ public void setDefinitionConfigFiles(String aDefinitionConfigFiles) {
+ definitionConfigFiles = aDefinitionConfigFiles;
+ }
+
+ /**
+ * Set value of an additional attribute.
+ * @param name Name of the attribute.
+ * @param value Value of the attribute.
+ */
+ public void setAttribute(String name, Object value) {
+ extraAttributes.put(name, value);
+ }
+
+ /**
+ * Get value of an additional attribute.
+ * @param name Name of the attribute.
+ * @return Value of the attribute, or null if not found.
+ */
+ public Object getAttribute(String name) {
+ return extraAttributes.get(name);
+ }
+
+ /**
+ * Get additional attributes as a Map.
+ * @return Map A Map containing attribute name - value pairs.
+ */
+ public Map getAttributes() {
+ Map map = new HashMap(extraAttributes);
+ // Add property attributes using old names
+ /*
+ map.put(DEFINITIONS_CONFIG_PARAMETER_NAME, getDefinitionConfigFiles());
+ map.put(TILES_DETAILS_PARAMETER_NAME, Integer.toString(getDebugLevel()) );
+ map.put(PARSER_DETAILS_PARAMETER_NAME, Integer.toString(getParserDebugLevel()) );
+ map.put(PARSER_VALIDATE_PARAMETER_NAME, new Boolean(getParserValidate()).toString() );
+
+ if( ! "org.apache.tiles.xmlDefinition.I18nFactorySet".equals(getFactoryClassname()) )
+ map.put(FACTORY_CLASSNAME_PARAMETER_NAME, getFactoryClassname());
+ */
+ return map;
+ }
+
+ /**
+ * Populate this config object from properties map, based on
+ * the specified name/value pairs. This method uses the populate() method from
+ * org.apache.commons.beanutils.BeanUtil.
+ * <p>
+ * Properties keys are scanned for old property names, and linked to the new name
+ * if necessary. This modifies the properties map.
+ * <p>
+ * The particular setter method to be called for each property is
+ * determined using the usual JavaBeans introspection mechanisms. Thus,
+ * you may identify custom setter methods using a BeanInfo class that is
+ * associated with the class of the bean itself. If no such BeanInfo
+ * class is available, the standard method name conversion ("set" plus
+ * the capitalized name of the property in question) is used.
+ * <p>
+ * <strong>NOTE</strong>: It is contrary to the JavaBeans Specification
+ * to have more than one setter method (with different argument
+ * signatures) for the same property.
+ *
+ * @param properties Map keyed by property name, with the
+ * corresponding (String or String[]) value(s) to be set.
+ *
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method.
+ * @exception InvocationTargetException if the property accessor method
+ * throws an exception.
+ * @see org.apache.commons.beanutils.BeanUtils
+ */
+ public void populate(Map properties)
+ throws IllegalAccessException, InvocationTargetException {
+
+ // link old parameter names for backward compatibility
+ linkOldPropertyNames(properties);
+ BeanUtils.populate(this, properties);
+ }
+
+ /**
+ * Link old property names to new property names.
+ * This modifies the map.
+ * @param properties Map keyed by property name, with the
+ * corresponding (String or String[]) value(s) to be set.
+ */
+ static public void linkOldPropertyNames(Map properties) {
+ Set entries = properties.entrySet();
+ Map toAdd = new HashMap();
+ Iterator i = entries.iterator();
+ while (i.hasNext()) {
+ Map.Entry entry = (Map.Entry) i.next();
+
+ if (DEFINITIONS_CONFIG_PARAMETER_NAME.equals(entry.getKey())) {
+ toAdd.put("definitionConfigFiles", entry.getValue());
+
+ } else if (FACTORY_CLASSNAME_PARAMETER_NAME.equals(entry.getKey())) {
+ toAdd.put("factoryClassname", entry.getValue());
+
+ } else if (PARSER_DETAILS_PARAMETER_NAME.equals(entry.getKey())) {
+ toAdd.put("parserDebugLevel", entry.getValue());
+
+ } else if (PARSER_VALIDATE_PARAMETER_NAME.equals(entry.getKey())) {
+ toAdd.put("parserValidate", entry.getValue());
+
+ } else if (TILES_DETAILS_PARAMETER_NAME.equals(entry.getKey())) {
+ toAdd.put("debugLevel", entry.getValue());
+ }
+ }
+
+ if (toAdd.size() > 0) {
+ properties.putAll(toAdd);
+ }
+ }
+
+ /**
+ * Get the factory name.
+ */
+ public String getFactoryName() {
+ return factoryName;
+ }
+ /**
+ * Set the factory name.
+ * @param factoryName Name of the factory.
+ */
+ public void setFactoryName(String factoryName) {
+ this.factoryName = factoryName;
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactoryException.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactoryException.java
new file mode 100644
index 0000000..2f21960
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsFactoryException.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+ /**
+ * Exception thrown when an error occurs while the factory tries to
+ * create a new instance mapper.
+ */
+public class DefinitionsFactoryException extends TilesException
+{
+ /**
+ * Constructor.
+ */
+ public DefinitionsFactoryException()
+ {
+ super();
+ this.exception = null;
+ }
+
+ /**
+ * Constructor.
+ * @param message The error or warning message.
+ */
+ public DefinitionsFactoryException(String message)
+ {
+ super(message);
+ this.exception = null;
+ }
+
+
+ /**
+ * Create a new <code>DefinitionsFactoryException</code> wrapping an existing exception.
+ *
+ * <p>The existing exception will be embedded in the new
+ * one and its message will become the default message for
+ * the DefinitionsFactoryException.</p>
+ *
+ * @param e The exception to be wrapped.
+ */
+ public DefinitionsFactoryException(Exception e)
+ {
+ super();
+ this.exception = e;
+ }
+
+
+ /**
+ * Create a new <code>DefinitionsFactoryException</code> from an existing exception.
+ *
+ * <p>The existing exception will be embedded in the new
+ * one, but the new exception will have its own message.</p>
+ *
+ * @param message The detail message.
+ * @param e The exception to be wrapped.
+ */
+ public DefinitionsFactoryException(String message, Exception e)
+ {
+ super(message);
+ this.exception = e;
+ }
+
+
+ /**
+ * Return a detail message for this exception.
+ *
+ * <p>If there is a embedded exception, and if the DefinitionsFactoryException
+ * has no detail message of its own, this method will return
+ * the detail message from the embedded exception.</p>
+ *
+ * @return The error or warning message.
+ */
+ public String getMessage ()
+ {
+ String message = super.getMessage ();
+
+ if (message == null && exception != null) {
+ return exception.getMessage();
+ } else {
+ return message;
+ }
+ }
+
+
+ /**
+ * Return the embedded exception, if any.
+ * @return The embedded exception, or <code>null</code> if there is none.
+ */
+ public Exception getException ()
+ {
+ return exception;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Internal state.
+ //////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Any "wrapped" exception will be exposed when this is serialized.
+ * @serial
+ */
+ private Exception exception;
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsUtil.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsUtil.java
new file mode 100644
index 0000000..4db31cd
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DefinitionsUtil.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.taglib.tiles.ComponentConstants;
+
+/**
+ * Utilities class for definitions factory.
+ * Also define userDebugLevel property (TODO to be moved from this class ?).
+ * @deprecated Use {@link TilesUtil#createDefinitionsFactory(ServletContext, DefinitionsFactoryConfig)}
+ */
+public class DefinitionsUtil extends TilesUtil implements ComponentConstants {
+
+ /**
+ * Commons Logging instance.
+ */
+ protected static Log log = LogFactory.getLog(DefinitionsUtil.class);
+
+ /**
+ * Global user defined debug level.
+ * @deprecated This will be removed in a release after Struts 1.2.
+ */
+ public static int userDebugLevel = 0;
+
+ /**
+ * User Debug level.
+ * @deprecated This will be removed in a release after Struts 1.2.
+ */
+ public static final int NO_DEBUG = 0;
+
+ /**
+ * Name of init property carrying debug level.
+ */
+ public static final String DEFINITIONS_CONFIG_USER_DEBUG_LEVEL =
+ "definitions-debug";
+
+ /**
+ * Name of init property carrying factory class name.
+ */
+ public static final String DEFINITIONS_FACTORY_CLASSNAME =
+ "definitions-factory-class";
+
+ /**
+ * Constant name used to store factory in context.
+ */
+ public static final String DEFINITIONS_FACTORY =
+ "org.apache.tiles.DEFINITIONS_FACTORY";
+
+ /**
+ * Constant name used to store definition in jsp context.
+ * Used to pass definition from a Struts action to servlet forward.
+ */
+ public static final String ACTION_DEFINITION =
+ "org.apache.tiles.ACTION_DEFINITION";
+
+ /**
+ * Create Definition factory.
+ * If a factory class name is provided, a factory of this class is created. Otherwise,
+ * default factory is created.
+ * @param classname Class name of the factory to create.
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property used to initialize factory configuration object.
+ * @return newly created factory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ * @deprecated Use createDefinitionsFactory(ServletContext servletContext, ServletConfig servletConfig)
+ */
+ public static DefinitionsFactory createDefinitionsFactory(
+ ServletContext servletContext,
+ Map properties,
+ String classname)
+ throws DefinitionsFactoryException {
+
+ // Create config object
+ DefinitionsFactoryConfig factoryConfig = new DefinitionsFactoryConfig();
+ // populate it from map.
+ try {
+ factoryConfig.populate(properties);
+
+ } catch (Exception ex) {
+ throw new DefinitionsFactoryException(
+ "Error - createDefinitionsFactory : Can't populate config object from properties map",
+ ex);
+ }
+
+ // Add classname
+ if (classname != null)
+ factoryConfig.setFactoryClassname(classname);
+
+ // Create factory using config object
+ return createDefinitionsFactory(servletContext, factoryConfig);
+ }
+
+ /**
+ * Create default Definition factory.
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property used to initialize factory configuration object.
+ * @return newly created factory of type ConfigurableDefinitionsFactory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ public static DefinitionsFactory createDefinitionsFactory(
+ ServletContext servletContext,
+ Map properties)
+ throws DefinitionsFactoryException {
+
+ return createDefinitionsFactory(servletContext, properties, null);
+ }
+
+ /**
+ * Create Definition factory.
+ * Create configuration object from servlet web.xml file, then create
+ * ConfigurableDefinitionsFactory and initialized it with object.
+ * <p>
+ * Convenience method. Calls createDefinitionsFactory(ServletContext servletContext, DefinitionsFactoryConfig factoryConfig)
+ *
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param servletConfig Servlet config containing parameters to be passed to factory configuration object.
+ * @return newly created factory of type ConfigurableDefinitionsFactory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ public static DefinitionsFactory createDefinitionsFactory(
+ ServletContext servletContext,
+ ServletConfig servletConfig)
+ throws DefinitionsFactoryException {
+
+ DefinitionsFactoryConfig factoryConfig = readFactoryConfig(servletConfig);
+
+ return createDefinitionsFactory(servletContext, factoryConfig);
+ }
+
+ /**
+ * Create Definition factory.
+ * Create configuration object from servlet web.xml file, then create
+ * ConfigurableDefinitionsFactory and initialized it with object.
+ * <p>
+ * If checkIfExist is true, start by checking if factory already exist. If yes,
+ * return it. If no, create a new one.
+ * <p>
+ * If checkIfExist is false, factory is always created.
+ * <p>
+ * Convenience method. Calls createDefinitionsFactory(ServletContext servletContext, DefinitionsFactoryConfig factoryConfig)
+ *
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param servletConfig Servlet config containing parameters to be passed to factory configuration object.
+ * @param checkIfExist Check if factory already exist. If true and factory exist, return it.
+ * If true and factory doesn't exist, create it. If false, create it in all cases.
+ * @return newly created factory of type ConfigurableDefinitionsFactory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ public static DefinitionsFactory createDefinitionsFactory(
+ ServletContext servletContext,
+ ServletConfig servletConfig,
+ boolean checkIfExist)
+ throws DefinitionsFactoryException {
+
+ if (checkIfExist) {
+ // Check if already exist in context
+ DefinitionsFactory factory = getDefinitionsFactory(servletContext);
+ if (factory != null)
+ return factory;
+ }
+
+ return createDefinitionsFactory(servletContext, servletConfig);
+ }
+
+ /**
+ * Get definition factory from appropriate servlet context.
+ * @return Definitions factory or null if not found.
+ * @deprecated Use {@link TilesUtil#getDefinitionsFactory(ServletRequest, ServletContext)}
+ * @since 20020708
+ */
+ public static DefinitionsFactory getDefinitionsFactory(ServletContext servletContext) {
+ return (DefinitionsFactory) servletContext.getAttribute(DEFINITIONS_FACTORY);
+ }
+
+ /**
+ * Get Definition stored in jsp context by an action.
+ * @return ComponentDefinition or null if not found.
+ */
+ public static ComponentDefinition getActionDefinition(ServletRequest request) {
+ return (ComponentDefinition) request.getAttribute(ACTION_DEFINITION);
+ }
+
+ /**
+ * Store definition in jsp context.
+ * Mainly used by Struts to pass a definition defined in an Action to the forward.
+ */
+ public static void setActionDefinition(
+ ServletRequest request,
+ ComponentDefinition definition) {
+
+ request.setAttribute(ACTION_DEFINITION, definition);
+ }
+
+ /**
+ * Remove Definition stored in jsp context.
+ * Mainly used by Struts to pass a definition defined in an Action to the forward.
+ */
+ public static void removeActionDefinition(
+ ServletRequest request,
+ ComponentDefinition definition) {
+
+ request.removeAttribute(ACTION_DEFINITION);
+ }
+
+ /**
+ * Populate Definition Factory Config from web.xml properties.
+ * @param factoryConfig Definition Factory Config to populate.
+ * @param servletConfig Current servlet config containing web.xml properties.
+ * @exception IllegalAccessException if the caller does not have
+ * access to the property accessor method
+ * @exception java.lang.reflect.InvocationTargetException if the property accessor method
+ * throws an exception
+ * @see org.apache.commons.beanutils.BeanUtils
+ * @since tiles 20020708
+ */
+ public static void populateDefinitionsFactoryConfig(
+ DefinitionsFactoryConfig factoryConfig,
+ ServletConfig servletConfig)
+ throws IllegalAccessException, InvocationTargetException {
+
+ Map properties = new DefinitionsUtil.ServletPropertiesMap(servletConfig);
+ System.out.println("Populating factory config with these properties: " + properties);
+ factoryConfig.populate(properties);
+ System.out.println("Done populating factory config");
+ }
+
+ /**
+ * Create FactoryConfig and initialize it from web.xml.
+ *
+ * @param servletConfig ServletConfig for the module with which
+ * this plug in is associated
+ * @exception DefinitionsFactoryException if this <code>PlugIn</code> cannot
+ * be successfully initialized
+ */
+ protected static DefinitionsFactoryConfig readFactoryConfig(ServletConfig servletConfig)
+ throws DefinitionsFactoryException {
+
+ // Create tiles definitions config object
+ DefinitionsFactoryConfig factoryConfig = new DefinitionsFactoryConfig();
+
+ // Get init parameters from web.xml files
+ try {
+ DefinitionsUtil.populateDefinitionsFactoryConfig(
+ factoryConfig,
+ servletConfig);
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new DefinitionsFactoryException(
+ "Can't populate DefinitionsFactoryConfig class from 'web.xml'.",
+ ex);
+ }
+
+ return factoryConfig;
+ }
+
+ /**
+ * Inner class.
+ * Wrapper for ServletContext init parameters.
+ * Object of this class is an hashmap containing parameters and values
+ * defined in the servlet config file (web.xml).
+ */
+ static class ServletPropertiesMap extends HashMap {
+ /**
+ * Constructor.
+ */
+ ServletPropertiesMap(ServletConfig config) {
+ // This implementation is very simple.
+ // It is possible to avoid creation of a new structure, but this need
+ // imply writing all Map interface.
+ System.out.println("Iterating over servlet parameters");
+ Enumeration names = config.getInitParameterNames();
+ while (names.hasMoreElements()) {
+ String key = (String) names.nextElement();
+ put(key, config.getInitParameter(key));
+ System.out.println("Storing key " + key);
+ }
+ }
+ } // end inner class
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DirectStringAttribute.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DirectStringAttribute.java
new file mode 100644
index 0000000..b975dd4
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/DirectStringAttribute.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+/**
+ * Component attribute.
+ * Such attribute value represent a path used to include a JSP.
+ */
+public class DirectStringAttribute extends UntypedAttribute {
+
+ public DirectStringAttribute(String value) {
+ super(value);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/FactoryNotFoundException.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/FactoryNotFoundException.java
new file mode 100644
index 0000000..b17b673
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/FactoryNotFoundException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+ /**
+ * Exception thrown when definitions factory is not found.
+ */
+public class FactoryNotFoundException extends DefinitionsFactoryException
+{
+ /**
+ * Constructor.
+ */
+ public FactoryNotFoundException()
+ {
+ super();
+ }
+ /**
+ * Constructor.
+ * @param msg Message.
+ */
+ public FactoryNotFoundException( String msg )
+ {
+ super(msg);
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/Globals.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/Globals.java
new file mode 100644
index 0000000..ed3ec85
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/Globals.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.Serializable;
+
+/**
+ * Global manifest constants for the entire Struts Framework.
+ *
+ * @author Craig R. McClanahan
+ * @author David Graham
+ * @author David Geary: migrated from struts package to eliminate Struts
+ * dependencies
+ */
+public class Globals implements Serializable {
+
+
+ // ----------------------------------------------------- Manifest Constants
+
+
+ /**
+ * The context attributes key under which our <code>ActionServlet</code>
+ * instance will be stored.
+ *
+ * @since Struts 1.1
+ */
+ public static final String ACTION_SERVLET_KEY =
+ "org.apache.tiles.action.ACTION_SERVLET";
+
+ /**
+ * The request attributes key under which a boolean <code>true</code>
+ * value should be stored if this request was cancelled.
+ *
+ * @since Struts 1.1
+ */
+ public static final String CANCEL_KEY =
+ "org.apache.tiles.action.CANCEL";
+
+ /**
+ * <p>The base of the context attributes key under which our
+ * <code>ModuleConfig</code> data structure will be stored. This
+ * will be suffixed with the actual module prefix (including the
+ * leading "/" character) to form the actual attributes key.</p>
+ *
+ * <p>For each request processed by the controller servlet, the
+ * <code>ModuleConfig</code> object for the module selected by
+ * the request URI currently being processed will also be exposed under
+ * this key as a request attribute.</p>
+ *
+ * @since Struts 1.1
+ */
+ public static final String MODULE_KEY =
+ "org.apache.tiles.action.MODULE";
+
+ /**
+ * The ServletContext attribute under which we store the module prefixes
+ * String[].
+ * @since Struts 1.2
+ */
+ public static final String MODULE_PREFIXES_KEY =
+ "org.apache.tiles.globals.MODULE_PREFIXES";
+
+
+ /**
+ * The context attributes key under which our <strong>default</strong>
+ * configured data source (which must implement
+ * <code>javax.sql.DataSource</code>) is stored,
+ * if one is configured for this module.
+ */
+ public static final String DATA_SOURCE_KEY =
+ "org.apache.tiles.action.DATA_SOURCE";
+
+
+ /**
+ * The request attributes key under which your action should store an
+ * <code>org.apache.tiles.action.ActionErrors</code> object, if you
+ * are using the corresponding custom tag library elements.
+ */
+ public static final String ERROR_KEY =
+ "org.apache.tiles.action.ERROR";
+
+
+ /**
+ * The request attributes key under which Struts custom tags might store a
+ * <code>Throwable</code> that caused them to report a JspException at
+ * runtime. This value can be used on an error page to provide more
+ * detailed information about what really went wrong.
+ */
+ public static final String EXCEPTION_KEY =
+ "org.apache.tiles.action.EXCEPTION";
+
+
+ /**
+ * The context attributes key under which our
+ * <code>org.apache.tiles.action.ActionFormBeans</code> collection
+ * is normally stored, unless overridden when initializing our
+ * ActionServlet.
+ *
+ * @deprecated Replaced by collection in ModuleConfig
+ */
+ public static final String FORM_BEANS_KEY =
+ "org.apache.tiles.action.FORM_BEANS";
+
+
+ /**
+ * The context attributes key under which our
+ * <code>org.apache.tiles.action.ActionForwards</code> collection
+ * is normally stored, unless overridden when initializing our
+ * ActionServlet.
+ *
+ * @deprecated Replaced by collection in ModuleConfig.
+ */
+ public static final String FORWARDS_KEY =
+ "org.apache.tiles.action.FORWARDS";
+
+
+ /**
+ * The session attributes key under which the user's selected
+ * <code>java.util.Locale</code> is stored, if any. If no such
+ * attribute is found, the system default locale
+ * will be used when retrieving internationalized messages. If used, this
+ * attribute is typically set during user login processing.
+ */
+ public static final String LOCALE_KEY =
+ "org.apache.tiles.action.LOCALE";
+
+
+ /**
+ * The request attributes key under which our
+ * <code>org.apache.tiles.ActionMapping</code> instance
+ * is passed.
+ */
+ public static final String MAPPING_KEY =
+ "org.apache.tiles.action.mapping.instance";
+
+
+ /**
+ * The context attributes key under which our
+ * <code>org.apache.tiles.action.ActionMappings</code> collection
+ * is normally stored, unless overridden when initializing our
+ * ActionServlet.
+ *
+ * @deprecated Replaced by collection in ModuleConfig
+ */
+ public static final String MAPPINGS_KEY =
+ "org.apache.tiles.action.MAPPINGS";
+
+
+ /**
+ * The request attributes key under which your action should store an
+ * <code>org.apache.tiles.action.ActionMessages</code> object, if you
+ * are using the corresponding custom tag library elements.
+ *
+ * @since Struts 1.1
+ */
+ public static final String MESSAGE_KEY =
+ "org.apache.tiles.action.ACTION_MESSAGE";
+
+
+ /**
+ * <p>The base of the context attributes key under which our
+ * module <code>MessageResources</code> will be stored. This
+ * will be suffixed with the actual module prefix (including the
+ * leading "/" character) to form the actual resources key.</p>
+ *
+ * <p>For each request processed by the controller servlet, the
+ * <code>MessageResources</code> object for the module selected by
+ * the request URI currently being processed will also be exposed under
+ * this key as a request attribute.</p>
+ */
+ public static final String MESSAGES_KEY =
+ "org.apache.tiles.action.MESSAGE";
+
+
+ /**
+ * The request attributes key under which our multipart class is stored.
+ */
+ public static final String MULTIPART_KEY =
+ "org.apache.tiles.action.mapping.multipartclass";
+
+
+ /**
+ * <p>The base of the context attributes key under which an array of
+ * <code>PlugIn</code> instances will be stored. This
+ * will be suffixed with the actual module prefix (including the
+ * leading "/" character) to form the actual attributes key.</p>
+ * @since Struts 1.1
+ */
+ public static final String PLUG_INS_KEY =
+ "org.apache.tiles.action.PLUG_INS";
+
+
+ /**
+ * <p>The base of the context attributes key under which our
+ * <code>RequestProcessor</code> instance will be stored. This
+ * will be suffixed with the actual module prefix (including the
+ * leading "/" character) to form the actual attributes key.</p>
+ * @since Struts 1.1
+ */
+ public static final String REQUEST_PROCESSOR_KEY =
+ "org.apache.tiles.action.REQUEST_PROCESSOR";
+
+
+ /**
+ * The context attributes key under which we store the mapping defined
+ * for our controller serlet, which will be either a path-mapped pattern
+ * (<code>/action/*</code>) or an extension mapped pattern
+ * (<code>*.do</code>).
+ */
+ public static final String SERVLET_KEY =
+ "org.apache.tiles.action.SERVLET_MAPPING";
+
+
+ /**
+ * The session attributes key under which our transaction token is
+ * stored, if it is used.
+ */
+ public static final String TRANSACTION_TOKEN_KEY =
+ "org.apache.tiles.action.TOKEN";
+
+ /**
+ * The page attributes key under which xhtml status is stored. This may be "true"
+ * or "false". When set to true, the html tags output xhtml.
+ * @since Struts 1.1
+ */
+ public static final String XHTML_KEY =
+ "org.apache.tiles.globals.XHTML";
+
+
+ /**
+ * The application-scope key whose value represents an
+ * exception thrown when Tiles parses the tile definition
+ * file(s).
+ */
+ public static final String TILES_INIT_EXCEPTION =
+ "org.apache.tiles.globals.TILES_INIT_EXCEPTION";
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/NoSuchDefinitionException.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/NoSuchDefinitionException.java
new file mode 100644
index 0000000..ed0c6b7
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/NoSuchDefinitionException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+ /**
+ * Exception thrown when a definition is not found.
+ */
+public class NoSuchDefinitionException extends DefinitionsFactoryException
+{
+ /**
+ * Constructor.
+ */
+ public NoSuchDefinitionException() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ * @param msg Message.
+ */
+ public NoSuchDefinitionException( String msg ) {
+ super(msg);
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/PathAttribute.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/PathAttribute.java
new file mode 100644
index 0000000..f4f9ae2
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/PathAttribute.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+/**
+ * Component attribute.
+ * Attribute value represents a path used to include a JSP.
+ */
+public class PathAttribute extends UntypedAttribute {
+
+ public PathAttribute(String value) {
+ super(value);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesException.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesException.java
new file mode 100644
index 0000000..b035ea7
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesException.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+/**
+ * Root class for all Tiles-exceptions.
+ * @author Cedric Dumoulin
+ */
+public class TilesException extends Exception
+{
+
+
+ /**
+ * Any "wrapped" exception will be exposed when this is serialized.
+ * @serial
+ */
+ private Exception exception;
+ /**
+ * Constructor.
+ */
+ public TilesException() {
+ super();
+ this.exception = null;
+ }
+
+ /**
+ * Constructor.
+ * @param message The error or warning message.
+ */
+ public TilesException(String message) {
+ super(message);
+ this.exception = null;
+ }
+
+
+ /**
+ * Create a new <code>TilesException</code> wrapping an existing exception.
+ *
+ * <p>The existing exception will be embedded in the new
+ * one, and its message will become the default message for
+ * the TilesException.</p>
+ *
+ * @param e The exception to be wrapped.
+ */
+ public TilesException(Exception e) {
+ super();
+ this.exception = e;
+ }
+
+
+ /**
+ * Create a new <code>TilesException</code> from an existing exception.
+ *
+ * <p>The existing exception will be embedded in the new
+ * one, but the new exception will have its own message.</p>
+ *
+ * @param message The detail message.
+ * @param e The exception to be wrapped.
+ */
+ public TilesException(String message, Exception e) {
+ super(message);
+ this.exception = e;
+ }
+
+
+ /**
+ * Return a detail message for this exception.
+ *
+ * <p>If there is a embedded exception, and if the TilesException
+ * has no detail message of its own, this method will return
+ * the detail message from the embedded exception.</p>
+ *
+ * @return The error or warning message.
+ */
+ public String getMessage () {
+ String message = super.getMessage ();
+
+ if (message == null && exception != null) {
+ return exception.getMessage();
+ } else {
+ return message;
+ }
+ }
+
+
+ /**
+ * Return the embedded exception, if any.
+ *
+ * @return The embedded exception, or <code>null</code> if there is none.
+ */
+ public Exception getException () {
+ return exception;
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtil.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtil.java
new file mode 100644
index 0000000..2c91bd4
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtil.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Class containing utility methods for Tiles.
+ * Methods of this class are static and thereby accessible from anywhere.
+ * The underlying implementation can be changed with
+ * {@link #setTilesUtil(TilesUtilImpl)}.
+ * <br>
+ * Real implementation classes should derive from the {@link TilesUtilImpl} class.
+ * <br>
+ * Some methods are specified to throw the <code>UnsupportedOperationException</code>
+ * if the underlying implementation doesn't support the operation.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ */
+public class TilesUtil {
+ /** Commons Logging instance.*/
+ protected static Log log = LogFactory.getLog(TilesUtil.class);
+
+ /** The implementation of tilesUtilImpl */
+ protected static TilesUtilImpl tilesUtilImpl = new TilesUtilImpl();
+
+ /**
+ * Get the real implementation.
+ * @return The underlying implementation object.
+ */
+ static public TilesUtilImpl getTilesUtil() {
+ return tilesUtilImpl;
+ }
+
+ /**
+ * Set the real implementation.
+ * This method should be called only once.
+ * Successive calls have no effect.
+ * @param tilesUtil The implementaion.
+ */
+ static public void setTilesUtil(TilesUtilImpl tilesUtil) {
+ if (implAlreadySet) {
+ return;
+ }
+ tilesUtilImpl = tilesUtil;
+ implAlreadySet = true;
+ }
+
+ /**
+ * Getter to know if the underlying implementation is already set to another
+ * value than the default value.
+ * @return <code>true</code> if {@link #setTilesUtil} has already been called.
+ */
+ static boolean isTilesUtilImplSet() {
+ return implAlreadySet;
+ }
+
+ /** Flag to know if internal implementation has been set by the setter method */
+ private static boolean implAlreadySet = false;
+
+ /**
+ * Do a forward using request dispatcher.
+ *
+ * This method is used by the Tiles package anytime a forward is required.
+ * @param uri Uri or Definition name to forward.
+ * @param request Current page request.
+ * @param response Current page response.
+ * @param servletContext Current servlet context.
+ */
+ public static void doForward(
+ String uri,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ServletContext servletContext)
+ throws IOException, ServletException {
+
+ tilesUtilImpl.doForward(uri, request, response, servletContext);
+ }
+
+ /**
+ * Do an include using request dispatcher.
+ *
+ * This method is used by the Tiles package when an include is required.
+ * The Tiles package can use indifferently any form of this method.
+ * @param uri Uri or Definition name to forward.
+ * @param request Current page request.
+ * @param response Current page response.
+ * @param servletContext Current servlet context.
+ */
+ public static void doInclude(
+ String uri,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ServletContext servletContext)
+ throws IOException, ServletException {
+
+ tilesUtilImpl.doInclude(uri, request, response, servletContext);
+ }
+
+ /**
+ * Do an include using PageContext.include().
+ *
+ * This method is used by the Tiles package when an include is required.
+ * The Tiles package can use indifferently any form of this method.
+ * @param uri Uri or Definition name to forward.
+ * @param request Current page request.
+ * @param response Current page response.
+ * @param servletContext Current servlet context.
+ */
+ public static void doInclude(String uri, PageContext pageContext)
+ throws IOException, ServletException {
+ TilesUtilImpl.doInclude(uri, pageContext);
+ }
+
+ /**
+ * Get definition factory from appropriate servlet context.
+ * @return Definitions factory or <code>null</code> if not found.
+ */
+ public static DefinitionsFactory getDefinitionsFactory(
+ ServletRequest request,
+ ServletContext servletContext) {
+ return tilesUtilImpl.getDefinitionsFactory(request, servletContext);
+ }
+
+ /**
+ * Create Definition factory from specified configuration object.
+ * Create a ConfigurableDefinitionsFactory and initialize it with the configuration
+ * object. This later can contain the factory classname to use.
+ * Factory is made accessible from tags.
+ * <p>
+ * Fallback of several factory creation methods.
+ *
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param factoryConfig Configuration object passed to factory.
+ * @return newly created factory of type ConfigurableDefinitionsFactory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ public static DefinitionsFactory createDefinitionsFactory(
+ ServletContext servletContext,
+ DefinitionsFactoryConfig factoryConfig)
+ throws DefinitionsFactoryException {
+ return tilesUtilImpl.createDefinitionsFactory(servletContext, factoryConfig);
+ }
+
+ /**
+ * Get a definition by its name.
+ * First, retrieve definition factory and then get requested definition.
+ * Throw appropriate exception if definition or definition factory is not found.
+ * @param definitionName Name of requested definition.
+ * @param request Current servelet request.
+ * @param servletContext current servlet context.
+ * @throws FactoryNotFoundException Can't find definition factory.
+ * @throws DefinitionsFactoryException General error in factory while getting definition.
+ * @throws NoSuchDefinitionException No definition found for specified name
+ */
+ public static ComponentDefinition getDefinition(
+ String definitionName,
+ ServletRequest request,
+ ServletContext servletContext)
+ throws FactoryNotFoundException, DefinitionsFactoryException {
+
+ try {
+ return getDefinitionsFactory(request, servletContext).getDefinition(
+ definitionName,
+ (HttpServletRequest) request,
+ servletContext);
+
+ } catch (NullPointerException ex) { // Factory not found in context
+ System.out.println("Couldn't find the Tiles definition factory");
+ throw new FactoryNotFoundException("Can't get definitions factory from context.");
+ }
+ }
+
+
+
+ /**
+ * Reset internal state.
+ * This method is used by test suites to reset the class to its original state.
+ */
+ protected static void testReset() {
+ implAlreadySet = false;
+ tilesUtilImpl = new TilesUtilImpl();
+ }
+
+ /**
+ * DG: I moved this method from org.apache.struts.util.RequestUtils
+ * to remove that dependency on Struts
+ *
+ * Return the <code>Class</code> object for the specified fully qualified
+ * class name, from this web application's class loader.
+ *
+ * @param className Fully qualified class name to be loaded
+ * @return Class object
+ * @exception ClassNotFoundException if the class cannot be found
+ */
+ public static Class applicationClass(String className)
+ throws ClassNotFoundException {
+ // Look up the class loader to be used
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = TilesUtil.class.getClassLoader();
+ }
+ // Attempt to load the specified class
+ return (classLoader.loadClass(className));
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtilImpl.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtilImpl.java
new file mode 100644
index 0000000..e9b8370
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtilImpl.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.PageContext;
+
+import java.util.logging.Logger;
+import org.apache.tiles.definition.ComponentDefinitionsFactoryWrapper;
+
+// DG: removed dependency to RequestUtils
+// import org.apache.util.RequestUtils;
+
+/**
+ * Default implementation of TilesUtil.
+ * This class contains default implementation of utilities. This implementation
+ * is intended to be used without Struts.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ */
+public class TilesUtilImpl implements Serializable {
+
+ /** Commons Logging instance.*/
+ protected Logger logger = Logger.getLogger(TilesUtil.class.getName());
+
+ /** Constant name used to store factory in servlet context */
+ public static final String DEFINITIONS_FACTORY =
+ "org.apache.tiles.DEFINITIONS_FACTORY";
+
+ /**
+ * Do a forward using request dispatcher.
+ *
+ * This method is used by the Tiles package anytime a forward is required.
+ * @param uri Uri or Definition name to forward.
+ * @param request Current page request.
+ * @param servletContext Current servlet context.
+ */
+ public void doForward(
+ String uri,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ServletContext servletContext)
+ throws IOException, ServletException {
+
+ request.getRequestDispatcher(uri).forward(request, response);
+ }
+
+ /**
+ * Do an include using request dispatcher.
+ *
+ * This method is used by the Tiles package when an include is required.
+ * The Tiles package can use indifferently any form of this method.
+ * @param uri Uri or Definition name to forward.
+ * @param request Current page request.
+ * @param response Current page response.
+ * @param servletContext Current servlet context.
+ */
+ public void doInclude(
+ String uri,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ ServletContext servletContext)
+ throws IOException, ServletException {
+
+ request.getRequestDispatcher(uri).include(request, response);
+ }
+
+ /**
+ * Do an include using PageContext.include().
+ *
+ * This method is used by the Tiles package when an include is required.
+ * The Tiles package can use indifferently any form of this method.
+ * @param uri Uri or Definition name to forward.
+ * @param request Current page request.
+ * @param response Current page response.
+ * @param servletContext Current servlet context.
+ */
+ public static void doInclude(String uri, PageContext pageContext)
+ throws IOException, ServletException {
+
+ pageContext.include(uri);
+ }
+
+ /**
+ * Get definition factory from appropriate servlet context.
+ * @return Definitions factory or <code>null</code> if not found.
+ */
+ public DefinitionsFactory getDefinitionsFactory(
+ ServletRequest request,
+ ServletContext servletContext) {
+
+ return (DefinitionsFactory) servletContext.getAttribute(DEFINITIONS_FACTORY);
+ }
+
+ /**
+ * Create Definition factory from specified configuration object.
+ * Create an instance of the factory with the class specified in the config
+ * object. Then, initialize this factory and finally store the factory in
+ * appropriate context by calling
+ * {@link #makeDefinitionsFactoryAccessible(DefinitionsFactory, ServletContext)}.
+ * Factory creation is done by {@link #createDefinitionFactoryInstance(String)}.
+ * <p>
+ *
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param factoryConfig Configuration object passed to factory.
+ * @return newly created factory of type specified in the config object.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ public DefinitionsFactory createDefinitionsFactory(
+ ServletContext servletContext,
+ DefinitionsFactoryConfig factoryConfig)
+ throws DefinitionsFactoryException {
+
+ // Create configurable factory
+ DefinitionsFactory factory =
+ createDefinitionFactoryInstance(factoryConfig.getFactoryClassname());
+
+ logger.info("Initializing Tile definition factory");
+ try {
+ factory.init(factoryConfig, servletContext);
+ }
+ catch(Exception ex) {
+ logger.info("CAUGHT TILES FACTORY INITIALIZATION ERROR: " + ex.toString());
+ throw new DefinitionsFactoryException(ex.getMessage());
+ }
+
+ logger.info("Making factory accessible to JSP tags");
+ // Make factory accessible from jsp tags (push it in appropriate context)
+ makeDefinitionsFactoryAccessible(factory, servletContext);
+ return factory;
+ }
+
+ /**
+ * Create Definition factory of specified classname.
+ * Factory class must extend the {@link DefinitionsFactory} class.
+ * The factory is wrapped appropriately with {@link DefinitionsFactory}
+ * if it is an instance of the deprecated DefinitionsFactory class.
+ * @param classname Class name of the factory to create.
+ * @return newly created factory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ protected DefinitionsFactory createDefinitionFactoryInstance(String classname)
+ throws DefinitionsFactoryException {
+
+ logger.info("Creating Tiles definition factory");
+ try {
+ Class factoryClass = TilesUtil.applicationClass(classname);
+ System.out.println("factory class: " + factoryClass);
+ Object factory = factoryClass.newInstance();
+
+ // Backward compatibility : if factory classes implements old interface,
+ // provide appropriate wrapper
+ if (factory instanceof ComponentDefinitionsFactory) {
+ factory =
+ new ComponentDefinitionsFactoryWrapper(
+ (ComponentDefinitionsFactory) factory);
+ }
+ return (DefinitionsFactory) factory;
+
+ } catch (ClassCastException ex) { // Bad classname
+ System.out.println("CLASS CAST EXCEPTION");
+ throw new DefinitionsFactoryException(
+ "Error - createDefinitionsFactory : Factory class '"
+ + classname
+ + " must implement 'TilesDefinitionsFactory'.",
+ ex);
+
+ } catch (ClassNotFoundException ex) { // Bad classname
+ System.out.println("CLASS NOT FOUND EXCEPTION");
+ throw new DefinitionsFactoryException(
+ "Error - createDefinitionsFactory : Bad class name '"
+ + classname
+ + "'.",
+ ex);
+
+ } catch (InstantiationException ex) { // Bad constructor or error
+ System.out.println("INSTANTIATION EXCEPTION");
+ throw new DefinitionsFactoryException(ex);
+
+ } catch (IllegalAccessException ex) {
+ System.out.println("ILLEGAL ACCESS EXCEPTION");
+ throw new DefinitionsFactoryException(ex);
+
+ } catch (Exception ex) {
+ System.out.println("EXCEPTION: " + ex.getClass().getName());
+ ex.printStackTrace();
+ throw new DefinitionsFactoryException(ex);
+ }
+ }
+
+ /**
+ * Make definition factory accessible to Tags.
+ * Factory is stored in servlet context.
+ * @param factory Factory to be made accessible.
+ * @param servletContext Current servlet context.
+ */
+ protected void makeDefinitionsFactoryAccessible(
+ DefinitionsFactory factory,
+ ServletContext servletContext) {
+
+ servletContext.setAttribute(DEFINITIONS_FACTORY, factory);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtilStrutsImpl.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtilStrutsImpl.java
new file mode 100644
index 0000000..6ceff04
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/TilesUtilStrutsImpl.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+
+import javax.servlet.ServletContext;
+
+/**
+ * TilesUtil implementation for Struts 1.1 with one single factory.
+ * This class contains default implementation of utilities. This implementation
+ * is intended to be used with Struts 1.1.
+ * This class is used as the base class for all Struts 1.1 implementations of TilesUtil.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ */
+public class TilesUtilStrutsImpl extends TilesUtilImpl {
+
+ /**
+ * Get definition factory for the module attached to the specified moduleConfig.
+ * @param servletContext Current servlet context
+ * @param moduleConfig Module config of the module for which the factory is requested.
+ * @return Definitions factory or null if not found.
+ */
+ public DefinitionsFactory getDefinitionsFactory(ServletContext servletContext) {
+ return (DefinitionsFactory) servletContext.getAttribute(DEFINITIONS_FACTORY);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/UntypedAttribute.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/UntypedAttribute.java
new file mode 100644
index 0000000..ef37d8f
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/UntypedAttribute.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+/**
+ * Common implementation of attribute definition.
+ */
+public class UntypedAttribute implements AttributeDefinition {
+
+ /**
+ * Role associated with this attribute.
+ */
+ protected String role = null;
+
+ protected Object value=null;
+
+ /**
+ * Constructor.
+ * @param value Object to store.
+ */
+ public UntypedAttribute(Object value) {
+ this.value = value;
+ }
+
+ /**
+ * Constructor.
+ * @param value Object to store.
+ * @param role Asociated role.
+ */
+ public UntypedAttribute(Object value, String role) {
+ this.value = value;
+ this.role = role;
+ }
+
+ /**
+ * Get role.
+ */
+ public String getRole() {
+ return role;
+ }
+
+ /**
+ * Set role.
+ * @param role Associated role.
+ */
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ /**
+ * Get value.
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * Set value.
+ * @param value New value.
+ */
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ /**
+ * Get String representation of this object.
+ */
+ public String toString() {
+ return value.toString();
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/UrlController.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/UrlController.java
new file mode 100644
index 0000000..657e930
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/UrlController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles;
+
+import java.io.IOException;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Tiles controller including a local URL.
+ * @author Cedric Dumoulin
+ */
+
+public class UrlController implements Controller {
+
+ /** Url associated with this controller. */
+ protected String url;
+
+ /**
+ * Constructor.
+ * @param url URL.
+ */
+ public UrlController( String url ) {
+ this.url=url;
+ }
+
+ /**
+ * Method associated to a tile and called immediately before the tile is included.
+ * This implementation calls a Struts Action. No servlet is set by this method.
+ *
+ * @param tileContext Current tile context.
+ * @param request Current request.
+ * @param response Current response.
+ * @param servletContext Current servlet context.
+ */
+ public void perform(ComponentContext tileContext,
+ HttpServletRequest request, HttpServletResponse response,
+ ServletContext servletContext)
+ throws ServletException, IOException {
+ RequestDispatcher rd = servletContext.getRequestDispatcher( url );
+ if( rd == null )
+ throw new ServletException( "Controller can't find url '" + url + "'." );
+
+ rd.include( request, response );
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/beans/MenuItem.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/beans/MenuItem.java
new file mode 100644
index 0000000..5942591
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/beans/MenuItem.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.beans;
+
+import java.io.Serializable;
+
+/**
+ * Interface for MenuItems.
+ * @see SimpleMenuItem
+ */
+public interface MenuItem extends Serializable {
+
+ /**
+ * Set value property.
+ */
+ public void setValue(String value);
+
+ /**
+ * Get value property.
+ */
+ public String getValue();
+
+ /**
+ * Set link property.
+ */
+ public void setLink(String link);
+
+ /**
+ * Get link property.
+ */
+ public String getLink();
+
+ /**
+ * Set icon property.
+ */
+ public void setIcon(String link);
+
+ /**
+ * Get icon property.
+ */
+ public String getIcon();
+
+ /**
+ * Set tooltip property.
+ */
+ public void setTooltip(String link);
+
+ /**
+ * Get tooltip property.
+ */
+ public String getTooltip();
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/beans/SimpleMenuItem.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/beans/SimpleMenuItem.java
new file mode 100644
index 0000000..f2b027a
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/beans/SimpleMenuItem.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.beans;
+
+import java.io.Serializable;
+
+/**
+ * A MenuItem implementation.
+ * Used to read menu items in definitions.
+ */
+public class SimpleMenuItem implements MenuItem, Serializable {
+
+ private String value = null;
+
+ private String link = null;
+
+ private String icon = null;
+
+ private String tooltip = null;
+
+ /**
+ * Constructor.
+ */
+ public SimpleMenuItem() {
+ super();
+ }
+
+ /**
+ * Set value property.
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Get value property.
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Set link property.
+ */
+ public void setLink(String link) {
+ this.link = link;
+ }
+
+ /**
+ * Get link property.
+ */
+ public String getLink() {
+ return link;
+ }
+
+ /**
+ * Set icon property.
+ */
+ public void setIcon(String icon) {
+ this.icon = icon;
+ }
+
+ /**
+ * Get icon property.
+ */
+ public String getIcon() {
+ return icon;
+ }
+
+ /**
+ * Set tooltip property.
+ */
+ public void setTooltip(String tooltip) {
+ this.tooltip = tooltip;
+ }
+
+ /**
+ * Get tooltip property.
+ */
+ public String getTooltip() {
+ return tooltip;
+ }
+
+ /**
+ * Return String representation.
+ */
+ public String toString() {
+ StringBuffer buff = new StringBuffer("SimpleMenuItem[");
+
+ if (getValue() != null) {
+ buff.append("value=").append(getValue()).append(", ");
+ }
+
+ if (getLink() != null) {
+ buff.append("link=").append(getLink()).append(", ");
+ }
+
+ if (getTooltip() != null) {
+ buff.append("tooltip=").append(getTooltip()).append(", ");
+ }
+
+ if (getIcon() != null) {
+ buff.append("icon=").append(getIcon()).append(", ");
+ }
+
+ buff.append("]");
+ return buff.toString();
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/definition/ComponentDefinitionsFactoryWrapper.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/definition/ComponentDefinitionsFactoryWrapper.java
new file mode 100644
index 0000000..4cb9771
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/definition/ComponentDefinitionsFactoryWrapper.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.definition;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.ComponentDefinitionsFactory;
+import org.apache.tiles.DefinitionsFactory;
+import org.apache.tiles.DefinitionsFactoryConfig;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.NoSuchDefinitionException;
+import org.apache.tiles.TilesUtil;
+
+/**
+ * Wrapper from new definition factory interface to old interface.
+ * This class provides mapping from the old interface's life cycle to the new life cycle.
+ * @author Cedric Dumoulin
+ * @author David Geary
+ * @since 20020708
+ */
+public class ComponentDefinitionsFactoryWrapper implements DefinitionsFactory {
+
+ /**
+ * The underlying factory.
+ */
+ private ComponentDefinitionsFactory factory = null;
+
+ /**
+ * Factory configuration,
+ */
+ private DefinitionsFactoryConfig config = null;
+
+ /**
+ * Constructor.
+ * Create new wrapper for specified factory.
+ * @param factory The factory to create a wrapper for.
+ */
+ public ComponentDefinitionsFactoryWrapper(ComponentDefinitionsFactory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * Constructor.
+ * Create new wrapper.
+ * The config object passed to init method should reference a factory implementing
+ * {@link ComponentDefinitionsFactory}.
+ */
+ public ComponentDefinitionsFactoryWrapper() {
+ super();
+ }
+
+ /**
+ * Get requested definition.
+ * @param name Name of the definition.
+ * @param request The request we are processing.
+ * @param servletContext Our servlet context.
+ * @return ComponentDefition
+ */
+ public ComponentDefinition getDefinition(
+ String name,
+ ServletRequest request,
+ ServletContext servletContext)
+ throws NoSuchDefinitionException, DefinitionsFactoryException {
+
+ return factory.getDefinition(name, request, servletContext);
+ }
+
+ /**
+ * Call underlying factory init method.
+ * @param config DefinitionsFactoryConfig.
+ * @param servletContext Our servlet context.
+ */
+ public void init(DefinitionsFactoryConfig config, ServletContext servletContext)
+ throws DefinitionsFactoryException {
+
+ this.config = config;
+
+ // create factory and initialize it
+ if (factory == null) {
+ factory = createFactoryInstance(config.getFactoryClassname());
+ }
+
+ factory.initFactory(servletContext, createConfigMap(config));
+ }
+
+ /**
+ * Do nothing because old life cycle has no equivalent.
+ */
+ public void destroy() {
+ factory = null;
+ }
+
+ /**
+ * Set underlying factory configuration.
+ * @param config DefinitionsFactoryConfig to use.
+ * @param servletContext Our servlet context.
+ *
+ */
+ public void setConfig(
+ DefinitionsFactoryConfig config,
+ ServletContext servletContext)
+ throws DefinitionsFactoryException {
+
+ ComponentDefinitionsFactory newFactory =
+ createFactoryInstance(config.getFactoryClassname());
+
+ newFactory.initFactory(servletContext, createConfigMap(config));
+ factory = newFactory;
+ }
+
+ /**
+ * Get underlying factory configuration.
+ * @return DefinitionsFactoryConfig.
+ */
+ public DefinitionsFactoryConfig getConfig() {
+ return config;
+ }
+
+ /**
+ * Get internal factory.
+ * @return The internal ComponentDefitionsFactory.
+ */
+ public ComponentDefinitionsFactory getInternalFactory() {
+ return factory;
+ }
+
+ /**
+ * Create Definition factory from provided classname which must implement {@link ComponentDefinitionsFactory}.
+ * Factory class must extend {@link DefinitionsFactory}.
+ * @param classname Class name of the factory to create.
+ * @return newly created factory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ protected ComponentDefinitionsFactory createFactoryInstance(String classname)
+ throws DefinitionsFactoryException {
+
+ try {
+ Class factoryClass = TilesUtil.applicationClass(classname);
+ Object factory = factoryClass.newInstance();
+ return (ComponentDefinitionsFactory) factory;
+
+ } catch (ClassCastException ex) { // Bad classname
+ throw new DefinitionsFactoryException(
+ "Error - createDefinitionsFactory : Factory class '"
+ + classname
+ + " must implement 'DefinitionsFactory'.",
+ ex);
+
+ } catch (ClassNotFoundException ex) { // Bad classname
+ throw new DefinitionsFactoryException(
+ "Error - createDefinitionsFactory : Bad class name '"
+ + classname
+ + "'.",
+ ex);
+
+ } catch (InstantiationException ex) { // Bad constructor or error
+ throw new DefinitionsFactoryException(ex);
+
+ } catch (IllegalAccessException ex) {
+ throw new DefinitionsFactoryException(ex);
+ }
+
+ }
+
+ /**
+ * Return String representation.
+ * Calls toString() on underlying factory.
+ * @return String representation.
+ */
+ public String toString() {
+ return getInternalFactory().toString();
+ }
+
+ /**
+ * Create map of configuration attributes from configuration object.
+ * Mapping is done between old names and new names.
+ * @param config The DefinitionsFactoryConfig to use.
+ * @return Map Map of name/value pairs.
+ */
+ public static Map createConfigMap(DefinitionsFactoryConfig config) {
+ Map map = new HashMap(config.getAttributes());
+ // Add property attributes using old names
+ map.put(
+ DefinitionsFactoryConfig.DEFINITIONS_CONFIG_PARAMETER_NAME,
+ config.getDefinitionConfigFiles());
+
+ map.put(
+ DefinitionsFactoryConfig.PARSER_VALIDATE_PARAMETER_NAME,
+ new Boolean(config.getParserValidate()).toString());
+
+ if (!"org.apache.tiles.xmlDefinition.I18nFactorySet"
+ .equals(config.getFactoryClassname())) {
+
+ map.put(
+ DefinitionsFactoryConfig.FACTORY_CLASSNAME_PARAMETER_NAME,
+ config.getFactoryClassname());
+ }
+
+ return map;
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/definition/ReloadableDefinitionsFactory.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/definition/ReloadableDefinitionsFactory.java
new file mode 100644
index 0000000..7ebf20a
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/definition/ReloadableDefinitionsFactory.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.definition;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.ComponentDefinitionsFactory;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.FactoryNotFoundException;
+import org.apache.tiles.xmlDefinition.I18nFactorySet;
+import org.apache.tiles.TilesUtil;
+
+/**
+ * A reloadable factory.
+ * This factory is the main entrance to any factory implementation. It takes in
+ * charge real implementation instance, and allows reloading by creating a new
+ * instance.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ * @since Struts 1.1
+ * @version $Revision: 1.8 $ $Date: 2003/07/09 00:14:01 $
+ */
+public class ReloadableDefinitionsFactory implements ComponentDefinitionsFactory {
+
+ /**
+ * The real factory instance.
+ */
+ protected ComponentDefinitionsFactory factory = null;
+
+ /**
+ * Initialization parameters.
+ */
+ protected Map properties = null;
+
+ /**
+ * Name of init property carrying factory class name.
+ */
+ public static final String DEFINITIONS_FACTORY_CLASSNAME =
+ "definitions-factory-class";
+
+ /**
+ * Constructor.
+ * Create a factory according to servlet settings.
+ * @param servletContext Our servlet context.
+ * @param servletConfig Our servlet config.
+ * @throws DefinitionsFactoryException If factory creation fail.
+ */
+ public ReloadableDefinitionsFactory(
+ ServletContext servletContext,
+ ServletConfig servletConfig)
+ throws DefinitionsFactoryException {
+
+ properties = new ServletPropertiesMap(servletConfig);
+ factory = createFactory(servletContext, properties);
+ }
+
+ /**
+ * Constructor.
+ * Create a factory according to servlet settings.
+ * @param servletContext Our servlet context.
+ * @param properties Map containing all properties.
+ * @throws DefinitionsFactoryException If factory creation fail.
+ */
+ public ReloadableDefinitionsFactory(
+ ServletContext servletContext,
+ Map properties)
+ throws DefinitionsFactoryException {
+
+ this.properties = properties;
+ factory = createFactory(servletContext, properties);
+ }
+
+ /**
+ * Create Definition factory from provided classname.
+ * If a factory class name is provided, a factory of this class is created. Otherwise,
+ * a default factory is created.
+ * Factory must have a constructor taking ServletContext and Map as parameter.
+ * @param classname Class name of the factory to create.
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property passed to newly created factory.
+ * @return newly created factory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ public ComponentDefinitionsFactory createFactoryFromClassname(
+ ServletContext servletContext,
+ Map properties,
+ String classname)
+ throws DefinitionsFactoryException {
+
+ if (classname == null) {
+ return createFactory(servletContext, properties);
+ }
+
+ // Try to create from classname
+ try {
+ Class factoryClass = TilesUtil.applicationClass(classname);
+ ComponentDefinitionsFactory factory =
+ (ComponentDefinitionsFactory) factoryClass.newInstance();
+ factory.initFactory(servletContext, properties);
+ return factory;
+
+ } catch (ClassCastException ex) { // Bad classname
+ throw new DefinitionsFactoryException(
+ "Error - createDefinitionsFactory : Factory class '"
+ + classname
+ + " must implements 'ComponentDefinitionsFactory'.",
+ ex);
+
+ } catch (ClassNotFoundException ex) { // Bad classname
+ throw new DefinitionsFactoryException(
+ "Error - createDefinitionsFactory : Bad class name '"
+ + classname
+ + "'.",
+ ex);
+
+ } catch (InstantiationException ex) { // Bad constructor or error
+ throw new DefinitionsFactoryException(ex);
+
+ } catch (IllegalAccessException ex) {
+ throw new DefinitionsFactoryException(ex);
+ }
+
+ }
+
+ /**
+ * Create default Definition factory.
+ * Factory must have a constructor taking ServletContext and Map as parameter.
+ * In this implementation, default factory is of class I18nFactorySet
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property passed to newly created factory.
+ * @return newly created factory.
+ * @throws DefinitionsFactoryException If an error occur while initializing factory
+ */
+ public ComponentDefinitionsFactory createDefaultFactory(
+ ServletContext servletContext,
+ Map properties)
+ throws DefinitionsFactoryException {
+
+ ComponentDefinitionsFactory factory =
+ new I18nFactorySet(servletContext, properties);
+
+ return factory;
+ }
+
+ /**
+ * Create Definition factory.
+ * Convenience method. ServletConfig is wrapped into a Map allowing retrieval
+ * of init parameters. Factory classname is also retrieved, as well as debug level.
+ * Finally, approriate createDefinitionsFactory() is called.
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map containing all properties.
+ */
+ public ComponentDefinitionsFactory createFactory(
+ ServletContext servletContext,
+ Map properties)
+ throws DefinitionsFactoryException {
+
+ String classname = (String) properties.get(DEFINITIONS_FACTORY_CLASSNAME);
+
+ if (classname != null) {
+ return createFactoryFromClassname(servletContext, properties, classname);
+ }
+
+ return new I18nFactorySet(servletContext, properties);
+ }
+
+ /**
+ * Get a definition by its name.
+ * Call appropriate method on underlying factory instance.
+ * Throw appropriate exception if definition or definition factory is not found.
+ * @param definitionName Name of requested definition.
+ * @param request Current servlet request.
+ * @param servletContext Current servlet context.
+ * @throws FactoryNotFoundException Can't find definition factory.
+ * @throws DefinitionsFactoryException General error in factory while getting definition.
+ */
+ public ComponentDefinition getDefinition(
+ String definitionName,
+ ServletRequest request,
+ ServletContext servletContext)
+ throws FactoryNotFoundException, DefinitionsFactoryException {
+
+ return factory.getDefinition(
+ definitionName,
+ (HttpServletRequest) request,
+ servletContext);
+ }
+
+ /**
+ * Reload underlying factory.
+ * Reload is done by creating a new factory instance, and replacing the old instance
+ * with the new one.
+ * @param servletContext Current servlet context.
+ * @throws DefinitionsFactoryException If factory creation fails.
+ */
+ public void reload(ServletContext servletContext)
+ throws DefinitionsFactoryException {
+
+ ComponentDefinitionsFactory newInstance =
+ createFactory(servletContext, properties);
+
+ factory = newInstance;
+ }
+
+ /**
+ * Get underlying factory instance.
+ * @return ComponentDefinitionsFactory
+ */
+ public ComponentDefinitionsFactory getFactory() {
+ return factory;
+ }
+
+ /**
+ * Init factory.
+ * This method is required by interface ComponentDefinitionsFactory. It is
+ * not used in this implementation, as it manages itself the underlying creation
+ * and initialization.
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property passed to newly created factory.
+ * Map can contain more properties than requested.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ public void initFactory(ServletContext servletContext, Map properties)
+ throws DefinitionsFactoryException {
+ // do nothing
+ }
+
+ /**
+ * Return String representation.
+ * @return String representation.
+ */
+ public String toString() {
+ return factory.toString();
+ }
+
+ /**
+ * Inner class.
+ * Wrapper for ServletContext init parameters.
+ * Object of this class is an HashMap containing parameters and values
+ * defined in the servlet config file (web.xml).
+ */
+ class ServletPropertiesMap extends HashMap {
+ /**
+ * Constructor.
+ */
+ ServletPropertiesMap(ServletConfig config) {
+ // This implementation is very simple.
+ // It is possible to avoid creation of a new structure, but this would
+ // imply writing all of the Map interface.
+ Enumeration names = config.getInitParameterNames();
+ while (names.hasMoreElements()) {
+ String key = (String) names.nextElement();
+ put(key, config.getInitParameter(key));
+ }
+ }
+ } // end inner class
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/doc-files/image001.gif b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/doc-files/image001.gif
new file mode 100644
index 0000000..f675c12
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/doc-files/image001.gif
Binary files differ
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/doc-files/tilesUML.gif b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/doc-files/tilesUML.gif
new file mode 100644
index 0000000..d444822
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/doc-files/tilesUML.gif
Binary files differ
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/package.html b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/package.html
new file mode 100644
index 0000000..8b6f709
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/package.html
@@ -0,0 +1,323 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html lang="en">
+<head>
+<title>Tiles Package</title>
+</head>
+<body>
+<div class="mainContent">
+ The Tiles taglib and framework allows building web pages by assembling reusable
+ pieces of pages, called Tiles. A Tiles is usually a simple JSP page.
+<img src="doc-files/tilesUML.gif" alt="TagLib Tiles UML">
+
+<div class="section">
+<h2>Introduction</h2>
+ <p>The Tiles framework allows building pages by assembling reusable Tiles.
+ As an example, the page in the next figure can be build by assembling a
+ header, a footer, a menu and a body.</p>
+ <p><img src="doc-files/image001.gif" height="169" width="145" alt="doc-files/image001"></p>
+ <p>Each Tiles (header, menu, body, ...) is a JSP page and can itself be build
+ by assembling other Tiles.</p>
+<p>Using Tiles can be compared as using Java methods: You need to define the Tiles (the method body), and then you can "call" this body anywhere you want, passing it some parameters. In Tiles, parameters are called "attributes" in order to avoid confusion with the request parameters.</p>
+ <p>The Tiles body can be a simple JSP page, a Struts action or any URI pointing
+ to a resource inside the current web site.</p>
+ <p>Inserting the body, or calling it, is done with the tag <tiles:insert
+ ...> anywhere in a JSP page. Insertion can also be done by specifying
+ a <em>definition name </em>as the path of a Struts forward or as input,
+ forward or include attributes of a Struts action.</p>
+ <p>Tiles bodies are used to create layouts, reusable parts, ... Tiles insertions
+ are used to insert Tiles. The same Tiles can be reused several times in
+ the same site, or even in the same page.</p>
+<p>Insertion of a Tiles body can be associated to a logical name in what Tiles calls a "definition". A definition contains a logical name, a page used as body and some attribute values. The definition declaration doesn't insert the associated Tiles body. It just associates it with the name. A definition name can be used anywhere insertion of a Tiles body can occur. The associated Tiles body is then inserted with associated attributes.</p>
+ <p>The definition declarations can be done in JSP pages or in one or more
+ centralized files. A definition can extend another one, overload some attributes,
+ add new attributes ... This allows the declaration of a "master" definition
+ declaring the common layout, header, menu and footer. All other definitions
+ extend this master layout thereby making it possible to change the entire
+ site look & feel simply by changing the master definition. </p>
+</div>
+<div class="section">
+<h2>Simple Examples</h2>
+<div class="subsection1">
+ <h3>Insert a JSP page</h3>
+ <pre><tiles:insert <strong>page</strong>="/layouts/commonLayout.jsp" flush="true" />
+</pre>
+<p>This example inserts the specified page in place of the tag. The page attribute is any valid URL pointing to a resource inside the current site.</p>
+</div>
+<div class="subsection1">
+<a name="doc.InsertPageWithAttributes">
+<h3>Insert a Tiles passing some attributes</h3>
+<pre>
+<tiles:insert page="/layouts/classicLayout.jsp" flush="true">
+ <tiles:put name="title" value="Page Title" />
+ <tiles:put name="header" value="/common/header.jsp" />
+ <tiles:put name="footer" value="/common/footer.jsp" />
+ <tiles:put name="menu" value="/common/menu.jsp" />
+ <tiles:put name="body" value="/tiles/mainBody.jsp" />
+</tiles:insert>
+</pre>
+ <p>This example inserts the specified page, passing it the attributes. Attributes
+ are stored in a Tiles context which is passed to the inserted pag and
+ can then be accesssed by their names.</p>
+</div>
+<div class="subsection1">
+<h3>Retrieve an attribute value as String</h3>
+<pre>
+<tiles:getAsString name="title" />
+</pre>
+<p>This example retrieves the value of the attribute "title" and prints it as a String in the current output stream. The method toString() is applied on the attribute value, allowing to pass any kind of object as value.</p>
+</div>
+<div class="subsection1">
+<h3>Insert Tiles referenced by an attribute</h3>
+<pre>
+<tiles:insert attribute='menu' />
+</pre>
+ <p>This inserts the Tiles referenced by the attribute "menu" value. The
+ specified attribute value is first retrieved from current Tiles's context,
+ and then the value is used as a page target to insert.</p>
+</div>
+<div class="subsection1">
+<h3>Classic Layout </h3>
+ <p>This example is a layout assembling a page in the classic header-footer-menu-body
+ fashion.</p>
+ <pre>
+<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
+<HTML>
+ <HEAD>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/layouts/stylesheet.css"
+ type="text/css"/>
+ <title><tiles:getAsString name="title"/></title>
+ </HEAD>
+<body>
+<table border="0" width="100%" cellspacing="5">
+<tr>
+ <td colspan="2"><tiles:insert attribute="header" /></td>
+</tr>
+<tr>
+ <td width="140" valign="top">
+ <tiles:insert attribute='menu' />
+ </td>
+ <td valign="top" align="left">
+ <tiles:insert attribute='body' />
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+ <tiles:insert attribute="footer" />
+ </td>
+</tr>
+</table>
+</body>
+</html>
+</pre>
+ <p>The layout is declared in a JSP page (ex: /layouts/classicLayout.jsp).
+ It can be used in conjunction with the tag described in "<a href="#doc.InsertPageWithAttributes">Insert
+ a page passing some attributes</a>". </p>
+</div>
+</div>
+<div class="section">
+<h2>Definitions</h2>
+ <p>A definition associates a logical name with the URL of a Tiles to be inserted
+ and some attribute values. A definition doesn't insert the Tiles. This is
+ done later using the definition name. A definition name can be inserted
+ as often as you want in your site, making it easy to reuse a Tiles. </p>
+ <p>A definition can extend another definition and overload some attributes
+ or add new ones. This makes easy factorization of definitions differing
+ by some attributes. For example, you can define a master definition declaring
+ the main header, menu, footer, and a default title. Then let each of your
+ page definitions extend this master definition and overload the title and
+ the body.</p>
+ <p>Definitions can be declared in a JSP page, or in one or more centralized
+ files. To enable the definitions from centralized files, you need to initialize
+ the "definitions factory" which will parse the definitions from the files
+ and provide them to the Tiles framework.</p>
+<div class="subsection1">
+<h3>Enabling Definition Factory</h3>
+<p>To enable Tiles definitions described in one or more files, you need to write these files and to initialize the definition factory. </p>
+ <p>Initialization is different depending on the Struts version you use,
+ or if you do not use Struts at all.</p>
+<div class="subsection2">
+<h4>Struts1.1</h4>
+ <p>Use the Tiles plug-in to enable Tiles definitions. This plug-in creates
+ the definition factory and passese it a configuration object populated
+ with parameters. Parameters can be specified in the web.xml file or
+ as plug-in parameters. The plug-in first reads parameters from web.xml,
+ and then overloads them with the ones found in the plug-in. All parameters
+ are optional and can be omitted. The plug-in should be declared in each
+ struts-config file:</p>
+<pre>
+ <plug-in className="org.apache.tiles.TilesPlugin" >
+ <set-property property="definitions-config"
+ value="/WEB-INF/tiles-defs.xml,
+ /WEB-INF/tiles-tests-defs.xml,/WEB-INF/tiles-tutorial-defs.xml,
+ /WEB-INF/tiles-examples-defs.xml" />
+ <set-property property="moduleAware" value="true" />
+ <set-property property="definitions-parser-validate" value="true" />
+ </plug-in>
+</pre>
+<ul>
+<li>definitions-config: (optional) <ul>
+<li>Specify configuration file names. There can be several comma separated file names (default: ?? )</li>
+</ul>
+</li>
+ <li>definitions-parser-validate: (optional)
+<ul>
+ <li>Specify if XML parser should validate the Tiles configuration
+ file
+ <ul>
+ <li>true : validate. DTD should be specified in file header (default)</li>
+<li>false : no validation </li>
+
+</ul>
+</li>
+</ul>
+</li>
+
+ <li>moduleAware: (optional)
+ <ul>
+ <li>Specify if the Tiles definition factory is module aware. If true (default),
+ there will be one factory for each Struts module.
+ If false, there will be one common factory for all module. In this later case,
+ it is still needed to declare one plugin per module. The factory will be
+ initialized with parameters found in the first initialized plugin (generally the
+ one associated with the default module).
+ <ul>
+ <li>true : Tiles framework is module aware </li>
+ <li>false :Tiles framework has one single factoy shared among modules (default)</li>
+ </ul>
+ </li>
+</ul>
+</li>
+
+<li>tilesUtilImplClassname: (optional - for advanced user)
+ <ul>
+ <li>Specify The classname of the TilesUtil implementation to use. The specified class should
+ be a subclass of TilesUtilStrutsImpl. This option disable the moduleAware option.
+ <br>Specifying "TilesUtilStrutsImpl" is equivalent to moduleAware = false.</br>
+ <br>Specifying "TilesUtilStrutsModuleImpl" is equivalent to moduleAware = true.</br>
+ This option is taken into account only once, when it is first encountered. To avoid problems,
+ it is advice to specify the same values in all TilesPlugin declaration.
+ </li>
+ </ul>
+</li>
+
+</ul>
+ <p>The TilesPlugin class creates one definition factory for each struts module.
+ </p>
+ <p>
+ If the flag moduleAware is false, only one shared factory is created for all modules.
+ In this later case, the factory is initialized with parameters found in the first plugin.
+ The plugins should be declared in all modules, and the moduleAware flag should be
+ the same for the entire application.</p>
+ <p>
+ Paths found in Tiles definitions are relative to the main context.</p>
+ <p>You don't need to specify a TilesRequestProcessor, this is automatically
+ done by the plug-in. If, however, you want to specify your own RequestProcessor,
+ it should extend the TilesRequestProcessor. The plug-in checks this
+ constraint.</p>
+</div>
+<div class="subsection2">
+<h4>Struts1.0.x</h4>
+<p>You need to use a special servlet extending the Struts servlet. This is specified in the web.xml file of your application:</p>
+ <pre>
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.tiles.ActionComponentServlet</servlet-class>
+ <!-- Tiles Servlet parameter
+ Specify configuration file names. There can be several comma
+ separated file names
+ -->
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles-defs.xml</param-value>
+ </init-param>
+ <!-- Tiles Servlet parameter
+ Specify if XML parser should validate the Tiles configuration file(s).
+ true : validate. DTD should be specified in file header.
+ false : no validation
+ -->
+ <init-param>
+ <param-name>definitions-parser-validate</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ ...
+ </servlet>
+</pre>
+</div>
+<div class="subsection2">
+<h4>Without Struts</h4>
+<p>Tiles can be used without Struts. To initialize the definition factory, you can use the provided servlet. Declare it in the web.xml file of your application:</p>
+<pre>
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.tiles.TilesServlet</servlet-class>
+
+
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles-defs.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>definitions-parser-validate</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ ...
+</pre>
+<p>The parameters are the same as for Struts1.1 or 1.0.</p>
+</div>
+</div>
+<div class="subsection1">
+<h3>Definition File Syntax</h3>
+<p>The definition file syntax can be found in the
+<a href="http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">tiles-config_1_1.dtd file</a>.
+</p>
+<p>Following is a simple example:</p>
+ <pre>
+<!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration//EN"
+ "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">
+
+<!-- Definitions for Tiles documentation -->
+<tiles-definitions>
+
+ <!-- ========================================================== -->
+ <!-- Master definition -->
+ <!-- ========================================================== -->
+ <!-- Main page layout used as a root for other page definitions -->
+
+ <definition name="site.mainLayout" path="/layouts/classicLayout.jsp">
+ <put name="title" value="Tiles Blank Site" />
+ <put name="header" value="/tiles/common/header.jsp" />
+ <put name="menu" value="site.menu.bar" />
+ <put name="footer" value="/tiles/common/footer.jsp" />
+ <put name="body" value="/tiles/body.jsp" />
+ </definition>
+
+ <!-- ========================================================== -->
+ <!-- Index page definition -->
+ <!-- ========================================================== -->
+ <!-- This definition inherits from the main definition.
+ It overloads the page title and the body used.
+ Use the same mechanism to define new pages sharing common
+ properties (here header, menu, footer, layout)
+ -->
+
+ <definition name="site.index.page" extends="site.mainLayout" >
+ <put name="title" value="Tiles Blank Site Index" />
+ <put name="body" value="/tiles/body.jsp" />
+ </definition>
+
+</tiles-definition>
+</pre>
+</div>
+<div class="subsection1">
+<h3>Debugging</h3>
+<p>To debug a page made of Tiles, you can use following advices:</p>
+<ul>
+ <li>Check each Tiles separatly. Try to access nested Tiles directly to test
+ if thes work properly.</li>
+ <li>Enable Tiles logging. See the commons-logging package help.</li>
+</ul>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/servlets/TilesServlet.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/servlets/TilesServlet.java
new file mode 100644
index 0000000..82eebf8
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/servlets/TilesServlet.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id$
+ */
+
+package org.apache.tiles.servlets;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tiles.*;
+
+/**
+ * This is the entry point for Tiles. The <code>TilesServlet</code> initializes
+ * Tiles by creating a factory of tile definitions.
+ * <p/>
+ * <strong>Using the Tiles Servlet</strong>
+ * <p/>
+ * Add this servlet to your web.xml file,
+ * like this:
+ * <pre>
+<web-app>
+ ...
+<servlet>
+ <servlet-name><strong>Tiles Servlet</strong></servlet-name>
+ <servlet-class><strong>org.apache.tiles.servlets.TilesServlet</strong></servlet-class>
+ <load-on-startup/>
+</servlet>
+ ...
+</web-app>
+ * </pre>Notice there are no mappings for this servlet. That's because
+ * this servlet does everything when it's loaded. After that, it does not
+ * service requests. This is not a front-controller servlet, like the Struts or JSF servlets.<br/><br/>
+ * TilesServlet reads through your Tiles configuration file(s) and stores
+ * tile definitions in a factory. That factory is accessed by the Tiles
+ * tag libraries. You can specify a configuration file like this:
+ * <p/>
+ * <pre><web-app>
+ ...
+<servlet>
+ <servlet-name>Tiles Servlet</servlet-name>
+ <servlet-class>org.apache.tiles.servlets.TilesServlet</servlet-class>
+ <init-param>
+ <param-name><strong>definitions-config</strong></param-name>
+ <param-value><strong>/WEB-INF/tiles.xml</strong></param-value>
+ </init-param>
+ <load-on-startup/>
+</servlet>
+ ...
+</web-app></pre>Notice that we didn't specify a config file in the first servlet
+definition. In that case, Tiles assumes the existence of a file named /WEB-INF/tiles.xml. You
+can also define multiple configuration files like this:
+<p/><pre><web-app>
+ ...
+<servlet>
+ <servlet-name>Tiles Servlet</servlet-name>
+ <servlet-class>org.apache.tiles.servlets.TilesServlet</servlet-class>
+ <init-param>
+ <param-name><strong>definitions-config</strong></param-name>
+ <param-value><strong>/WEB-INF/tile-adaptors.xml, /WEB-INF/tiles.xml</strong></param-value>
+ </init-param>
+ <load-on-startup/>
+</servlet>
+ ...
+</web-app></pre>Here, we've specified two config files for Tiles to process. Both
+ * files must exist and each can reference definitions made in the other.
+ * <p/>
+ * <strong>Exception Handling</strong>
+ * <p/>
+ * When Tiles was bundled with Struts it reliably produced the same error message if anything
+ * was amiss in your Tiles configuration file: <i>Can't find definitions config file.</i>
+ * Standalone Tiles, OTOH, will display explicit error messages, such as <i>Error while parsing file
+ * '/WEB-INF/tiles.xml'. The element type "tiles-definitions" must be terminated by the matching
+ * end-tag tiles-definitions".</i> The following explains how it works.
+ * <p/>
+ * The Tiles servlet reads your tile configuration file(s) when the Tiles servlet is loaded. If
+ * problems are found with your configuration files, the Tiles servlet of yesteryear would
+ * throw a <code>FactoryNotFound</code> exception and log the error message to the servlet
+ * container's log. Subsequently, when the <code>tiles:insert</code> tag blows up because
+ * there's no definition factory, Tiles would throw an exception with the familiar
+ * <i>Cant find definitions config file</i> message. It was up to you to dig through
+ * the servlet container's log to find out what really went wrong.
+ *
+ * The standalone Tiles servlet, OTOH, places the exception's message in application scope
+ * and retrieves it when tiles:insert blows up. It throws an exception with the original error
+ * message, which is subsequently displayed in the browser, saving you the trouble of looking
+ * at the log file.
+ * <p>
+ * @author David Geary
+ */
+public class TilesServlet extends HttpServlet {
+
+
+ /**
+ * The logger for this class
+ */
+ protected static Logger logger = Logger.getLogger(TilesServlet.class.
+ getName());
+
+
+ /**
+ * The default name of a context init parameter that specifies the Tiles configuration file
+ */
+ private static final String DEFAULT_CONFIG_FILE_PARAM = "definitions-config";
+
+
+ /**
+ * The default name of the Tiles configuration file
+ */
+ private static final String DEFAULT_CONFIG_FILE = "/WEB-INF/tiles.xml";
+
+
+ /**
+ * An error message stating that something went wrong during initialization
+ */
+ private static final String CANT_POPULATE_FACTORY_ERROR =
+ "CAN'T POPULATE TILES DEFINITION FACTORY";
+
+
+ /**
+ * The Tiles definition factory
+ */
+ protected DefinitionsFactory definitionFactory = null;
+
+
+ /**
+ * A comma-separated list of filenames representing the
+ * application's Tiles configuration files.
+ */
+ private String configFiles = null;
+
+
+ /**
+ * Initializes the servlet by creating the Tiles definition
+ * factory and placing that factory in application scope. The
+ * Tiles tags will subsequently access that factory.
+ *
+ * @param config The servlet config
+ */
+ public void init(ServletConfig config)
+ throws javax.servlet.ServletException {
+ logger.info("Initializing TilesServlet");
+ configFiles = config.getInitParameter("definitions-config");
+
+ try {
+ // Create factory config object
+ DefinitionsFactoryConfig fconfig = readFactoryConfig();
+ fconfig.setModuleAware(false);
+
+ ServletContext context = config.getServletContext();
+ TilesUtil.setTilesUtil(new TilesUtilStrutsImpl());
+ initDefinitionsFactory(context, fconfig);
+ }
+ catch(Exception ex) {
+ saveExceptionMessage(config, ex);
+ throw new ServletException(ex.getMessage());
+ }
+ }
+
+
+ /**
+ * Populates the tiles factory configuration. If a
+ * context init param named <i>definitions-config</i>
+ * was defined, that param's value is assumed to be
+ * a comma-separated list of configuration file names,
+ * all of which are processed. If a
+ * <i>definitions-config</i> context param was not
+ * specified, Tiles assumes that your Tiles definition
+ * file is <code>/WEB-INF/tiles.xml</code>.
+ *
+ * @param config The servlet config
+ */
+ protected DefinitionsFactoryConfig readFactoryConfig()
+ throws ServletException {
+ DefinitionsFactoryConfig factoryConfig = new DefinitionsFactoryConfig();
+ Map map = new HashMap();
+
+ try {
+ if(configFiles != null) {
+ logger.info("CONFIG FILES DEFINED IN WEB.XML");
+ map.put(DEFAULT_CONFIG_FILE_PARAM, configFiles);
+ }
+ else {
+ logger.info("CONFIG FILES WERE NOT DEFINED IN WEB.XML, " +
+ "LOOKING FOR " + DEFAULT_CONFIG_FILE);
+ map.put(DEFAULT_CONFIG_FILE_PARAM, DEFAULT_CONFIG_FILE);
+ }
+
+ factoryConfig.populate(map);
+ }
+ catch (Exception ex) {
+ saveExceptionMessage(getServletConfig(), ex);
+ throw new UnavailableException(CANT_POPULATE_FACTORY_ERROR + ex.getMessage());
+ }
+ return factoryConfig;
+ }
+
+
+ /**
+ * Initializes the Tiles definitions factory.
+ *
+ * @param servletContext The servlet context
+ * @param factoryConfig The definitions factory config
+ */
+ private void initDefinitionsFactory(ServletContext servletContext,
+ DefinitionsFactoryConfig factoryConfig)
+ throws ServletException {
+ logger.info("initializing definitions factory...");
+ // Create configurable factory
+ try {
+ definitionFactory = DefinitionsUtil.createDefinitionsFactory(
+ servletContext, factoryConfig);
+ } catch (DefinitionsFactoryException ex) {
+ saveExceptionMessage(getServletConfig(), ex);
+ throw new ServletException(ex.getMessage());
+ }
+ }
+
+
+ /**
+ * Stores the message associated with any exception thrown in this
+ * servlet in application scope. Tiles later accesses that message
+ * if an exception is thrown when the tiles:insert tag is
+ * activated.
+ *
+ * @param servletContext The servlet context
+ * @param ex An exception
+ */
+ private void saveExceptionMessage(ServletConfig config, Exception ex) {
+ logger.warning("Caught exception when initializing definitions factory");
+ logger.warning(ex.getMessage());
+ logger.warning(ex.toString());
+ config.getServletContext().setAttribute(Globals.TILES_INIT_EXCEPTION, ex.getMessage());
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/DefinitionsFactory.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/DefinitionsFactory.java
new file mode 100644
index 0000000..848f468
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/DefinitionsFactory.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.NoSuchDefinitionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.io.Serializable;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+
+/**
+ * A factory for definitions.
+ * This factory allows to retrieve definitions by their keys.
+ */
+public class DefinitionsFactory implements Serializable
+{
+ /** Underlying map containing all definitions.*/
+ protected Map definitions;
+
+ /**
+ * Get a definition by its name.
+ * @param name Name of the definition.
+ * @param request Servlet request.
+ * @param servletContext Servlet context.
+ * @throws DefinitionsFactoryException An error occur while getting
+ * definition.
+ * @throws NoSuchDefinitionException No definition found for specified name
+ * Implementation can throw more accurate exception as a subclass of this
+ * exception.
+ */
+ public ComponentDefinition getDefinition(String name, ServletRequest request, ServletContext servletContext)
+ throws NoSuchDefinitionException, DefinitionsFactoryException
+ {
+ return (ComponentDefinition)definitions.get(name);
+ }
+
+ /**
+ * Put definition in set.
+ * @param definition Definition to put.
+ */
+ public void putDefinition(ComponentDefinition definition)
+ {
+ definitions.put( definition.getName(), definition );
+ }
+
+ /**
+ * Constructor.
+ * Create a factory initialized with definitions from {@link XmlDefinitionsSet}.
+ * @param xmlDefinitions Resolved definition from XmlDefinitionSet.
+ * @throws NoSuchDefinitionException If an error occurs while resolving inheritance
+ */
+ public DefinitionsFactory(XmlDefinitionsSet xmlDefinitions)
+ throws NoSuchDefinitionException
+ {
+ definitions = new HashMap();
+
+ // First, resolve inheritance
+ xmlDefinitions.resolveInheritances();
+
+ // Walk thru xml set and copy each definitions.
+ Iterator i = xmlDefinitions.getDefinitions().values().iterator();
+ while( i.hasNext() )
+ {
+ XmlDefinition xmlDefinition = (XmlDefinition)i.next();
+ putDefinition( new ComponentDefinition( xmlDefinition) );
+ } // end loop
+ }
+ /**
+ * Return String representation.
+ * @return String representation.
+ */
+ public String toString()
+ {
+ return definitions.toString();
+ }
+
+}
+
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/FactorySet.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/FactorySet.java
new file mode 100644
index 0000000..54a4ae4
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/FactorySet.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import org.apache.tiles.ComponentDefinitionsFactory;
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.NoSuchDefinitionException;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.FactoryNotFoundException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Component Definitions factory.
+ * This factory contains several factories identified by a key. The
+ * getDefinition() method first looks for the factory key, retrieves or creates this
+ * factory and then calls its getDefinition().
+ */
+public abstract class FactorySet implements ComponentDefinitionsFactory
+{
+
+ /** Loaded factories */
+ protected Map factories=null;
+
+ /**
+ * Extract key that will be used to get the sub factory.
+ * @param name Name of requested definition.
+ * @param request Current servlet request.
+ * @param servletContext Current servlet context.
+ * @return Object.
+ */
+ abstract protected Object getDefinitionsFactoryKey(String name, ServletRequest request, ServletContext servletContext);
+
+ /**
+ * Get default factory.
+ * @return Default factory.
+ */
+ abstract protected DefinitionsFactory getDefaultFactory();
+
+ /**
+ * Get a factory by its key.
+ * If key is <code>null</code>, return defaultFactory.
+ * Search in loaded factories. If not found, create factory and store return value in
+ * loaded factories.
+ * @param key Key of requested definition.
+ * @param request Current servlet request.
+ * @param servletContext Current servlet context.
+ * @throws DefinitionsFactoryException If an error occur while creating factory.
+ */
+ protected DefinitionsFactory getFactory(Object key, ServletRequest request, ServletContext servletContext)
+ throws DefinitionsFactoryException
+ {
+ if(key == null )
+ return getDefaultFactory();
+
+ Object factory = factories.get( key );
+ if( factory == null )
+ {
+ // synchronize creation to avoid double creation by separate threads.
+ // Also, check if factory hasn't been created while waiting for synchronized
+ // section.
+ synchronized(factories)
+ {
+ factory = factories.get( key );
+ if( factory == null )
+ {
+ factory = createFactory( key, request, servletContext);
+ factories.put( key, factory );
+ } // end if
+ } // end synchronized
+ } // end if
+ return (DefinitionsFactory)factory;
+ }
+
+ /**
+ * Get a definition by its name.
+ *
+ * @param name Name of requested definition.
+ * @param request Current servlet request.
+ * @param servletContext Current servlet context.
+ * @throws NoSuchDefinitionException No definition found for specified name
+ * @throws DefinitionsFactoryException General exception
+ */
+ public ComponentDefinition getDefinition(String name, ServletRequest request, ServletContext servletContext)
+ throws NoSuchDefinitionException, DefinitionsFactoryException
+ {
+ if( factories == null )
+ throw new FactoryNotFoundException( "No definitions factory defined" );
+
+ Object key = getDefinitionsFactoryKey( name, request, servletContext);
+ DefinitionsFactory factory = getFactory( key, request, servletContext);
+ return factory.getDefinition( name, request, servletContext );
+ }
+
+ /**
+ * Create a factory for specified key.
+ * This method is called by getFactory() when the requested factory doesn't already exist.
+ * Must return a factory, or a default one.
+ * Real implementation needs to provide this method.
+ * @param key Key of requested definition.
+ * @param request Current servlet request.
+ * @param servletContext Current servlet context
+ * @throws DefinitionsFactoryException If an error occur while creating factory.
+ */
+ abstract protected DefinitionsFactory createFactory(Object key, ServletRequest request, ServletContext servletContext)
+ throws DefinitionsFactoryException;
+
+ /**
+ * Init factory set.
+ * @param servletContext Current servlet context
+ * @param properties properties used to initialized factory set;
+ */
+ abstract public void initFactory(ServletContext servletContext, Map properties)
+ throws DefinitionsFactoryException;
+
+ /**
+ * Constructor.
+ */
+ public FactorySet()
+ {
+ factories = new HashMap();
+ }
+
+ /**
+ * Return String representation.
+ * @return String representation.
+ */
+ public String toString()
+ {
+ Iterator i = factories.values().iterator();
+ StringBuffer buff = new StringBuffer( "all FactorySet's factory : \n" );
+ while( i.hasNext() )
+ {
+ buff.append( i.next().toString() ).append("\n");
+ }
+ return buff.toString();
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/I18nFactorySet.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/I18nFactorySet.java
new file mode 100644
index 0000000..5bc5c03
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/I18nFactorySet.java
@@ -0,0 +1,587 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tiles.DefinitionsFactoryException;
+import org.apache.tiles.DefinitionsUtil;
+import org.apache.tiles.FactoryNotFoundException;
+import org.apache.taglib.tiles.ComponentConstants;
+import org.xml.sax.SAXException;
+
+/**
+ * Definitions factory.
+ * This implementation allows to have a set of definition factories.
+ * There is a main factory and one factory for each file associated to a Locale.
+ *
+ * To retrieve a definition, we first search for the appropriate factory using
+ * the Locale found in session context. If no factory is found, use the
+ * default one. Then we ask the factory for the definition.
+ *
+ * A definition factory file is loaded using main filename extended with locale code
+ * (ex : <code>templateDefinitions_fr.xml</code>). If no file is found under this name, use default file.
+ */
+public class I18nFactorySet extends FactorySet {
+
+ /**
+ * Commons Logging instance.
+ */
+ protected static Log log = LogFactory.getLog(I18nFactorySet.class);
+
+ /**
+ * Config file parameter name.
+ */
+ public static final String DEFINITIONS_CONFIG_PARAMETER_NAME =
+ "definitions-config";
+
+ /**
+ * Config file parameter name.
+ */
+ public static final String PARSER_DETAILS_PARAMETER_NAME =
+ "definitions-parser-details";
+
+ /**
+ * Config file parameter name.
+ */
+ public static final String PARSER_VALIDATE_PARAMETER_NAME =
+ "definitions-parser-validate";
+
+ /**
+ * Possible definition filenames.
+ */
+ public static final String DEFAULT_DEFINITION_FILENAMES[] =
+ {
+ "/WEB-INF/tileDefinitions.xml",
+ "/WEB-INF/componentDefinitions.xml",
+ "/WEB-INF/instanceDefinitions.xml" };
+
+ /**
+ * Maximum length of one branch of the resource search path tree.
+ * Used in getBundle().
+ */
+ private static final int MAX_BUNDLES_SEARCHED = 2;
+
+ /**
+ * Default filenames extension.
+ */
+ public static final String FILENAME_EXTENSION = ".xml";
+
+ /**
+ * Default factory.
+ */
+ protected DefinitionsFactory defaultFactory = null;
+
+ /**
+ * XML parser used.
+ * Attribute is transient to allow serialization. In this implementaiton,
+ * xmlParser is created each time we need it ;-(.
+ */
+ protected transient XmlParser xmlParser;
+
+ /**
+ * Do we want validating parser. Default is <code>false</code>.
+ * Can be set from servlet config file.
+ */
+ protected boolean isValidatingParser = false;
+
+ /**
+ * Parser detail level. Default is 0.
+ * Can be set from servlet config file.
+ */
+ protected int parserDetailLevel = 0;
+
+ /**
+ * Names of files containing instances descriptions.
+ */
+ private List filenames = null;
+
+ /**
+ * Collection of already loaded definitions set, referenced by their suffix.
+ */
+ private Map loaded = null;
+
+ /**
+ * Parameterless Constructor.
+ * Method {@link #initFactory} must be called prior to any use of created factory.
+ */
+ public I18nFactorySet() {
+ super();
+ log.info("CONSTRUCTING I18NFactorySet");
+ }
+
+ /**
+ * Constructor.
+ * Init the factory by reading appropriate configuration file.
+ * @param servletContext Servlet context.
+ * @param properties Map containing all properties.
+ * @throws FactoryNotFoundException Can't find factory configuration file.
+ */
+ public I18nFactorySet(ServletContext servletContext, Map properties)
+ throws DefinitionsFactoryException {
+
+ initFactory(servletContext, properties);
+ }
+
+ /**
+ * Initialization method.
+ * Init the factory by reading appropriate configuration file.
+ * This method is called exactly once immediately after factory creation in
+ * case of internal creation (by DefinitionUtil).
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param properties Map of name/property passed to newly created factory. Map can contains
+ * more properties than requested.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ public void initFactory(ServletContext servletContext, Map properties)
+ throws DefinitionsFactoryException {
+
+ // Set some property values
+ String value = (String) properties.get(PARSER_VALIDATE_PARAMETER_NAME);
+ if (value != null) {
+ isValidatingParser = Boolean.valueOf(value).booleanValue();
+ }
+
+ value = (String) properties.get(PARSER_DETAILS_PARAMETER_NAME);
+ if (value != null) {
+ try {
+ parserDetailLevel = Integer.valueOf(value).intValue();
+
+ } catch (NumberFormatException ex) {
+ log.error(
+ "Bad format for parameter '"
+ + PARSER_DETAILS_PARAMETER_NAME
+ + "'. Integer expected.");
+ }
+ }
+
+ // init factory withappropriate configuration file
+ // Try to use provided filename, if any.
+ // If no filename are provided, try to use default ones.
+ String filename = (String) properties.get(DEFINITIONS_CONFIG_PARAMETER_NAME);
+ if (filename != null) { // Use provided filename
+ try {
+ initFactory(servletContext, filename);
+ if (log.isDebugEnabled()) {
+ log.debug("Factory initialized from file '" + filename + "'.");
+ }
+
+ } catch (FileNotFoundException ex) { // A filename is specified, throw appropriate error.
+ log.error(ex.getMessage() + " : Can't find file '" + filename + "'");
+ throw new FactoryNotFoundException(
+ ex.getMessage() + " : Can't find file '" + filename + "'");
+ }
+
+ } else { // try each default file names
+ for (int i = 0; i < DEFAULT_DEFINITION_FILENAMES.length; i++) {
+ filename = DEFAULT_DEFINITION_FILENAMES[i];
+ try {
+ initFactory(servletContext, filename);
+ if (log.isInfoEnabled()) {
+ log.info(
+ "Factory initialized from file '" + filename + "'.");
+ }
+ } catch (FileNotFoundException ex) {
+ // Do nothing
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Initialization method.
+ * Init the factory by reading appropriate configuration file.
+ * This method is called exactly once immediately after factory creation in
+ * case of internal creation (by DefinitionUtil).
+ * @param servletContext Servlet Context passed to newly created factory.
+ * @param proposedFilename File names, comma separated, to use as base file names.
+ * @throws DefinitionsFactoryException An error occur during initialization.
+ */
+ protected void initFactory(
+ ServletContext servletContext,
+ String proposedFilename)
+ throws DefinitionsFactoryException, FileNotFoundException {
+
+ // Init list of filenames
+ StringTokenizer tokenizer = new StringTokenizer(proposedFilename, ",");
+ this.filenames = new ArrayList(tokenizer.countTokens());
+ while (tokenizer.hasMoreTokens()) {
+ this.filenames.add(tokenizer.nextToken().trim());
+ }
+
+ loaded = new HashMap();
+ defaultFactory = createDefaultFactory(servletContext);
+ if (log.isDebugEnabled())
+ log.debug("default factory:" + defaultFactory);
+ }
+
+ /**
+ * Get default factory.
+ * @return Default factory
+ */
+ protected DefinitionsFactory getDefaultFactory() {
+ return defaultFactory;
+ }
+
+ /**
+ * Create default factory .
+ * Create InstancesMapper for specified Locale.
+ * If creation failes, use default mapper and log error message.
+ * @param servletContext Current servlet context. Used to open file.
+ * @return Created default definition factory.
+ * @throws DefinitionsFactoryException If an error occur while creating factory.
+ * @throws FileNotFoundException if factory can't be loaded from filenames.
+ */
+ protected DefinitionsFactory createDefaultFactory(ServletContext servletContext)
+ throws DefinitionsFactoryException, FileNotFoundException {
+
+ XmlDefinitionsSet rootXmlConfig = parseXmlFiles(servletContext, "", null);
+ if (rootXmlConfig == null) {
+ log.info("COULDN'T FIND THE FILE");
+ throw new FileNotFoundException();
+ }
+
+ rootXmlConfig.resolveInheritances();
+
+ if (log.isDebugEnabled()) {
+ log.debug(rootXmlConfig);
+ }
+
+ DefinitionsFactory factory = new DefinitionsFactory(rootXmlConfig);
+ if (log.isDebugEnabled()) {
+ log.debug("factory loaded : " + factory);
+ }
+
+ return factory;
+ }
+
+ /**
+ * Extract key that will be used to get the sub factory.
+ * @param name Name of requested definition
+ * @param request Current servlet request.
+ * @param servletContext Current servlet context.
+ * @return the key or <code>null</code> if not found.
+ */
+ protected Object getDefinitionsFactoryKey(
+ String name,
+ ServletRequest request,
+ ServletContext servletContext) {
+
+ Locale locale = null;
+ try {
+ HttpSession session = ((HttpServletRequest) request).getSession(false);
+ if (session != null) {
+ locale = (Locale) session.getAttribute(ComponentConstants.LOCALE_KEY);
+ }
+
+ } catch (ClassCastException ex) {
+ log.error("I18nFactorySet.getDefinitionsFactoryKey");
+ ex.printStackTrace();
+ }
+
+ return locale;
+ }
+
+ /**
+ * Create a factory for specified key.
+ * If creation failes, return default factory and log an error message.
+ * @param key The key.
+ * @param request Servlet request.
+ * @param servletContext Servlet context.
+ * @return Definition factory for specified key.
+ * @throws DefinitionsFactoryException If an error occur while creating factory.
+ */
+ protected DefinitionsFactory createFactory(
+ Object key,
+ ServletRequest request,
+ ServletContext servletContext)
+ throws DefinitionsFactoryException {
+
+ if (key == null) {
+ return getDefaultFactory();
+ }
+
+ // Build possible postfixes
+ List possiblePostfixes = calculatePostixes("", (Locale) key);
+
+ // Search last postix corresponding to a config file to load.
+ // First check if something is loaded for this postfix.
+ // If not, try to load its config.
+ XmlDefinitionsSet lastXmlFile = null;
+ DefinitionsFactory factory = null;
+ String curPostfix = null;
+ int i = 0;
+
+ for (i = possiblePostfixes.size() - 1; i >= 0; i--) {
+ curPostfix = (String) possiblePostfixes.get(i);
+
+ // Already loaded ?
+ factory = (DefinitionsFactory) loaded.get(curPostfix);
+ if (factory != null) { // yes, stop search
+ return factory;
+ }
+
+ // Try to load it. If success, stop search
+ lastXmlFile = parseXmlFiles(servletContext, curPostfix, null);
+ if (lastXmlFile != null) {
+ break;
+ }
+ }
+
+ // Have we found a description file ?
+ // If no, return default one
+ if (lastXmlFile == null) {
+ return getDefaultFactory();
+ }
+
+ // We found something. Need to load base and intermediate files
+ String lastPostfix = curPostfix;
+ XmlDefinitionsSet rootXmlConfig = parseXmlFiles(servletContext, "", null);
+ for (int j = 0; j < i; j++) {
+ curPostfix = (String) possiblePostfixes.get(j);
+ parseXmlFiles(servletContext, curPostfix, rootXmlConfig);
+ }
+
+ rootXmlConfig.extend(lastXmlFile);
+ rootXmlConfig.resolveInheritances();
+
+ factory = new DefinitionsFactory(rootXmlConfig);
+ loaded.put(lastPostfix, factory);
+
+ if (log.isDebugEnabled()) {
+ log.debug("factory loaded : " + factory);
+ }
+
+ // return last available found !
+ return factory;
+ }
+
+ /**
+ * Calculate the postixes along the search path from the base bundle to the
+ * bundle specified by baseName and locale.
+ * Method copied from java.util.ResourceBundle
+ * @param baseName the base bundle name
+ * @param locale the locale
+ */
+ private static List calculatePostixes(String baseName, Locale locale) {
+ final List result = new ArrayList(MAX_BUNDLES_SEARCHED);
+ final String language = locale.getLanguage();
+ final int languageLength = language.length();
+ final String country = locale.getCountry();
+ final int countryLength = country.length();
+ final String variant = locale.getVariant();
+ final int variantLength = variant.length();
+
+ if (languageLength + countryLength + variantLength == 0) {
+ //The locale is "", "", "".
+ return result;
+ }
+
+ final StringBuffer temp = new StringBuffer(baseName);
+ temp.append('_');
+ temp.append(language);
+
+ if (languageLength > 0)
+ result.add(temp.toString());
+
+ if (countryLength + variantLength == 0)
+ return result;
+
+ temp.append('_');
+ temp.append(country);
+
+ if (countryLength > 0)
+ result.add(temp.toString());
+
+ if (variantLength == 0) {
+ return result;
+ } else {
+ temp.append('_');
+ temp.append(variant);
+ result.add(temp.toString());
+ return result;
+ }
+ }
+
+ /**
+ * Parse files associated to postix if they exist.
+ * For each name in filenames, append postfix before file extension,
+ * then try to load the corresponding file.
+ * If file doesn't exist, try next one. Each file description is added to
+ * the XmlDefinitionsSet description.
+ * The XmlDefinitionsSet description is created only if there is a definition file.
+ * Inheritance is not resolved in the returned XmlDefinitionsSet.
+ * If no description file can be opened and no definiion set is provided, return <code>null</code>.
+ * @param postfix Postfix to add to each description file.
+ * @param xmlDefinitions Definitions set to which definitions will be added. If <code>null</code>, a definitions
+ * set is created on request.
+ * @return XmlDefinitionsSet The definitions set created or passed as parameter.
+ * @throws DefinitionsFactoryException On errors parsing file.
+ */
+ private XmlDefinitionsSet parseXmlFiles(
+ ServletContext servletContext,
+ String postfix,
+ XmlDefinitionsSet xmlDefinitions)
+ throws DefinitionsFactoryException {
+
+ if (postfix != null && postfix.length() == 0) {
+ postfix = null;
+ }
+
+ // Iterate throw each file name in list
+ Iterator i = filenames.iterator();
+ while (i.hasNext()) {
+ String filename = concatPostfix((String) i.next(), postfix);
+ xmlDefinitions = parseXmlFile(servletContext, filename, xmlDefinitions);
+ }
+
+ return xmlDefinitions;
+ }
+
+ /**
+ * Parse specified xml file and add definition to specified definitions set.
+ * This method is used to load several description files in one instances list.
+ * If filename exists and definition set is <code>null</code>, create a new set. Otherwise, return
+ * passed definition set (can be <code>null</code>).
+ * @param servletContext Current servlet context. Used to open file.
+ * @param filename Name of file to parse.
+ * @param xmlDefinitions Definitions set to which definitions will be added. If null, a definitions
+ * set is created on request.
+ * @return XmlDefinitionsSet The definitions set created or passed as parameter.
+ * @throws DefinitionsFactoryException On errors parsing file.
+ */
+ private XmlDefinitionsSet parseXmlFile(
+ ServletContext servletContext,
+ String filename,
+ XmlDefinitionsSet xmlDefinitions)
+ throws DefinitionsFactoryException {
+
+ try {
+ InputStream input = servletContext.getResourceAsStream(filename);
+ // Try to load using real path.
+ // This allow to load config file under websphere 3.5.x
+ // Patch proposed Houston, Stephen (LIT) on 5 Apr 2002
+ if (null == input) {
+ try {
+ input =
+ new java.io.FileInputStream(
+ servletContext.getRealPath(filename));
+ } catch (Exception e) {
+ }
+ }
+
+ // If still nothing found, this mean no config file is associated
+ if (input == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Can't open file '" + filename + "'");
+ }
+ return xmlDefinitions;
+ }
+
+ // Check if parser already exist.
+ // Doesn't seem to work yet.
+ //if( xmlParser == null )
+ if (true) {
+ xmlParser = new XmlParser();
+ xmlParser.setValidating(isValidatingParser);
+ }
+
+ // Check if definition set already exist.
+ if (xmlDefinitions == null) {
+ xmlDefinitions = new XmlDefinitionsSet();
+ }
+
+ xmlParser.parse(input, xmlDefinitions);
+
+ } catch (SAXException ex) {
+ if (log.isDebugEnabled()) {
+ log.debug("Error while parsing file '" + filename + "'.");
+ ex.printStackTrace();
+ }
+ throw new DefinitionsFactoryException(
+ "Error while parsing file '" + filename + "'. " + ex.getMessage(),
+ ex);
+
+ } catch (IOException ex) {
+ throw new DefinitionsFactoryException(
+ "IO Error while parsing file '" + filename + "'. " + ex.getMessage(),
+ ex);
+ }
+
+ return xmlDefinitions;
+ }
+
+ /**
+ * Concat postfix to the name. Take care of existing filename extension.
+ * Transform the given name "name.ext" to have "name" + "postfix" + "ext".
+ * If there is no ext, return "name" + "postfix".
+ * @param name Filename.
+ * @param postfix Postfix to add.
+ * @return Concatenated filename.
+ */
+ private String concatPostfix(String name, String postfix) {
+ if (postfix == null) {
+ return name;
+ }
+
+ // Search file name extension.
+ // take care of Unix files starting with .
+ int dotIndex = name.lastIndexOf(".");
+ int lastNameStart = name.lastIndexOf(java.io.File.pathSeparator);
+ if (dotIndex < 1 || dotIndex < lastNameStart) {
+ return name + postfix;
+ }
+
+ String ext = name.substring(dotIndex);
+ name = name.substring(0, dotIndex);
+ return name + postfix + ext;
+ }
+
+ /**
+ * Return String representation.
+ * @return String representation.
+ */
+ public String toString() {
+ StringBuffer buff = new StringBuffer("I18nFactorySet : \n");
+ buff.append("--- default factory ---\n");
+ buff.append(defaultFactory.toString());
+ buff.append("\n--- other factories ---\n");
+ Iterator i = factories.values().iterator();
+ while (i.hasNext()) {
+ buff.append(i.next().toString()).append("---------- \n");
+ }
+ return buff.toString();
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlAttribute.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlAttribute.java
new file mode 100644
index 0000000..121fe35
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlAttribute.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import org.apache.tiles.DefinitionNameAttribute;
+import org.apache.tiles.DirectStringAttribute;
+import org.apache.tiles.PathAttribute;
+import org.apache.tiles.UntypedAttribute;
+
+/**
+ * A property key-value pair. This class is used to read configuration files.
+ */
+public class XmlAttribute {
+
+ /**
+ * Attribute name or key.
+ */
+ private String name = null;
+
+ /**
+ * Attribute value.
+ * Value read from description file.
+ */
+ private Object value = null;
+
+ /**
+ * Attribute value.
+ */
+ private String direct = null;
+
+ /**
+ * Attribute value.
+ */
+ private String valueType = null;
+
+ /**
+ * Attribute value.
+ */
+ private String role = null;
+
+ /**
+ * Real attribute value.
+ * Real value is the value after processing of valueType.
+ * I.e. if a type is defined, realValue contains wrapper for this type.
+ */
+ private Object realValue = null;
+
+ /**
+ * Constructor.
+ */
+ public XmlAttribute() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ */
+ public XmlAttribute(String name, Object value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Access method for the name property.
+ *
+ * @return The current value of the name property.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param aName the new value of the name property
+ */
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ /**
+ * Access method for the name property.
+ *
+ * @return The current value of the name property.
+ */
+ public String getRole() {
+ return role;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param aName the new value of the name property.
+ */
+ public void setName(String aName) {
+ name = aName;
+ }
+
+ /**
+ * Another access method for the name property.
+ *
+ * @return the current value of the name property
+ */
+ public String getAttribute() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param aName the new value of the name property
+ */
+ public void setAttribute(String aName) {
+ name = aName;
+ }
+
+ /**
+ * Access method for the value property. Return the value or a
+ * QualifiedAttribute containing the value if 'direct' is set.
+ *
+ * @return The current value of the value property.
+ */
+ public Object getValue() {
+ // Compatibility with JSP Template
+ if (this.realValue == null) {
+ this.realValue = this.computeRealValue();
+ }
+
+ return this.realValue;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param aValue the new value of the value property
+ */
+ public void setValue(Object aValue) {
+ realValue = null;
+ value = aValue;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param aValue the new value of the value property
+ */
+ public void setContent(Object aValue) {
+ setValue(aValue);
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param aValue the new value of the value property
+ */
+ public void setBody(String body) {
+ if (body.length() == 0) {
+ return;
+ }
+
+ setValue(body);
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param aValue the new value of the value property
+ */
+ public void setDirect(String value) {
+ this.direct = value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param aValue the new value of the value property
+ */
+ public void setType(String value) {
+ this.valueType = value;
+ }
+
+ /**
+ * Compute real value from attributes setting.
+ */
+ protected Object computeRealValue() {
+ Object realValue = value;
+ // Is there a type set ?
+ // First check direct attribute, and translate it to a valueType.
+ // Then, evaluate valueType, and create requested typed attribute.
+ if (direct != null) {
+ this.valueType =
+ Boolean.valueOf(direct).booleanValue() ? "string" : "path";
+ }
+
+ if (value != null && valueType != null) {
+ String strValue = value.toString();
+
+ if (valueType.equalsIgnoreCase("string")) {
+ realValue = new DirectStringAttribute(strValue);
+
+ } else if (valueType.equalsIgnoreCase("page")) {
+ realValue = new PathAttribute(strValue);
+
+ } else if (valueType.equalsIgnoreCase("template")) {
+ realValue = new PathAttribute(strValue);
+
+ } else if (valueType.equalsIgnoreCase("instance")) {
+ realValue = new DefinitionNameAttribute(strValue);
+ }
+
+ // Set realValue's role value if needed
+ if (role != null) {
+ ((UntypedAttribute) realValue).setRole(role);
+ }
+ }
+
+ // Create attribute wrapper to hold role if role is set and no type specified
+ if (role != null && value != null && valueType == null) {
+ realValue = new UntypedAttribute(value.toString(), role);
+ }
+
+ return realValue;
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlDefinition.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlDefinition.java
new file mode 100644
index 0000000..dfab7bb
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlDefinition.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import org.apache.tiles.ComponentDefinition;
+import org.apache.tiles.NoSuchDefinitionException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Iterator;
+
+/**
+ *A definition read from an XML definitions file.
+ */
+public class XmlDefinition extends ComponentDefinition
+{
+ /**
+ * Extends attribute value.
+ */
+ private String inherit;
+
+ /** Commons Logging instance. */
+ protected static Log log = LogFactory.getLog(XmlDefinition.class);
+
+ /**
+ * Used for resolving inheritance.
+ */
+ private boolean isVisited=false;
+
+
+ /**
+ * Constructor.
+ */
+ public XmlDefinition()
+ {
+ super();
+ //if(debug)
+ //System.out.println( "create definition" );
+ }
+
+ /**
+ * Add an attribute to this component.
+ *
+ * @param attribute Attribute to add.
+ */
+ public void addAttribute( XmlAttribute attribute)
+ {
+ putAttribute( attribute.getName(), attribute.getValue() );
+ }
+
+ /**
+ * Set extends.
+ *
+ * @param name Name of the extended definition.
+ */
+ public void setExtends(String name)
+ {
+ inherit = name;
+ }
+
+ /**
+ * Get extends.
+ *
+ * @return Name of the extended definition.
+ */
+ public String getExtends()
+ {
+ return inherit;
+ }
+
+ /**
+ * Get extends flag.
+ *
+ */
+ public boolean isExtending( )
+ {
+ return inherit!=null;
+ }
+
+ /**
+ * Set isVisited.
+ *
+ */
+ public void setIsVisited( boolean isVisited )
+ {
+ this.isVisited = isVisited;
+ }
+
+ /**
+ * Resolve inheritance.
+ * First, resolve parent's inheritance, then set path to the parent's path.
+ * Also copy attributes setted in parent, and not set in child
+ * If instance doesn't extend anything, do nothing.
+ * @throws NoSuchDefinitionException If an inheritance can not be solved.
+ */
+ public void resolveInheritance( XmlDefinitionsSet definitionsSet )
+ throws NoSuchDefinitionException
+ {
+ // Already done, or not needed ?
+ if( isVisited || !isExtending() )
+ return;
+
+ if(log.isDebugEnabled())
+ log.debug( "Resolve definition for child name='" + getName()
+ + "' extends='" + getExtends() + "'.");
+
+ // Set as visited to avoid endless recurisvity.
+ setIsVisited( true );
+
+ // Resolve parent before itself.
+ XmlDefinition parent = definitionsSet.getDefinition( getExtends() );
+ if( parent == null )
+ { // error
+ String msg = "Error while resolving definition inheritance: child '"
+ + getName() + "' can't find its ancestor '"
+ + getExtends() + "'. Please check your description file.";
+ log.error( msg );
+ // to do : find better exception
+ throw new NoSuchDefinitionException( msg );
+ }
+
+ parent.resolveInheritance( definitionsSet );
+
+ // Iterate on each parent's attribute and add it if not defined in child.
+ Iterator parentAttributes = parent.getAttributes().keySet().iterator();
+ while( parentAttributes.hasNext() )
+ {
+ String name = (String)parentAttributes.next();
+ if( !getAttributes().containsKey(name) )
+ putAttribute( name, parent.getAttribute(name) );
+ }
+ // Set path and role if not setted
+ if( path == null )
+ setPath( parent.getPath() );
+ if( role == null )
+ setRole( parent.getRole() );
+ if( controller==null )
+ {
+ setController( parent.getController());
+ setControllerType( parent.getControllerType());
+ }
+ }
+
+ /**
+ * Overload this definition with passed child.
+ * All attributes from child are copied to this definition. Previous attributes with
+ * same name are disguarded.
+ * Special attribute 'path','role' and 'extends' are overloaded if defined in child.
+ * @param child Child used to overload this definition.
+ */
+ public void overload( XmlDefinition child )
+ {
+ if( child.getPath() != null )
+ {
+ path = child.getPath();
+ }
+ if( child.getExtends() != null )
+ {
+ inherit = child.getExtends();
+ }
+ if( child.getRole() != null )
+ {
+ role = child.getRole();
+ }
+ if( child.getController()!=null )
+ {
+ controller = child.getController();
+ controllerType = child.getControllerType();
+ }
+ // put all child attributes in parent.
+ attributes.putAll( child.getAttributes());
+ }
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlDefinitionsSet.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlDefinitionsSet.java
new file mode 100644
index 0000000..33c3170
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlDefinitionsSet.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import org.apache.tiles.NoSuchDefinitionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A set of definitions read from XML definitions file.
+*/
+public class XmlDefinitionsSet
+{
+ /** Defined definitions. */
+ protected Map definitions;
+
+ /**
+ * Constructor.
+ */
+ public XmlDefinitionsSet()
+ {
+ definitions = new HashMap();
+ }
+
+ /**
+ * Put definition in set.
+ * @param definition Definition to add.
+ */
+ public void putDefinition(XmlDefinition definition)
+ {
+ definitions.put( definition.getName(), definition );
+ }
+
+ /**
+ * Get requested definition.
+ * @param name Definition name.
+ */
+ public XmlDefinition getDefinition(String name)
+ {
+ return (XmlDefinition)definitions.get( name );
+ }
+
+ /**
+ * Get definitions map.
+ */
+ public Map getDefinitions()
+ {
+ return definitions;
+ }
+
+ /**
+ * Resolve extended instances.
+ */
+ public void resolveInheritances() throws NoSuchDefinitionException
+ {
+ // Walk through all definitions and resolve individual inheritance
+ Iterator i = definitions.values().iterator();
+ while( i.hasNext() )
+ {
+ XmlDefinition definition = (XmlDefinition)i.next();
+ definition.resolveInheritance( this );
+ } // end loop
+ }
+
+ /**
+ * Add definitions from specified child definitions set.
+ * For each definition in child, look if it already exists in this set.
+ * If not, add it, if yes, overload parent's definition with child definition.
+ * @param child Definition used to overload this object.
+ */
+ public void extend( XmlDefinitionsSet child )
+ {
+ if(child==null)
+ return;
+ Iterator i = child.getDefinitions().values().iterator();
+ while( i.hasNext() )
+ {
+ XmlDefinition childInstance = (XmlDefinition)i.next();
+ XmlDefinition parentInstance = getDefinition(childInstance.getName() );
+ if( parentInstance != null )
+ {
+ parentInstance.overload( childInstance );
+ }
+ else
+ putDefinition( childInstance );
+ } // end loop
+ }
+ /**
+ * Get String representation.
+ */
+ public String toString()
+ {
+ return "definitions=" + definitions.toString() ;
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlListAttribute.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlListAttribute.java
new file mode 100644
index 0000000..ac5d470
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlListAttribute.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.RequestDispatcher;
+
+public class XmlListAttribute extends XmlAttribute {
+ /** List.
+ * We declare a List to avoid cast.
+ * Parent "value" property points to the same list.
+ */
+ private List list;
+
+ /**
+ * Constructor.
+ */
+ public XmlListAttribute()
+ {
+ list = new ArrayList();
+ setValue(list);
+ }
+
+ /**
+ * Constructor.
+ * @param name Name.
+ * @param value List.
+ */
+ public XmlListAttribute( String name, List value)
+ {
+ super( name, value );
+ list = value;
+ }
+
+ /**
+ * Add an element in list.
+ * We use a property to avoid rewriting a new class.
+ * @param element XmlAttribute to add.
+ */
+ public void add( XmlAttribute element )
+ {
+ list.add( element.getValue() );
+ }
+
+ /**
+ * Add an element in list.
+ * @param value Object to add.
+ */
+ public void add( Object value )
+ {
+ //list.add( value );
+ // To correct a bug in digester, we need to check the object type
+ // Digester doesn't call correct method according to object type ;-(
+ if(value instanceof XmlAttribute)
+ {
+ add((XmlAttribute)value);
+ return;
+ }
+ else
+ list.add( value );
+ }
+
+ /**
+ * Add an element in list.
+ * @param value Object to add.
+ */
+ public void addObject( Object value )
+ {
+ list.add( value );
+ }
+
+
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlParser.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlParser.java
new file mode 100644
index 0000000..c2b3357
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/XmlParser.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.xmlDefinition;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.commons.digester.Digester;
+import org.xml.sax.SAXException;
+
+/**
+ * Parse an XML definitions file.
+ *
+ * @author Cedric Dumoulin
+ * @author David Geary
+ */
+public class XmlParser {
+ /** Associated digester. */
+ protected Digester digester;
+ /**
+ * Should we use a validating XML parser to read the configuration file.
+ * Default is <code>false</code>.
+ */
+ protected boolean validating = false;
+ /**
+ * The set of public identifiers, and corresponding resource names for
+ * the versions of the configuration file DTDs we know about. There
+ * <strong>MUST</strong> be an even number of Strings in this list!
+ */
+ protected String registrations[] = {
+ // pre 1.1
+ "-//Apache Software Foundation//DTD Tiles Configuration//EN",
+ "/org/apache/struts/resources/tiles-config_1_1.dtd",
+ "-//Apache Software Foundation//DTD Components Configuration//EN",
+ "/org/apache/struts/resources/tiles-config.dtd",
+ // version 1.1
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN",
+ "/org/apache/struts/resources/tiles-config_1_1.dtd",
+ // version 1.2
+ "-//Apache Software Foundation//DTD Tiles Configuration 1.2//EN",
+ "/org/apache/tiles/resources/tiles-config_1_2.dtd"
+ };
+
+ /**
+ * Constructor.
+ * Creates a digester parser and initializes syntax rules.
+ */
+ public XmlParser()
+ {
+ digester = new Digester();
+ digester.setValidating(validating);
+ digester.setNamespaceAware(true);
+ digester.setUseContextClassLoader(true);
+ // Register our local copy of the DTDs that we can find
+ for (int i = 0; i < registrations.length; i += 2) {
+ URL url = this.getClass().getResource(registrations[i+1]);
+ if (url != null)
+ {
+ digester.register(registrations[i], url.toString());
+ }
+ }
+ // Init syntax rules
+ initDigester( digester );
+ }
+
+ /**
+ * Set digester validating flag.
+ */
+ public void setValidating( boolean validating )
+ {
+ digester.setValidating( validating);
+ }
+
+
+ /**
+ * Init digester for components syntax.
+ * This is an old set of rules, left for backward compatibility.
+ * @param digester Digester instance to use.
+ */
+ private void initDigesterForComponentsDefinitionsSyntax( Digester digester )
+ {
+ // Common constants
+ String PACKAGE_NAME = "org.apache.tiles.xmlDefinition";
+ String DEFINITION_TAG = "component-definitions/definition";
+ String definitionHandlerClass = PACKAGE_NAME + ".XmlDefinition";
+
+ String PUT_TAG = DEFINITION_TAG + "/put";
+ String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute";
+
+ String LIST_TAG = DEFINITION_TAG + "/putList";
+ String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute";
+
+ String ADD_LIST_ELE_TAG = LIST_TAG + "/add";
+
+ // syntax rules
+ digester.addObjectCreate( DEFINITION_TAG, definitionHandlerClass );
+ digester.addSetProperties( DEFINITION_TAG);
+ digester.addSetNext( DEFINITION_TAG, "putDefinition", definitionHandlerClass);
+ // put / putAttribute rules
+ digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass);
+ digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass);
+ digester.addSetProperties( PUT_TAG);
+ digester.addCallMethod( PUT_TAG, "setBody", 0);
+ // list rules
+ digester.addObjectCreate( LIST_TAG, listHandlerClass);
+ digester.addSetProperties( LIST_TAG);
+ digester.addSetNext( LIST_TAG, "addAttribute", putAttributeHandlerClass);
+ // list elements rules
+ // We use Attribute class to avoid rewriting a new class.
+ // Name part can't be used in listElement attribute.
+ digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass);
+ digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
+ digester.addSetProperties( ADD_LIST_ELE_TAG);
+ digester.addCallMethod( ADD_LIST_ELE_TAG, "setBody", 0);
+ }
+
+ /**
+ * Init digester for Tiles syntax.
+ * Same as components, but with first element = tiles-definitions
+ * @param digester Digester instance to use.
+ */
+ private void initDigesterForTilesDefinitionsSyntax( Digester digester )
+ {
+ // Common constants
+ String PACKAGE_NAME = "org.apache.tiles.xmlDefinition";
+ String DEFINITION_TAG = "tiles-definitions/definition";
+ String definitionHandlerClass = PACKAGE_NAME + ".XmlDefinition";
+
+ String PUT_TAG = DEFINITION_TAG + "/put";
+ String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute";
+
+ //String LIST_TAG = DEFINITION_TAG + "/putList";
+ // List tag value
+ String LIST_TAG = "putList";
+ String DEF_LIST_TAG = DEFINITION_TAG + "/" + LIST_TAG;
+ String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute";
+ // Tag value for adding an element in a list
+ String ADD_LIST_ELE_TAG = "*/" + LIST_TAG + "/add";
+
+ // syntax rules
+ digester.addObjectCreate( DEFINITION_TAG, definitionHandlerClass );
+ digester.addSetProperties( DEFINITION_TAG);
+ digester.addSetNext( DEFINITION_TAG, "putDefinition", definitionHandlerClass);
+ // put / putAttribute rules
+ // Rules for a same pattern are called in order, but rule.end() are called
+ // in reverse order.
+ // SetNext and CallMethod use rule.end() method. So, placing SetNext in
+ // first position ensure it will be called last (sic).
+ digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass);
+ digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass);
+ digester.addSetProperties( PUT_TAG);
+ digester.addCallMethod( PUT_TAG, "setBody", 0);
+ // Definition level list rules
+ // This is rules for lists nested in a definition
+ digester.addObjectCreate( DEF_LIST_TAG, listHandlerClass);
+ digester.addSetProperties( DEF_LIST_TAG);
+ digester.addSetNext( DEF_LIST_TAG, "addAttribute", putAttributeHandlerClass);
+ // list elements rules
+ // We use Attribute class to avoid rewriting a new class.
+ // Name part can't be used in listElement attribute.
+ digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass);
+ digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
+ digester.addSetProperties( ADD_LIST_ELE_TAG);
+ digester.addCallMethod( ADD_LIST_ELE_TAG, "setBody", 0);
+
+ // nested list elements rules
+ // Create a list handler, and add it to parent list
+ String NESTED_LIST = "*/" + LIST_TAG + "/" + LIST_TAG;
+ digester.addObjectCreate( NESTED_LIST, listHandlerClass);
+ digester.addSetProperties( NESTED_LIST);
+ digester.addSetNext( NESTED_LIST, "add", putAttributeHandlerClass);
+
+ // item elements rules
+ // We use Attribute class to avoid rewriting a new class.
+ // Name part can't be used in listElement attribute.
+ //String ADD_WILDCARD = LIST_TAG + "/addItem";
+ // non String ADD_WILDCARD = LIST_TAG + "/addx*";
+ String ADD_WILDCARD = "*/item";
+ String menuItemDefaultClass = "org.apache.tiles.beans.SimpleMenuItem";
+ digester.addObjectCreate( ADD_WILDCARD, menuItemDefaultClass, "classtype");
+ digester.addSetNext( ADD_WILDCARD, "add", "java.lang.Object");
+ digester.addSetProperties( ADD_WILDCARD);
+
+ // bean elements rules
+ String BEAN_TAG = "*/bean";
+ String beanDefaultClass = "org.apache.tiles.beans.SimpleMenuItem";
+ digester.addObjectCreate( BEAN_TAG, beanDefaultClass, "classtype");
+ digester.addSetNext( BEAN_TAG, "add", "java.lang.Object");
+ digester.addSetProperties( BEAN_TAG);
+
+ // Set properties to surrounding element
+ digester.addSetProperty(BEAN_TAG+ "/set-property", "property", "value");
+ }
+
+ /**
+ * Init digester in order to parse instances definition file syntax.
+ * Instances is an old name for "definition". This method is left for
+ * backwards compatibility.
+ * @param digester Digester instance to use.
+ */
+ private void initDigesterForInstancesSyntax( Digester digester )
+ {
+ // Build a digester to process our configuration resource
+ String PACKAGE_NAME = "org.apache.tiles.xmlDefinition";
+ String INSTANCE_TAG = "component-instances/instance";
+ String instanceHandlerClass = PACKAGE_NAME + ".XmlDefinition";
+
+ String PUT_TAG = INSTANCE_TAG + "/put";
+ String PUTATTRIBUTE_TAG = INSTANCE_TAG + "/putAttribute";
+ String putAttributeHandlerClass = PACKAGE_NAME + ".XmlAttribute";
+
+ String LIST_TAG = INSTANCE_TAG + "/putList";
+ String listHandlerClass = PACKAGE_NAME + ".XmlListAttribute";
+
+ String ADD_LIST_ELE_TAG = LIST_TAG + "/add";
+
+ // component instance rules
+ digester.addObjectCreate( INSTANCE_TAG, instanceHandlerClass );
+ digester.addSetProperties( INSTANCE_TAG);
+ digester.addSetNext( INSTANCE_TAG, "putDefinition", instanceHandlerClass);
+ // put / putAttribute rules
+ digester.addObjectCreate( PUTATTRIBUTE_TAG, putAttributeHandlerClass);
+ digester.addSetProperties( PUTATTRIBUTE_TAG);
+ digester.addSetNext( PUTATTRIBUTE_TAG, "addAttribute", putAttributeHandlerClass);
+ // put / putAttribute rules
+ digester.addObjectCreate( PUT_TAG, putAttributeHandlerClass);
+ digester.addSetProperties( PUT_TAG);
+ digester.addSetNext( PUT_TAG, "addAttribute", putAttributeHandlerClass);
+ // list rules
+ digester.addObjectCreate( LIST_TAG, listHandlerClass);
+ digester.addSetProperties( LIST_TAG);
+ digester.addSetNext( LIST_TAG, "addAttribute", putAttributeHandlerClass);
+ // list elements rules
+ // We use Attribute class to avoid rewriting a new class.
+ // Name part can't be used in listElement attribute.
+ digester.addObjectCreate( ADD_LIST_ELE_TAG, putAttributeHandlerClass);
+ digester.addSetProperties( ADD_LIST_ELE_TAG);
+ digester.addSetNext( ADD_LIST_ELE_TAG, "add", putAttributeHandlerClass);
+ }
+
+ /**
+ * Init digester.
+ * @param digester Digester instance to use.
+ */
+ protected void initDigester( Digester digester )
+ {
+ initDigesterForTilesDefinitionsSyntax( digester );
+ initDigesterForComponentsDefinitionsSyntax( digester );
+ initDigesterForInstancesSyntax( digester );
+ }
+
+ /**
+ * Parse input reader and add encountered definitions to definitions set.
+ * @param in Input stream.
+ * @param definitions Xml Definitions set to which encountered definition are added.
+ * @throws IOException On errors during file parsing.
+ * @throws SAXException On errors parsing XML.
+ */
+ public void parse( InputStream in, XmlDefinitionsSet definitions ) throws IOException, SAXException
+ {
+ try
+ {
+ // set first object in stack
+ //digester.clear();
+ digester.push(definitions);
+ // parse
+ digester.parse(in);
+ in.close();
+ }
+ catch (SAXException e)
+ {
+ //throw new ServletException( "Error while parsing " + mappingConfig, e);
+ throw e;
+ }
+
+ }
+
+ /**
+ * Main method to check file syntax.
+ */
+ public static void main(String[] args)
+ {
+ //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-struts/WEB-INF/tiles-examples-defs.xml";
+ String filename = "E:/programs/jakarta-tomcat-4.0.3/webapps/wtiles-struts/WEB-INF/tiles-examples-defs.xml";
+ //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-struts/WEB-INF/tilesDefinitions.xml";
+ //String filename = "E:/programs/jakarta-tomcat/webapps/wtiles-channel/WEB-INF/componentDefinitions.xml";
+ //String filename2 = "E:/programs/jakarta-tomcat/webapps/wtiles-tutorial/WEB-INF/componentDefinitions.xml";
+
+
+ if( args.length > 1 )
+ {
+ filename = args[1];
+ } // end if
+
+ System.out.println( "Read file '" + filename +"'" );
+
+ InputStream input = null;
+ // InputStream input2 = null;
+ // Open file
+ try
+ {
+ input = new BufferedInputStream(
+ new FileInputStream( filename) );
+ // input2 = new BufferedInputStream(
+ // new FileInputStream( filename2) );
+ }
+ catch( IOException ex )
+ {
+ System.out.println( "can't open file '" + filename + "' : " + ex.getMessage() );
+ }
+ // Check file syntax
+ try
+ {
+ XmlParser parser = new XmlParser();
+ parser.setValidating(true);
+ XmlDefinitionsSet definitions = new XmlDefinitionsSet();
+ System.out.println( " Parse file" );
+ parser.parse( input, definitions);
+ // System.out.println( " Check file 2" );
+ //parser.parse( input2, definitions);
+ System.out.println( " done." );
+ System.out.println( " Result : " + definitions.toString() );
+ }
+ catch( Exception ex )
+ {
+ System.out.println( "Error during parsing '" + filename + "' : " + ex.getMessage() );
+ ex.printStackTrace();
+ }
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/sub b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/sub
new file mode 100644
index 0000000..cf52f3d
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/tiles/xmlDefinition/sub
@@ -0,0 +1,3 @@
+2,/^END/{
+ /org.apache.struts.tiles/s//org.apache.tiles/g
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/MessageResources.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/MessageResources.java
new file mode 100755
index 0000000..285740b
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/MessageResources.java
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.util;
+
+import java.io.Serializable;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Locale;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * General purpose abstract class that describes an API for retrieving
+ * Locale-sensitive messages from underlying resource locations of an
+ * unspecified design, and optionally utilizing the <code>MessageFormat</code>
+ * class to produce internationalized messages with parametric replacement.
+ * <p>
+ * Calls to <code>getMessage()</code> variants without a <code>Locale</code>
+ * argument are presumed to be requesting a message string in the default
+ * <code>Locale</code> for this JVM.
+ * <p>
+ * Calls to <code>getMessage()</code> with an unknown key, or an unknown
+ * <code>Locale</code> will return <code>null</code> if the
+ * <code>returnNull</code> property is set to <code>true</code>. Otherwise,
+ * a suitable error message will be returned instead.
+ * <p>
+ * <strong>IMPLEMENTATION NOTE</strong> - Classes that extend this class
+ * must be Serializable so that instances may be used in distributable
+ * application server environments.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.18 $ $Date: 2003/07/02 03:42:09 $
+ */
+public abstract class MessageResources implements Serializable {
+
+ // ------------------------------------------------------------- Properties
+
+ /**
+ * Commons Logging instance.
+ */
+ protected static Log log = LogFactory.getLog(MessageResources.class);
+
+ /**
+ * The configuration parameter used to initialize this MessageResources.
+ */
+ protected String config = null;
+
+ /**
+ * The configuration parameter used to initialize this MessageResources.
+ * @return parameter used to initialize this MessageResources
+ */
+ public String getConfig() {
+ return (this.config);
+ }
+
+ /**
+ * The default Locale for our environment.
+ */
+ protected Locale defaultLocale = Locale.getDefault();
+
+ /**
+ * The <code>MessageResourcesFactory</code> that created this instance.
+ */
+ protected MessageResourcesFactory factory = null;
+
+ /**
+ * The <code>MessageResourcesFactory</code> that created this instance.
+ * @return <code>MessageResourcesFactory</code> that created instance
+ */
+ public MessageResourcesFactory getFactory() {
+ return (this.factory);
+ }
+
+ /**
+ * The set of previously created MessageFormat objects, keyed by the
+ * key computed in <code>messageKey()</code>.
+ */
+ protected HashMap formats = new HashMap();
+
+ /**
+ * Indicate is a <code>null</code> is returned instead of an error message string
+ * when an unknown Locale or key is requested.
+ */
+ protected boolean returnNull = false;
+
+ /**
+ * Indicates that a <code>null</code> is returned instead of an error message string
+ * if an unknown Locale or key is requested.
+ * @return true if null is returned if unknown key or locale is requested
+ */
+ public boolean getReturnNull() {
+ return (this.returnNull);
+ }
+
+ /**
+ * Indicates that a <code>null</code> is returned instead of an error message string
+ * if an unknown Locale or key is requested.
+ * @param returnNull true Indicates that a <code>null</code> is returned
+ * if an unknown Locale or key is requested.
+ */
+ public void setReturnNull(boolean returnNull) {
+ this.returnNull = returnNull;
+ }
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new MessageResources according to the specified parameters.
+ *
+ * @param factory The MessageResourcesFactory that created us
+ * @param config The configuration parameter for this MessageResources
+ */
+ public MessageResources(MessageResourcesFactory factory, String config) {
+
+ this(factory, config, false);
+
+ }
+
+ /**
+ * Construct a new MessageResources according to the specified parameters.
+ *
+ * @param factory The MessageResourcesFactory that created us
+ * @param config The configuration parameter for this MessageResources
+ * @param returnNull The returnNull property we should initialize with
+ */
+ public MessageResources(
+ MessageResourcesFactory factory,
+ String config,
+ boolean returnNull) {
+
+ super();
+ this.factory = factory;
+ this.config = config;
+ this.returnNull = returnNull;
+
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Returns a text message for the specified key, for the default Locale.
+ *
+ * @param key The message key to look up
+ */
+ public String getMessage(String key) {
+
+ return this.getMessage((Locale) null, key);
+
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders.
+ *
+ * @param key The message key to look up
+ * @param args An array of replacement parameters for placeholders
+ */
+ public String getMessage(String key, Object args[]) {
+
+ return this.getMessage((Locale) null, key, args);
+
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders.
+ *
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ */
+ public String getMessage(String key, Object arg0) {
+
+ return this.getMessage((Locale) null, key, arg0);
+
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders.
+ *
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ * @param arg1 The replacement for placeholder {1} in the message
+ */
+ public String getMessage(String key, Object arg0, Object arg1) {
+
+ return this.getMessage((Locale) null, key, arg0, arg1);
+
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders.
+ *
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ * @param arg1 The replacement for placeholder {1} in the message
+ * @param arg2 The replacement for placeholder {2} in the message
+ */
+ public String getMessage(String key, Object arg0, Object arg1, Object arg2) {
+
+ return this.getMessage((Locale) null, key, arg0, arg1, arg2);
+
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders.
+ *
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ * @param arg1 The replacement for placeholder {1} in the message
+ * @param arg2 The replacement for placeholder {2} in the message
+ * @param arg3 The replacement for placeholder {3} in the message
+ */
+ public String getMessage(
+ String key,
+ Object arg0,
+ Object arg1,
+ Object arg2,
+ Object arg3) {
+
+ return this.getMessage((Locale) null, key, arg0, arg1, arg2, arg3);
+
+ }
+
+ /**
+ * Returns a text message for the specified key, for the default Locale.
+ * A null string result will be returned by this method if no relevant
+ * message resource is found for this key or Locale, if the
+ * <code>returnNull</code> property is set. Otherwise, an appropriate
+ * error message will be returned.
+ * <p>
+ * This method must be implemented by a concrete subclass.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ */
+ public abstract String getMessage(Locale locale, String key);
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders. A null string result will be returned by
+ * this method if no resource bundle has been configured.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ * @param args An array of replacement parameters for placeholders
+ */
+ public String getMessage(Locale locale, String key, Object args[]) {
+
+ // Cache MessageFormat instances as they are accessed
+ if (locale == null) {
+ locale = defaultLocale;
+ }
+
+ MessageFormat format = null;
+ String formatKey = messageKey(locale, key);
+
+ synchronized (formats) {
+ format = (MessageFormat) formats.get(formatKey);
+ if (format == null) {
+ String formatString = getMessage(locale, key);
+
+ if (formatString == null) {
+ return returnNull ? null : ("???" + formatKey + "???");
+ }
+
+ format = new MessageFormat(escape(formatString));
+ formats.put(formatKey, format);
+ }
+
+ }
+
+ return format.format(args);
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders. A null string result will never be returned
+ * by this method.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ */
+ public String getMessage(Locale locale, String key, Object arg0) {
+ return this.getMessage(locale, key, new Object[] { arg0 });
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders. A null string result will never be returned
+ * by this method.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ * @param arg1 The replacement for placeholder {1} in the message
+ */
+ public String getMessage(Locale locale, String key, Object arg0, Object arg1) {
+ return this.getMessage(locale, key, new Object[] { arg0, arg1 });
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders. A null string result will never be returned
+ * by this method.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ * @param arg1 The replacement for placeholder {1} in the message
+ * @param arg2 The replacement for placeholder {2} in the message
+ */
+ public String getMessage(
+ Locale locale,
+ String key,
+ Object arg0,
+ Object arg1,
+ Object arg2) {
+
+ return this.getMessage(locale, key, new Object[] { arg0, arg1, arg2 });
+ }
+
+ /**
+ * Returns a text message after parametric replacement of the specified
+ * parameter placeholders. A null string result will never be returned
+ * by this method.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ * @param arg0 The replacement for placeholder {0} in the message
+ * @param arg1 The replacement for placeholder {1} in the message
+ * @param arg2 The replacement for placeholder {2} in the message
+ * @param arg3 The replacement for placeholder {3} in the message
+ */
+ public String getMessage(
+ Locale locale,
+ String key,
+ Object arg0,
+ Object arg1,
+ Object arg2,
+ Object arg3) {
+
+ return this.getMessage(locale, key, new Object[] { arg0, arg1, arg2, arg3 });
+ }
+
+ /**
+ * Return <code>true</code> if there is a defined message for the specified
+ * key in the system default locale.
+ *
+ * @param key The message key to look up
+ */
+ public boolean isPresent(String key) {
+
+ return this.isPresent(null, key);
+
+ }
+
+ /**
+ * Return <code>true</code> if there is a defined message for the specified
+ * key in the specified Locale.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ */
+ public boolean isPresent(Locale locale, String key) {
+
+ String message = getMessage(locale, key);
+
+ if (message == null) {
+ return false;
+
+ } else if (message.startsWith("???") && message.endsWith("???")) {
+ return false; // FIXME - Only valid for default implementation
+
+ } else {
+ return true;
+ }
+
+ }
+
+ // ------------------------------------------------------ Protected Methods
+
+ /**
+ * Escape any single quote characters that are included in the specified
+ * message string.
+ *
+ * @param string The string to be escaped
+ */
+ protected String escape(String string) {
+
+ if ((string == null) || (string.indexOf('\'') < 0)) {
+ return string;
+ }
+
+ int n = string.length();
+ StringBuffer sb = new StringBuffer(n);
+
+ for (int i = 0; i < n; i++) {
+ char ch = string.charAt(i);
+
+ if (ch == '\'') {
+ sb.append('\'');
+ }
+
+ sb.append(ch);
+ }
+
+ return sb.toString();
+
+ }
+
+ /**
+ * Compute and return a key to be used in caching information by a Locale.
+ * <strong>NOTE</strong> - The locale key for the default Locale in our
+ * environment is a zero length String.
+ *
+ * @param locale The locale for which a key is desired
+ */
+ protected String localeKey(Locale locale) {
+ return (locale == null) ? "" : locale.toString();
+ }
+
+ /**
+ * Compute and return a key to be used in caching information
+ * by Locale and message key.
+ *
+ * @param locale The Locale for which this format key is calculated
+ * @param key The message key for which this format key is calculated
+ */
+ protected String messageKey(Locale locale, String key) {
+
+ return (localeKey(locale) + "." + key);
+
+ }
+
+ /**
+ * Compute and return a key to be used in caching information
+ * by locale key and message key.
+ *
+ * @param localeKey The locale key for which this cache key is calculated
+ * @param key The message key for which this cache key is calculated
+ */
+ protected String messageKey(String localeKey, String key) {
+
+ return (localeKey + "." + key);
+
+ }
+
+ // --------------------------------------------------------- Static Methods
+
+ /**
+ * The default MessageResourcesFactory used to create MessageResources
+ * instances.
+ */
+ protected static MessageResourcesFactory defaultFactory = null;
+
+ /**
+ * Create and return an instance of <code>MessageResources</code> for the
+ * created by the default <code>MessageResourcesFactory</code>.
+ *
+ * @param config Configuration parameter for this message bundle.
+ */
+ public synchronized static MessageResources getMessageResources(String config) {
+
+ if (defaultFactory == null) {
+ defaultFactory = MessageResourcesFactory.createFactory();
+ }
+
+ return defaultFactory.createResources(config);
+ }
+
+ /**
+ * Log a message to the Writer that has been configured for our use.
+ *
+ * @param message The message to be logged
+ */
+ public void log(String message) {
+ log.debug(message);
+ }
+
+ /**
+ * Log a message and exception to the Writer that has been configured
+ * for our use.
+ *
+ * @param message The message to be logged
+ * @param throwable The exception to be logged
+ */
+ public void log(String message, Throwable throwable) {
+ log.debug(message, throwable);
+ }
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/MessageResourcesFactory.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/MessageResourcesFactory.java
new file mode 100644
index 0000000..9097d98
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/MessageResourcesFactory.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.util;
+
+import java.io.Serializable;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.tiles.TilesUtil;
+
+
+/**
+ * Factory for <code>MessageResources</code> instances. The general usage
+ * pattern for this class is:
+ * <ul>
+ * <li>Call <code>MessageResourcesFactory().createFactory()</code> to retrieve
+ * a <code>MessageResourcesFactory</code> instance.</li>
+ * <li>Set properties as required to configure this factory instance to create
+ * <code>MessageResources</code> instances with desired
+ * characteristics.</li>
+ * <li>Call the <code>createResources()</code> method of the factory to
+ * retrieve a newly instantiated <code>MessageResources</code>
+ * instance.</li>
+ * </ul>
+ *
+ * @author Craig R. McClanahan
+ * @author David Geary
+ * @version $Revision: 1.8 $ $Date: 2002/10/17 03:20:31 $
+ */
+
+public abstract class MessageResourcesFactory implements Serializable {
+
+
+ // ---------------------------------------------------- Instance Properties
+
+
+ /**
+ * The "return null" property value to which newly created
+ * MessageResourcess should be initialized.
+ */
+ protected boolean returnNull = true;
+
+ /**
+ * Get default value of the "returnNull" property used to initialize newly created
+ * MessageResourcess.
+ * @return default value of the "returnNull" property newly created
+ * MessageResourcess are initialized to.
+ */
+ public boolean getReturnNull() {
+ return (this.returnNull);
+ }
+
+ /**
+ * Set the default value of the "returnNull" property newly created
+ * MessageResourcess are initialized to.
+ * @param returnNull default value of the "returnNull" MessageResourcess are initialized to.
+ */
+ public void setReturnNull(boolean returnNull) {
+ this.returnNull = returnNull;
+ }
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Create and return a newly instansiated <code>MessageResources</code>.
+ * This method must be implemented by concrete subclasses.
+ *
+ * @param config Configuration parameter(s) for the requested bundle
+ */
+ public abstract MessageResources createResources(String config);
+
+
+ // ------------------------------------------------------ Static Properties
+
+
+ /**
+ * The Java class to be used for
+ * <code>MessageResourcesFactory</code> instances.
+ */
+ protected static transient Class clazz = null;
+
+
+ /**
+ * Commons Logging instance.
+ */
+ private static Log LOG = LogFactory.getLog(MessageResourcesFactory.class);
+
+
+ /**
+ * The fully qualified class name to be used for
+ * <code>MessageResourcesFactory</code> instances.
+ */
+ protected static String factoryClass =
+ "org.apache.util.PropertyMessageResourcesFactory";
+
+ /**
+ * The fully qualified class name that is used for
+ * <code>MessageResourcesFactory</code> instances.
+ * @return class name that is used for
+ * <code>MessageResourcesFactory</code> instances
+ */
+ public static String getFactoryClass() {
+ return (MessageResourcesFactory.factoryClass);
+ }
+
+ /**
+ * Set the fully qualified class name that is used for
+ * <code>MessageResourcesFactory</code> instances.
+ * @param factoryClass name that is used for
+ * <code>MessageResourcesFactory</code> instances
+ */
+ public static void setFactoryClass(String factoryClass) {
+ MessageResourcesFactory.factoryClass = factoryClass;
+ MessageResourcesFactory.clazz = null;
+ }
+
+
+ // --------------------------------------------------------- Static Methods
+
+
+ /**
+ * Create and return a <code>MessageResourcesFactory</code> instance of the
+ * appropriate class, which can be used to create customized
+ * <code>MessageResources</code> instances. If no such factory can be
+ * created, return <code>null</code> instead.
+ */
+ public static MessageResourcesFactory createFactory() {
+
+ // Construct a new instance of the specified factory class
+ try {
+ if (clazz == null)
+ clazz = TilesUtil.applicationClass(factoryClass);
+ MessageResourcesFactory factory =
+ (MessageResourcesFactory) clazz.newInstance();
+ return (factory);
+ } catch (Throwable t) {
+ LOG.error("MessageResourcesFactory.createFactory", t);
+ return (null);
+ }
+
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/PropertyMessageResources.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/PropertyMessageResources.java
new file mode 100644
index 0000000..3ddf016
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/PropertyMessageResources.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Concrete subclass of <code>MessageResources</code> that reads message keys
+ * and corresponding strings from named property resources in the same manner
+ * that <code>java.util.PropertyResourceBundle</code> does. The
+ * <code>base</code> property defines the base property resource name, and
+ * must be specified.
+ * <p>
+ * <strong>IMPLEMENTATION NOTE</strong> - This class trades memory for
+ * speed by caching all messages located via generalizing the Locale under
+ * the original locale as well.
+ * This results in specific messages being stored in the message cache
+ * more than once, but improves response time on subsequent requests for
+ * the same locale + key combination.
+ *
+ * @author Craig R. McClanahan
+ * @author David Graham
+ * @version $Revision: 1.8 $ $Date: 2003/04/19 19:06:02 $
+ */
+public class PropertyMessageResources extends MessageResources {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new PropertyMessageResources according to the
+ * specified parameters.
+ *
+ * @param factory The MessageResourcesFactory that created us
+ * @param config The configuration parameter for this MessageResources
+ */
+ public PropertyMessageResources(MessageResourcesFactory factory,
+ String config) {
+
+ super(factory, config);
+ log.info("Initializing, config='" + config + "'");
+
+ }
+
+
+ /**
+ * Construct a new PropertyMessageResources according to the
+ * specified parameters.
+ *
+ * @param factory The MessageResourcesFactory that created us
+ * @param config The configuration parameter for this MessageResources
+ * @param returnNull The returnNull property we should initialize with
+ */
+ public PropertyMessageResources(MessageResourcesFactory factory,
+ String config, boolean returnNull) {
+
+ super(factory, config, returnNull);
+ log.info("Initializing, config='" + config +
+ "', returnNull=" + returnNull);
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * The set of locale keys for which we have already loaded messages, keyed
+ * by the value calculated in <code>localeKey()</code>.
+ */
+ protected HashMap locales = new HashMap();
+
+
+ /**
+ * The <code>Log</code> instance for this class.
+ */
+ protected static final Log log =
+ LogFactory.getLog(PropertyMessageResources.class);
+
+
+ /**
+ * The cache of messages we have accumulated over time, keyed by the
+ * value calculated in <code>messageKey()</code>.
+ */
+ protected HashMap messages = new HashMap();
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Returns a text message for the specified key, for the default Locale.
+ * A null string result will be returned by this method if no relevant
+ * message resource is found for this key or Locale, if the
+ * <code>returnNull</code> property is set. Otherwise, an appropriate
+ * error message will be returned.
+ * <p>
+ * This method must be implemented by a concrete subclass.
+ *
+ * @param locale The requested message Locale, or <code>null</code>
+ * for the system default Locale
+ * @param key The message key to look up
+ * @return text message for the specified key and locale
+ */
+ public String getMessage(Locale locale, String key) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("getMessage(" + locale + "," + key + ")");
+ }
+
+ // Initialize variables we will require
+ String localeKey = localeKey(locale);
+ String originalKey = messageKey(localeKey, key);
+ String messageKey = null;
+ String message = null;
+ int underscore = 0;
+ boolean addIt = false; // Add if not found under the original key
+
+ // Loop from specific to general Locales looking for this message
+ while (true) {
+
+ // Load this Locale's messages if we have not done so yet
+ loadLocale(localeKey);
+
+ // Check if we have this key for the current locale key
+ messageKey = messageKey(localeKey, key);
+ synchronized (messages) {
+ message = (String) messages.get(messageKey);
+ if (message != null) {
+ if (addIt) {
+ messages.put(originalKey, message);
+ }
+ return (message);
+ }
+ }
+
+ // Strip trailing modifiers to try a more general locale key
+ addIt = true;
+ underscore = localeKey.lastIndexOf("_");
+ if (underscore < 0) {
+ break;
+ }
+ localeKey = localeKey.substring(0, underscore);
+
+ }
+
+ // Try the default locale if the current locale is different
+ if (!defaultLocale.equals(locale)) {
+ localeKey = localeKey(defaultLocale);
+ messageKey = messageKey(localeKey, key);
+ loadLocale(localeKey);
+ synchronized (messages) {
+ message = (String) messages.get(messageKey);
+ if (message != null) {
+ messages.put(originalKey, message);
+ return (message);
+ }
+ }
+ }
+
+ // As a last resort, try the default Locale
+ localeKey = "";
+ messageKey = messageKey(localeKey, key);
+ loadLocale(localeKey);
+ synchronized (messages) {
+ message = (String) messages.get(messageKey);
+ if (message != null) {
+ messages.put(originalKey, message);
+ return (message);
+ }
+ }
+
+ // Return an appropriate error indication
+ if (returnNull) {
+ return (null);
+ } else {
+ return ("???" + messageKey(locale, key) + "???");
+ }
+
+ }
+
+
+ // ------------------------------------------------------ Protected Methods
+
+
+ /**
+ * Load the messages associated with the specified Locale key. For this
+ * implementation, the <code>config</code> property should contain a fully
+ * qualified package and resource name, separated by periods, of a series
+ * of property resources to be loaded from the class loader that created
+ * this PropertyMessageResources instance. This is exactly the same name
+ * format you would use when utilizing the
+ * <code>java.util.PropertyResourceBundle</code> class.
+ *
+ * @param localeKey Locale key for the messages to be retrieved
+ */
+ protected synchronized void loadLocale(String localeKey) {
+
+ if (log.isTraceEnabled()) {
+ log.trace("loadLocale(" + localeKey + ")");
+ }
+
+ // Have we already attempted to load messages for this locale?
+ if (locales.get(localeKey) != null) {
+ return;
+ }
+ locales.put(localeKey, localeKey);
+
+ // Set up to load the property resource for this locale key, if we can
+ String name = config.replace('.', '/');
+ if (localeKey.length() > 0) {
+ name += "_" + localeKey;
+ }
+ name += ".properties";
+ InputStream is = null;
+ Properties props = new Properties();
+
+ // Load the specified property resource
+ if (log.isTraceEnabled()) {
+ log.trace(" Loading resource '" + name + "'");
+ }
+
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = this.getClass().getClassLoader();
+ }
+
+ is = classLoader.getResourceAsStream(name);
+ if (is != null) {
+ try {
+ props.load(is);
+
+ } catch (IOException e) {
+ log.error("loadLocale()", e);
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ log.error("loadLocale()", e);
+ }
+ }
+ }
+
+ if (log.isTraceEnabled()) {
+ log.trace(" Loading resource completed");
+ }
+
+ // Copy the corresponding values into our cache
+ if (props.size() < 1) {
+ return;
+ }
+
+ synchronized (messages) {
+ Iterator names = props.keySet().iterator();
+ while (names.hasNext()) {
+ String key = (String) names.next();
+ if (log.isTraceEnabled()) {
+ log.trace(" Saving message key '" + messageKey(localeKey, key));
+ }
+ messages.put(messageKey(localeKey, key), props.getProperty(key));
+ }
+ }
+
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/PropertyMessageResourcesFactory.java b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/PropertyMessageResourcesFactory.java
new file mode 100644
index 0000000..69340ea
--- /dev/null
+++ b/struts-sandbox/tiles-original/core-library/src/java/org/apache/util/PropertyMessageResourcesFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.util;
+
+
+/**
+ * Factory for <code>PropertyMessageResources</code> instances. The
+ * configuration paramter for such instances is the base Java package
+ * name of the resources entries from which our keys and values will be
+ * loaded.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.2 $ $Date: 2001/02/12 00:32:14 $
+ */
+
+public class PropertyMessageResourcesFactory extends MessageResourcesFactory {
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Create and return a newly instansiated <code>MessageResources</code>.
+ * This method must be implemented by concrete subclasses.
+ *
+ * @param config Configuration parameter(s) for the requested bundle
+ */
+ public MessageResources createResources(String config) {
+
+ return new PropertyMessageResources(this, config, this.returnNull);
+
+ }
+
+
+}
diff --git a/struts-sandbox/tiles-original/examples/simple/README.txt b/struts-sandbox/tiles-original/examples/simple/README.txt
new file mode 100644
index 0000000..149450f
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/README.txt
@@ -0,0 +1,5 @@
+This is a simple application that illustrates fundamental Tiles concepts. The application is documented in the file tiles.pdf, in the top-level directory of the Tiles distribution.
+
+Copy the contents of this directory into a directory in your servlet container's
+webapps directory. Depending on your container, you may have to restart the
+container to access the application you just created.
diff --git a/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/commons-beanutils.jar b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/commons-beanutils.jar
new file mode 100644
index 0000000..795655a
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/commons-beanutils.jar
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/commons-digester.jar b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/commons-digester.jar
new file mode 100644
index 0000000..c2a7d9d
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/commons-digester.jar
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/jstl.jar b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/jstl.jar
new file mode 100644
index 0000000..6d02845
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/jstl.jar
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/standard.jar b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/standard.jar
new file mode 100644
index 0000000..f457646
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/standard.jar
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/tiles-core.jar b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/tiles-core.jar
new file mode 100644
index 0000000..bbadd47
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/WEB-INF/lib/tiles-core.jar
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/WEB-INF/tiles.xml b/struts-sandbox/tiles-original/examples/simple/WEB-INF/tiles.xml
new file mode 100644
index 0000000..175a61a
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/WEB-INF/tiles.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE tiles-definitions PUBLIC
+ "-//Apache Software Foundation//DTD Tiles Configuration//EN"
+ "http://jakarta.apache.org/struts/dtds/tiles-config.dtd">
+
+<tiles-definitions>
+ <definition name="header-footer-sidebar"
+ path="/header-footer-sidebar-layout.jsp">
+ <put name="header" value="/header.jsp"/>
+ <put name="sidebar" value="/sidebar.jsp"/>
+ <put name="content"/>
+ <put name="footer" value="/footer.jsp"/>
+ </definition>
+
+ <definition name="login-tile" extends="header-footer-sidebar">
+ <put name="content" value="/loginContent.jsp"/>
+ </definition>
+
+ <definition name="preferences-tile" extends="header-footer-sidebar">
+ <put name="content" value="/preferencesContent.jsp"/>
+ </definition>
+</tiles-definitions>
diff --git a/struts-sandbox/tiles-original/examples/simple/WEB-INF/web.xml b/struts-sandbox/tiles-original/examples/simple/WEB-INF/web.xml
new file mode 100644
index 0000000..9f0c4b4
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
+ "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
+
+<web-app>
+ <servlet>
+ <servlet-name>Tiles Servlet</servlet-name>
+ <servlet-class>org.apache.tiles.servlets.TilesServlet</servlet-class>
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles.xml</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <!-- Define the welcome file -->
+ <welcome-file-list>
+ <welcome-file>/login.jsp</welcome-file>
+ </welcome-file-list>
+</web-app>
+
+
diff --git a/struts-sandbox/tiles-original/examples/simple/footer.jsp b/struts-sandbox/tiles-original/examples/simple/footer.jsp
new file mode 100644
index 0000000..0a6c6dd
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/footer.jsp
@@ -0,0 +1 @@
+<hr>Thanks for stopping by on <%= new java.util.Date() %>
diff --git a/struts-sandbox/tiles-original/examples/simple/graphics/blueAndWhiteBackground.gif b/struts-sandbox/tiles-original/examples/simple/graphics/blueAndWhiteBackground.gif
new file mode 100644
index 0000000..b7abf5c
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/graphics/blueAndWhiteBackground.gif
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/graphics/flags/britain_flag.gif b/struts-sandbox/tiles-original/examples/simple/graphics/flags/britain_flag.gif
new file mode 100644
index 0000000..3acb3ac
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/graphics/flags/britain_flag.gif
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/graphics/flags/chinese_flag.gif b/struts-sandbox/tiles-original/examples/simple/graphics/flags/chinese_flag.gif
new file mode 100644
index 0000000..fc80664
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/graphics/flags/chinese_flag.gif
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/graphics/flags/german_flag.gif b/struts-sandbox/tiles-original/examples/simple/graphics/flags/german_flag.gif
new file mode 100644
index 0000000..e7ff41f
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/graphics/flags/german_flag.gif
Binary files differ
diff --git a/struts-sandbox/tiles-original/examples/simple/header-footer-sidebar-layout.jsp b/struts-sandbox/tiles-original/examples/simple/header-footer-sidebar-layout.jsp
new file mode 100644
index 0000000..c993c3c
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/header-footer-sidebar-layout.jsp
@@ -0,0 +1,39 @@
+<%@ taglib uri="http://jakarta.apache.org/tiles"
+ prefix="tiles" %>
+
+ <%-- One table lays out all of the content for this attribute --%>
+ <table width='100%' height='100%'>
+ <tr>
+
+ <%-- Sidebar section --%>
+ <td width='150' valign='top' align='left'>
+ <tiles:insert attribute='sidebar'/>
+ </td>
+
+ <%-- Main content section --%>
+ <td height='100%' width='*'>
+ <table width='100%' height='100%'>
+ <tr>
+ <%-- Header section --%>
+ <td valign='top' height='15%'>
+ <tiles:insert attribute='header'/>
+ </td>
+ <tr>
+
+ <tr>
+ <%-- Content section --%>
+ <td valign='top' height='*'>
+ <tiles:insert attribute='content'/>
+ </td>
+ </tr>
+
+ <tr>
+ <%-- Footer section --%>
+ <td valign='bottom' height='15%'>
+ <tiles:insert attribute='footer'/>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
diff --git a/struts-sandbox/tiles-original/examples/simple/header.jsp b/struts-sandbox/tiles-original/examples/simple/header.jsp
new file mode 100644
index 0000000..03f3ca4
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/header.jsp
@@ -0,0 +1,2 @@
+<font size='6'>Tiles</font>
+<hr>
diff --git a/struts-sandbox/tiles-original/examples/simple/login.jsp b/struts-sandbox/tiles-original/examples/simple/login.jsp
new file mode 100644
index 0000000..b2dc403
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/login.jsp
@@ -0,0 +1,12 @@
+<%@ taglib uri="http://jakarta.apache.org/tiles" prefix="tiles" %>
+
+<html>
+ <head>
+ <title>Login</title>
+ </head>
+
+ <body background="graphics/blueAndWhiteBackground.gif">
+ <tiles:insert definition="login-tile"/>
+ </body>
+</html>
+
diff --git a/struts-sandbox/tiles-original/examples/simple/loginContent.jsp b/struts-sandbox/tiles-original/examples/simple/loginContent.jsp
new file mode 100644
index 0000000..09c4a97
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/loginContent.jsp
@@ -0,0 +1,23 @@
+<font size='5'>Please log in</font>
+<p>
+<table>
+ <tr>
+ <td>
+ Name:
+ </td>
+ <td>
+ <input type="text"/>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Password
+ </td>
+ <td>
+ <input type="secret" size="8"/>
+ </td>
+ </tr>
+</table>
+<p>
+<input type="submit" value="Log in"/>
+
diff --git a/struts-sandbox/tiles-original/examples/simple/preferences.jsp b/struts-sandbox/tiles-original/examples/simple/preferences.jsp
new file mode 100644
index 0000000..9929b7c
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/preferences.jsp
@@ -0,0 +1,12 @@
+<%@ taglib uri="http://jakarta.apache.org/tiles" prefix="tiles" %>
+
+<html>
+ <head>
+ <title>Preferences</title>
+ </head>
+
+ <body background="graphics/blueAndWhiteBackground.gif">
+ <tiles:insert definition="preferences-tile"/>
+ </body>
+</html>
+
diff --git a/struts-sandbox/tiles-original/examples/simple/preferencesContent.jsp b/struts-sandbox/tiles-original/examples/simple/preferencesContent.jsp
new file mode 100644
index 0000000..7972b8a
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/preferencesContent.jsp
@@ -0,0 +1,48 @@
+<font size='5'>Change your preferences</font>
+<p>
+<table>
+ <tr>
+ <td>
+ Standard font:
+ </td>
+ <td>
+ <input type="text" value="Arial 13"/>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Fixed-width font:
+ </td>
+ <td>
+ <input type="text" value="Helvetica 12"/>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Smallest allowable font size:
+ </td>
+ <td>
+ <input type="text" size="3" value="5"/>
+ <input type="submit" value="<"/>
+ <input type="submit" value=">"/>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Display images when page opens
+ </td>
+ <td>
+ <input type="checkbox"/>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Underline links
+ </td>
+ <td>
+ <input type="checkbox"/>
+ </td>
+ </tr>
+</table>
+<p>
+<input type="submit" value="Set preferences"/>
diff --git a/struts-sandbox/tiles-original/examples/simple/sidebar.jsp b/struts-sandbox/tiles-original/examples/simple/sidebar.jsp
new file mode 100644
index 0000000..52b35a1
--- /dev/null
+++ b/struts-sandbox/tiles-original/examples/simple/sidebar.jsp
@@ -0,0 +1,31 @@
+<%@ page contentType='text/html; charset=UTF-8' %>
+<%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %>
+
+<table width='100%'>
+ <tr>
+ <%-- Sidebar top component --%>
+ <td width='150' height='50' valign='top' align='left'>
+ <a href=''><img src='graphics/flags/britain_flag.gif' style='border: 0px'/></a>
+ <a href=''><img src='graphics/flags/german_flag.gif' style='border: 0px'/></a>
+ <a href=''><img src='graphics/flags/chinese_flag.gif' style='border: 0px'/></a>
+ </td>
+ </tr>
+
+ <tr>
+ <%-- Sidebar bottom component --%>
+ <td>
+ <table>
+ <tr>
+ <td>
+ <font size='5'>Links</font><p>
+ <a href=''>Home</a><br>
+ <a href=''>Products</a><br>
+ <a href=''>Downloads</a><br>
+ <a href=''>White papers</a><br>
+ <a href=''>Contact us</a><br>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
diff --git a/struts-sandbox/tiles-original/tiles.pdf b/struts-sandbox/tiles-original/tiles.pdf
new file mode 100644
index 0000000..e4c54d4
--- /dev/null
+++ b/struts-sandbox/tiles-original/tiles.pdf
Binary files differ
diff --git a/struts-sandbox/workflow/ActivityAction.java b/struts-sandbox/workflow/ActivityAction.java
new file mode 100644
index 0000000..6c89576
--- /dev/null
+++ b/struts-sandbox/workflow/ActivityAction.java
@@ -0,0 +1,404 @@
+/*
+ * $Id$
+ *
+ * Copyright 2001,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.action;
+
+import java.io.IOException;
+
+
+import javax.servlet.ServletException;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionError;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionServlet;
+
+import org.apache.commons.workflow.Activity;
+import org.apache.commons.workflow.Step;
+import org.apache.commons.workflow.StepException;
+import org.apache.commons.workflow.Context;
+import org.apache.commons.workflow.ContextEvent;
+import org.apache.commons.workflow.ContextListener;
+import org.apache.commons.workflow.Registry;
+
+import org.apache.commons.workflow.web.WebContext;
+
+
+
+/**
+ * @author Craig McClanahan
+ * @author Ted Husted
+ * @version $Rev$ $Date$
+ */
+public class ActivityAction extends Action implements ContextListener {
+
+
+// --------------------------------------------------------- Instance Variables
+
+
+ // ** FOR THREAD-SAFETY THESE MUST BE GLOBAL TO APPLICATION
+ // ** AND NOT SPECIFIC TO A GIVEN REQUEST
+
+ protected Registry registry = null;
+
+ protected Activity activity = null;
+
+
+// --------------------------------------------------------- Protected Methods
+
+
+ /**
+ * Whether the debug level is set to verbose logging.
+ */
+ protected boolean doDebugLog() {
+
+ return ((servlet.getDebug() > 1));
+
+ }
+
+
+ /**
+ * Whether the debug level is set to listening.
+ */
+ protected boolean doDebugListener() {
+
+ return ((servlet.getDebug() > 2));
+
+ }
+
+
+ /**
+ * Return Activity by ID
+ */
+ protected Activity getActivity(String id) {
+
+ // return (registry.getActivity(id));
+ return this.activity;
+
+ }
+
+
+ /**
+ * Return Activity by looking up ID in mapping.
+ */
+ protected Activity getActivity(ActionMapping mapping) {
+
+ return (getActivity(mapping.getParameter()));
+
+ }
+
+
+ /**
+ * Return context, instantiating it if necessary.
+ */
+ protected WebContext getContext(ActionMapping mapping,
+ HttpServletRequest request, HttpServletResponse response) {
+
+ String contextId = mapping.getParameter();
+ HttpSession session = request.getSession();
+ WebContext context = (WebContext)
+ session.getAttribute(contextId);
+ if (context == null) {
+ if (doDebugLog())
+ servlet.log("{" + session.getId() + "} Creating new Context");
+ context = new WebContext();
+ // context.setActivity(getActivity(contextId));
+ context.setActivity(activity);
+ context.setHttpSession(session);
+ context.setServletContext(servlet.getServletContext());
+ if (doDebugListener())
+ context.addContextListener(this);
+ session.setAttribute(contextId, context);
+ context.call(context.getActivity());
+ }
+ return context;
+
+ }
+
+
+ /**
+ * Validate context, returning errors if found.
+ */
+ protected void validateInit(ActionErrors errors,
+ Context context, Activity activity) {
+
+ if ((context==null) ||
+ (context.getActivity()==null)) {
+ errors.add(ActionErrors.GLOBAL_ERROR,
+ new ActionError("action.missing.parameter"));
+ }
+
+ }
+
+
+ /**
+ * Execute the next stage of the current Activity
+ */
+ protected void executeContext(WebContext context, Activity activity,
+ ActionMapping mapping, ActionForm form,
+ HttpServletRequest request, HttpServletResponse response)
+ throws ServletException {
+
+ synchronized (context) {
+
+ // If we are not already executing our associated Activity, call it
+ if (!activity.equals(context.getActivity())) {
+ if (doDebugLog())
+ servlet.log("{" + request.getSession().getId() +
+ "} calling Activity " +
+ activity.getId());
+ context.call(activity);
+ }
+
+ // Associate our context with the current request and response
+ context.setServletRequest(request);
+ context.setServletResponse(response);
+
+ // Execute our activity until suspended or ended
+ try {
+ if (doDebugLog())
+ servlet.log("{" + context.getHttpSession().getId() +
+ "} executing Activity " +
+ context.getActivity().getId());
+ context.execute();
+ } catch (StepException e) {
+ if (e.getCause() == null)
+ throw new ServletException(e.getMessage(), e);
+ else
+ throw new ServletException(e.getMessage(),
+ e.getCause());
+ }
+ }
+ }
+
+
+ /**
+ * Analyze initialization properties,
+ * and report any errors.
+ */
+ protected void validateContext(ActionErrors errors,
+ Context context) {
+ }
+
+
+ /**
+ * Analyze result, and determine next forward.
+ * <p>
+ * If no errors, forward for id of next step is returned.
+ * <p>
+ * If there are errors, save errors to request, and
+ * forward to input. If there is not input property,
+ * then forward to local or global "errors" forwarding.
+ */
+ protected ActionForward nextForward(ActionMapping mapping,
+ ActionErrors errors, HttpServletRequest request,
+ WebContext context) {
+
+ if (!errors.empty()) {
+
+ // Save for display
+ saveErrors(request,errors);
+
+ // Return to input page, if there is one
+ if (mapping.getInput()!=null)
+ return (new ActionForward(mapping.getInput()));
+
+ // If no input page, use error forwarding
+ return (mapping.findForward("error"));
+ }
+
+ // If no errors, goto forwarding for next step
+ return (mapping.findForward(
+ context.getNextStep().getId()));
+ }
+
+
+// --------------------------------------------------------- Public Properties
+
+
+ /**
+ * Set the Registry for this Action (or application)
+ */
+ public void setRegistry(Registry registry) {
+ this.registry = registry;
+ }
+
+
+
+// --------------------------------------------------------- Public Methods
+
+ /**
+ * Set the controller servlet instance to which we are attached
+ * (if servlet is non-null), or release any allocated resources
+ * (if servlet is null).
+ * Call setRegistry to obtain registry from servlet context.
+ */
+ public void setServlet(ActionServlet servlet) {
+ super.setServlet(servlet);
+
+ if (servlet==null) {
+ setRegistry(null);
+ this.activity = null;
+ }
+ else {
+ setRegistry((Registry)
+ servlet.getServletContext().getAttribute(
+ RegistryServlet.REGISTRY));
+ this.activity = (Activity)
+ servlet.getServletContext().getAttribute(
+ RegistryServlet.ACTIVITY);
+ }
+ }
+
+
+ /**
+ * Retrieve or initialize context from session, using ActionMapping
+ * parameter as key. Returns action.missing.parameters if parameter
+ * missing or not found. Executes the next step of the actitivity.
+ *
+ * @param mapping The ActionMapping used to select this instance
+ * @param form The optional ActionForm bean for this request (if any)
+ * @param request The HTTP request we are processing
+ * @param response The HTTP response we are creating
+ *
+ * @exception IOException if an input/output error occurs
+ * @exception ServletException if a servlet exception occurs
+ */
+ public ActionForward execute(ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception {
+
+ ActionErrors errors = new ActionErrors();
+
+ WebContext context = getContext(mapping,request,
+ response);
+
+ Activity activity = getActivity(mapping);
+
+ validateInit(errors,context,activity);
+
+ if (errors.isEmpty()) {
+
+ executeContext(context,activity,
+ mapping,form,request,response);
+
+ }
+
+ validateContext(errors,context);
+
+ // return (nextForward(mapping,errors,request,context));
+ return null;
+
+ } // end ActionForward
+
+
+ // ------------------------------------------------ ContextListener Methods
+
+
+ /**
+ * Invoked immediately after execution of the related Activity has
+ * been completed normally, been suspended, or been aborted by
+ * the throwing of a StepException. The Step included in this event
+ * will be the last one to be executed.
+ *
+ * @param event The <code>ContextEvent</code> that has occurred
+ */
+ public void afterActivity(ContextEvent event) {
+
+ WebContext context = (WebContext) event.getContext();
+ HttpSession session = context.getHttpSession();
+ StringBuffer sb = new StringBuffer("{");
+ sb.append(session.getId());
+ sb.append("} afterActivity");
+ servlet.log(sb.toString());
+
+ }
+
+
+ /**
+ * Invoked immediately after the specified Step was executed.
+ *
+ * @param event The <code>ContextEvent</code> that has occurred
+ */
+ public void afterStep(ContextEvent event) {
+
+ WebContext context = (WebContext) event.getContext();
+ HttpSession session = context.getHttpSession();
+ StringBuffer sb = new StringBuffer("{");
+ sb.append(session.getId());
+ sb.append("} afterStep ");
+ sb.append(event.getStep());
+ if (context.getSuspend())
+ sb.append(" (Suspended)");
+ if (context.getNextStep() == null)
+ sb.append(" (Finished)");
+ servlet.log(sb.toString());
+ if (event.getException() != null)
+ servlet.log("-->Step threw exception", event.getException());
+
+ }
+
+
+ /**
+ * Invoked immediately before execution of the related Activity has
+ * started. The Step included in this event will be the first one
+ * to be executed.
+ *
+ * @param event The <code>ContextEvent</code> that has occurred
+ */
+ public void beforeActivity(ContextEvent event) {
+
+ WebContext context = (WebContext) event.getContext();
+ HttpSession session = context.getHttpSession();
+ StringBuffer sb = new StringBuffer("{");
+ sb.append(session.getId());
+ sb.append("} beforeActivity");
+ servlet.log(sb.toString());
+
+ }
+
+
+ /**
+ * Invoked immediately before the specified Step is executed.
+ *
+ * @param event The <code>ContextEvent</code> that has occurred
+ */
+ public void beforeStep(ContextEvent event) {
+
+ WebContext context = (WebContext) event.getContext();
+ HttpSession session = context.getHttpSession();
+ StringBuffer sb = new StringBuffer("{");
+ sb.append(session.getId());
+ sb.append("} beforeStep ");
+ sb.append(event.getStep());
+ servlet.log(sb.toString());
+
+ }
+
+
+} // end Activity
diff --git a/struts-sandbox/workflow/RegistryServlet.java b/struts-sandbox/workflow/RegistryServlet.java
new file mode 100644
index 0000000..5db8a8f
--- /dev/null
+++ b/struts-sandbox/workflow/RegistryServlet.java
@@ -0,0 +1,381 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts.action;
+
+
+import java.io.InputStream;
+
+
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServlet;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.workflow.Activity;
+import org.apache.commons.workflow.Context;
+import org.apache.commons.workflow.ContextEvent;
+import org.apache.commons.workflow.ContextListener;
+import org.apache.commons.workflow.Step;
+import org.apache.commons.workflow.StepException;
+import org.apache.commons.workflow.base.BaseRuleSet;
+import org.apache.commons.workflow.core.CoreRuleSet;
+import org.apache.commons.workflow.io.IoRuleSet;
+import org.apache.commons.workflow.web.WebContext;
+import org.apache.commons.workflow.web.WebRuleSet;
+
+import simple.workflow.Registry;
+import simple.workflow.base.BaseRegistry;
+
+
+/**
+ * <p>Demonstration servlet that illustrates one way that workflow support can
+ * be integrated into Struts. This servlet is used to instantiate the Registry
+ * of Activities and expose them to the application. Processing of the Activities
+ * is expected to take place in an <code>Activity</code> Action.</p>
+ *
+ * <p>Note: The functionality of this Servlet could be replaced by the new
+ * ServiceManager.</p>
+ *
+ * <p>Initialization parameters (defaults in square brackets):</p>
+ * <ul>
+ * <li><strong>registry</strong> - Context-relative resource path to the
+ * definition file for the Activities to be initialized by this servlet.</li>
+ * <li><strong>registry-key</strong> - Name of the session attribute under
+ * which the <code>Registry</code> implementation is stored.
+ * [org.apache.commons.workflow.REGISTRY]</li>
+ * <li><strong>context-key</strong> - Name of the session attribute under
+ * which our current <code>Context</code> implementation is stored.
+ * [org.apache.commons.workflow.web.CONTEXT]</li>
+ * <li><strong>debug</strong> - The debugging detail level for this
+ * servlet, which controls how much information is logged. [0]</li>
+ * <li><strong>detail</strong> - The debugging detail level for the Digester
+ * we utilize in <code>initMapping()</code>, which logs to System.out
+ * instead of the servlet log. [0]</li>
+ * </ul>
+ *
+ * @author Craig R. McClanahan
+ * @author Ted Husted
+ * @version $Rev$ $Date$
+ */
+
+
+public class RegistryServlet extends HttpServlet {
+
+
+// ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The Activity for this servlet
+ * //:TODO: TEMPORARY
+ */
+ protected Activity activity = null;
+
+
+ /**
+ * Default Name of the session attribute under which
+ * the current <code>Activity</code> is stored.
+ */
+ public static String ACTIVITY =
+ "org.apache.commons.workflow.ACTIVITY";
+
+
+ /**
+ * Name of the session attribute under
+ * which the <code>Activity</code> is stored.
+ */
+ protected String activityKey = ACTIVITY;
+
+
+ /**
+ * Default Name of the session attribute under which
+ * a current <code>Context</code> is stored.
+ */
+ public static String CONTEXT =
+ "org.apache.commons.workflow.CONTEXT";
+
+
+ /**
+ * Name of the session attribute under
+ * which a current <code>Context</code> is stored.
+ */
+ protected String contextKey = CONTEXT;
+
+
+ /**
+ * The Registry for this servlet
+ */
+ protected Registry registry = null;
+
+
+ /**
+ * Default Name of the application attribute under which
+ * the <code>Registry</code> is stored.
+ */
+ public static String REGISTRY =
+ "org.apache.commons.workflow.REGISTRY";
+
+
+ /**
+ * Name of the session attribute under
+ * which the <code>Registry</code> is stored.
+ */
+ protected String registryKey = REGISTRY;
+
+ /**
+ * Default name for Registry XML document
+ */
+ protected String registryPath = "WEB-INF/workflow.xml";
+
+
+ /**
+ * The debugging detail level for this servlet.
+ */
+ private int debug = 0;
+
+
+
+// --------------------------------------------------------- Public Properties
+
+
+ /**
+ * Set the <code>Activity</code> associated with this instance.
+ *
+ * @param activity The new associated Activity
+ */
+ public void setActivity(Activity activity) {
+
+ this.activity = activity;
+ getServletContext().setAttribute(ACTIVITY,this.activity);
+
+ }
+
+
+ /**
+ * Return the name of the session attribute under which a current
+ * <code>Context</code> is stored.
+ */
+ public String getContextKey() {
+
+ return contextKey;
+
+ }
+
+
+ /**
+ * Set the name of the session attribute under which a current
+ * <code>Context</code> is stored.
+ */
+ protected void setContextKey(String contextKey) {
+
+ this.contextKey = contextKey;
+
+ }
+
+
+ /**
+ * Return Name of the application attribute under which this
+ * servlet is exposed.
+ */
+ public String getRegistryKey() {
+
+ return registryKey;
+
+ }
+
+
+ /**
+ * Set the name of the session attribute under which a current
+ * <code>Registry</code> is stored.
+ */
+ protected void setRegistryKey(String registryKey) {
+
+ this.registryKey = registryKey;
+
+ }
+
+
+ /**
+ * Return the Registry for this servlet
+ */
+ protected Registry getRegistry() {
+
+ return (this.registry);
+
+ }
+
+
+ /**
+ * Set the <code>Registry</code> associated with this instance.
+ * Called by Digester via parse.
+ *
+ * @param regisry The new associated Registry
+ */
+ public void setRegistry(Registry registry) {
+
+ this.registry = registry;
+ initRegistry();
+ getServletContext().setAttribute(
+ getRegistryKey(),getRegistry());
+
+ }
+
+
+
+// --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Perform any optimizations or related tasks on Registry once it is
+ * populated.
+ */
+ protected void initRegistry() {
+
+ synchronized (this.registry) {
+
+ registry.initActivities();
+
+ }
+
+ }
+
+
+ /**
+ * Gracefully shut down any activity instances we have created.
+ */
+ protected void destroyRegistry() {
+
+ synchronized (this.registry) {
+
+ registry.clearActivities();
+
+ }
+
+ }
+
+
+ /**
+ * Perform a graceful shutdown of this servlet instance.
+ */
+ public void destroy() {
+
+ destroyRegistry();
+
+ }
+
+
+ /**
+ * Perform a graceful startup of this servlet instance.
+ *
+ * @exception ServletException if we cannot process the activity
+ * definition file for this activity
+ */
+ public void init() throws ServletException {
+
+ // Record the debugging detail level settings
+ String debug = getServletConfig().getInitParameter("debug");
+ if (debug != null) {
+ try {
+ this.debug = Integer.parseInt(debug);
+ } catch (NumberFormatException e) {
+ throw new UnavailableException
+ ("Debug initialization parameter must be an integer");
+ }
+ }
+
+ // Record the attribute name for our current Context
+ String contextKey = getServletConfig().getInitParameter("context-key");
+ if (contextKey != null)
+ setContextKey(contextKey);
+
+ // Record the attribute name for our current Context
+ String registryKey = getServletConfig().getInitParameter("registry-key");
+ if (registryKey != null)
+ setRegistryKey(registryKey);
+
+ // Parse the activity definition file for our Activity
+ String registryPath = getServletConfig().getInitParameter("registry");
+ if (registryPath != null)
+ this.registryPath = registryPath;
+ parse(this.registryPath);
+
+ // Check result of parse
+ if (activity == null)
+ throw new UnavailableException("No registry defined in resource "
+ + registryPath);
+
+ }
+
+
+ // -------------------------------------------------------- Private Methods
+
+
+ /**
+ * Parse the specified activity definition file for this instance.
+ *
+ * @param path Context-relative resource path of the activity
+ * definition file
+ *
+ * @exception ServletException on any processing error in parsing
+ */
+ private void parse(String path) throws ServletException {
+
+ // Get an input source for the specified path
+ InputStream is =
+ getServletContext().getResourceAsStream(path);
+ if (is == null)
+ throw new UnavailableException("Cannot access resource " +
+ path);
+
+ // Configure a Digester instance to parse our definition file
+ Digester digester = new Digester();
+ digester.setNamespaceAware(true);
+ digester.setValidating(false);
+ digester.push(this);
+
+ // Add rules to recognize the built-in steps that we know about
+ BaseRuleSet brs = new BaseRuleSet();
+ digester.addRuleSet(brs);
+ digester.addRuleSet(new CoreRuleSet());
+ digester.addRuleSet(new IoRuleSet());
+ digester.addRuleSet(new WebRuleSet());
+
+ // Add a rule to register the Activity being created
+ digester.setRuleNamespaceURI(brs.getNamespaceURI());
+ digester.addSetNext("activity", "setActivity",
+ "org.apache.commons.workflow.Activity");
+
+ // Parse the activity definition file
+ try {
+ digester.parse(is);
+ } catch (Throwable t) {
+ log("Cannot parse resource " + path, t);
+ throw new UnavailableException("Cannot parse resource " + path);
+ } finally {
+ try {
+ is.close();
+ } catch (Throwable u) {
+ ;
+ }
+ }
+
+ }
+
+
+}